Reference
Errors
Every error has a stable code, a plain message and a retryable flag. Retry only when it says yes, and wait for the Retry-After header when there is one.
- A failed screenshot is not charged.
- The number of failed screenshots per day is limited: 15 on free credits, 300 after a first payment.
Refused before anything is captured
Nothing was tried, nothing was charged. The body is {"error": {...}}. With invalid_request, details names the parameters to fix.
| Code | HTTP | Retry | What it means |
|---|---|---|---|
invalid_request | 422 | no | The request is not valid. Check the parameters listed in "details". |
unauthorized | 401 | no | Missing or invalid API key. Send it in the "Authorization: Bearer" header. |
account_blocked | 403 | no | Screenshots are paused for this account. Contact support. |
insufficient_credits | 402 | no | Not enough credits for this screenshot. |
rate_limited | 429 | yes | Too many requests. Wait a moment and try again. |
concurrency_limit | 429 | yes | Too many screenshots running at once for this account. Wait for one to finish. |
failure_budget_exceeded | 429 | no | Too many failed screenshots today for this account. Failed screenshots are free, so their number per day is limited. |
spend_limit_reached | 503 | yes | Screenshots are temporarily paused. Try again later. |
url_not_allowed | 422 | no | This URL cannot be captured. Only public http and https pages are allowed. |
domain_blocked | 403 | no | This website cannot be captured with this service. |
domain_busy | 429 | yes | This website is receiving too many screenshots right now. Try again in a minute. |
country_not_available | 422 | no | This country is not available. See GET /v1/countries. |
service_paused | 503 | yes | Screenshots are temporarily paused. Try again later. |
idempotency_conflict | 409 | no | This Idempotency-Key was already used with different parameters. |
not_found | 404 | no | Not found. |
The screenshot was tried and failed
The page was opened, or we tried to. Most of the time the body is the screenshot itself, with status set to failed and its error filled in, so you keep its id.
option_unavailable can also be answered before anything is tried, for example when you ask for a country that is not open to your account. The body is then {"error": {...}}, as in the first table.
| Code | HTTP | Retry | What it means |
|---|---|---|---|
country_not_obtained | 502 | yes | The page could not be loaded from the requested country, so no screenshot was taken. You were not charged. Try again. |
challenge_page | 502 | no | The website showed a bot check instead of the page. We do not bypass bot checks. |
timeout | 504 | yes | The page took too long to load. |
page_too_heavy | 502 | no | The page is too heavy to capture (over the size limit). |
too_many_redirects | 502 | no | The page redirected too many times. |
selector_not_found | 422 | no | No element matches "selector" on this page. |
wait_for_timeout | 422 | no | The "wait_for" element never appeared. |
navigation_failed | 502 | no | The page could not be opened. Check the address. |
image_too_large | 502 | no | The screenshot would be too large. Use a smaller viewport or turn off full_page. |
option_unavailable | 503 | no | One of the requested options is not available right now. |
image_withheld | 502 | no | The page displays the network address used to load it, so the screenshot was not kept. You were not charged. |
engine_busy | 503 | yes | All browsers are busy. Try again in a few seconds. |
canceled | 409 | no | The screenshot was cancelled before it finished. |
internal_error | 500 | yes | Something went wrong on our side. You were not charged. |
What to do with an error
- Read
error.code, not the message: the code is stable, the wording may change. - If
retryableisfalse, change the request before sending it again. - If
retryableistrue, wait forRetry-Afterwhen it is there, then try again with the sameIdempotency-Key. - Stop after a few tries. See Retries and Idempotency-Key.
Through the MCP server
Your AI gets the same message as a plain sentence, followed by the code, for example (code: challenge_page, retryable: no). It can tell you what happened without reading JSON.