Skip to main content
An error is an HTTP status with a JSON body. Every error body has detail, a sentence you can show or log:
A request whose input is wrong (400) also has message (the same sentence) and errors, which says which field was refused:
A few older answers use error instead of detail, for example a job that can’t be retried. Read detail, then message, then error; the Python SDK does. The examples on this page are real answers from the API.

Status codes

A job that fails is not an HTTP error: creating it answered 201, and its outcome is in its status and error_code (Jobs and results). Two refusals carry amounts in detail: a 402 names the cost needed and your balance (and, when pending or running jobs hold credit, the amount they reserve), and a 400 for a job over its maxTotalChargeUsd names the estimate, the cap and how many results the cap buys.

Examples

Taken from a key whose limit was set to 1 request an hour.

402: not enough credit

When a job is created, its estimated cost is checked against your organization’s balance. The API refuses it with 402 Payment Required if the balance can’t cover the estimate, or if the quoted estimated_cost of pending and running jobs plus its own exceeds 10 times the balance. The job isn’t created: nothing is charged and nothing runs. The body has only detail, in these formats (the amounts are illustrative):
The estimate is the scraper’s rate times the results the job’s limits allow for, counting every target, and at most 50 per target per day on a crawl with a recent date filter (Billing). A smaller limit, a shorter date window or a maxTotalChargeUsd lowers it. To handle it:
  1. Back off for a minute or more if credit is reserved by pending or running jobs, and wait for some to finish.
  2. Add credits (Billing), or lower the job’s limits if its own estimate exceeds the balance.
  3. Retry the same request. No job was created, so the retry is safe.
POST /api/v1/jobs/{id}/retry/ checks credit the same way. To be warned before you run out, subscribe a webhook to account.low_balance.

429: too many requests

Each API key has a request limit per hour (Rate limits). Past it, the API answers 429 with Retry-After: the seconds until a request is allowed again. Wait that long, then retry. The Python SDK does this by itself, up to 3 times.

Retrying safely

  • Retry 429, 500, 502, 503, 504 and network errors with backoff. Don’t retry other 4xx unchanged.
  • Creating a job is not idempotent: if a create request timed out, list your recent jobs (GET /api/v1/jobs/?limit=5) before you send it again, or you may run the job twice.