contentcheckfailed

You asked the API to check the page text before capture, with options.fail_if_missing or options.fail_if_contains, and the page did not pass. The API stops and returns this error instead of an image. In most cases this is the check doing its job: it caught a login wall, an error page or a page that had not finished loading. This page is part of the error code reference.

HTTP status 422 Unprocessable Entity
error.type target_error
error.retryable true
Credits used 0

Example responses

The message tells you which list failed and which string caused it. A required string was not found:

{
  "error": {
    "type": "target_error",
    "code": "content_check_failed",
    "message": "Required text not found: 'Dashboard'",
    "retryable": true
  },
  "request_id": "req_abc123"
}

A forbidden string was found:

{
  "error": {
    "type": "target_error",
    "code": "content_check_failed",
    "message": "Forbidden text found: 'Access Denied'",
    "retryable": true
  },
  "request_id": "req_def456"
}

The request that produces them looks like this. Both lists sit under options, as described in content validation:

{
  "url": "https://app.example.com/dashboard",
  "options": {
    "fail_if_missing": ["Dashboard"],
    "fail_if_contains": ["Access Denied", "Sign in"]
  }
}

Common causes

Message Likely cause Fix
Required text not found on some runs only The check ran before the data arrived Wait for an element that appears with the data (wait.for_selector). See wait strategies.
Required text not found on every run The text differs: case, translation, or a copy change on the site Compare with the live page. Matching is case-sensitive. Set browser.locale if the site localizes.
Forbidden text found: 'Sign in' The session cookie expired or was not sent Refresh the cookie. See authenticated pages.
Forbidden text found with a short string such as '404' or 'Error' Partial matching found the string inside normal content, such as a price, an order number or "Error-free" Use longer, more specific strings, for example "Page not found".

Not the same error: fail_on_error reports JavaScript console errors with the code console_error, which is not retryable.

How to handle it

retryable is true because a slow page can pass on the next attempt. Retry once, after a short wait. If the same string fails again, stop: the page itself is in the wrong state, and more retries only add latency.

This Ruby example passes the checks as a Hash (the SDK sends it as the JSON body), retries once, and then raises an error that your job can route to a person:

require 'renderscreenshot'

CLIENT = RenderScreenshot.client(ENV.fetch('RS_API_KEY'), timeout: 90)

class PageNotReady < StandardError; end

def capture_report(url, attempts: 2)
  request = {
    url: url,
    wait: { for_selector: '#report-ready', timeout: 45 },
    options: {
      fail_if_missing: ['Report generated'],
      fail_if_contains: ['Sign in', 'Something went wrong']
    }
  }

  attempts.times do |i|
    return CLIENT.take(request)
  rescue RenderScreenshot::Error => e
    raise unless e.code == 'content_check_failed'

    # The message names the string that failed the check. Log it with the request ID.
    warn "attempt #{i + 1}: #{e.message} (#{e.request_id})"
    sleep 5 if i + 1 < attempts
  end

  raise PageNotReady, "#{url} did not pass the content checks"
end

begin
  File.binwrite('report.png', capture_report(ARGV.fetch(0)))
  puts 'saved report.png'
rescue PageNotReady => e
  warn e.message
  exit 1
end

Use the message for logs and alerts, not for program logic. The code and retryable flag are the stable contract; message wording can change.

Tested on 2026-10-15 with Ruby 4.0.7 and the renderscreenshot gem 1.0.0 against a local mock that returns the envelope above. A failing page produced two logged attempts and exit code 1; a passing page saved the image.

Related in this topic

Was this page helpful?