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
- Content validation reference for every option and more patterns.
- Content checks guide for login walls and soft 404s.
- Error handling and retries for a retry policy that covers all target errors.