Skip to main content
Every error returns the same JSON shape with a standard HTTP status. There’s one thing to parse, whatever went wrong.
number
The HTTP status, mirrored in the body for convenience.
string
A stable, machine-readable code. Branch on this — the wording of message may change; the code won’t.
string
A human-readable explanation of what went wrong.
Failed calls are free. Because credits are charged only on success, an error never costs you anything — see Credits.

Statuses

The request body didn’t pass validation — a missing url, a non-http scheme, an out-of-range maxAge, or requesting the json format without jsonOptions. Fix the request and retry.
The X-API-Key header is missing, malformed, or revoked. The check runs before any work, so a rejected request never costs credits. See Authentication.
Your workspace doesn’t have enough credits to cover the call. It’s rejected up front, before any work runs, so nothing is charged. Top up and retry.
The resource doesn’t exist — an unknown job, crawl, or batch id — or a cacheOnly scrape found no fresh capture to serve. A cacheOnly miss is expected and never triggers a live fetch; see Caching.
The target site did not respond, so there was nothing to return. This says something about that URL rather than about our service, and retrying it will not change the answer: treat it as a dead address and move on. Nothing was charged.
You’ve sent requests faster than your allowance. Back off and retry after a short delay, ideally with exponential backoff.
The page ran past the 90-second synchronous budget. The fetch keeps going in the background, so the capture usually lands in the cache and an immediate retry returns it quickly. Pages that hit this are almost always behind heavy bot protection. If you would rather not wait at all, send async: true and poll the job instead.
Something went wrong on our side, or the target page couldn’t be delivered within the time budget. These are safe to retry — the failed call wasn’t charged.

Handling errors

Read code to decide what to do, not the HTTP status alone:
  • VALIDATION_ERROR — fix the request; retrying as-is won’t help.
  • UNAUTHORIZED — check the key.
  • INSUFFICIENT_CREDITS — top up, then retry.
  • NOT_FOUND — for cacheOnly, fall back to a live fetch if you want the page.
  • REQUEST_TIMEOUT — retry once; the background fetch usually makes the second call fast. Use async: true if you would rather not wait.
  • UPSTREAM_UNREACHABLE — the site is not answering; do not retry it.
  • TOO_MANY_REQUESTS and 5xx — retry with exponential backoff.
Job-level failure is different from a request error. A crawl or batch returns 200 while individual pages may fail — check each page’s status and error in the job’s pages array, and the job’s own status for failed or cancelled. See Jobs & webhooks.