Skip to main content
Every request goes to https://api.parse.bot. This page is the definitive reference for what each status code means — especially for executing endpoints (POST /scraper/{scraper_id}/{endpoint_name}), where Parse wraps the outcome in a structured envelope so you can tell whose fault a failure is: yours, the target site’s, or the scraper’s.

The execution envelope

A successful call returns the endpoint’s own JSON (the shape described by its return_schema) with HTTP 200:
{ "title": "A Light in the Attic", "price": 51.77, "rating": 3 }
A failed call returns a non-2xx status with an error envelope. The HTTP code tells you the category of failure, and the body carries a machine-readable status plus detail:
{
  "error": {
    "status": "upstream_error",
    "upstream_status_code": 404,
    "message": "The target site returned HTTP 404. See `snippet` for the upstream response body.",
    "snippet": "<html>Product not found</html>",
    "url": "https://example.com/products/invalid-sku"
  },
  "status_code": 502
}
The status field is the most useful signal — it maps 1:1 to the HTTP code:
HTTPstatusWhat it meansWhat to do
200successThe endpoint ran and returned dataUse the body
422stale_inputYour input was invalid, or the resource is gone upstreamFix the input and retry
429Rate limit hit (burst or daily)Honor Retry-After and back off
502upstream_errorThe target site returned a non-2xx responseInspect upstream_status_code + snippet; do not blindly retry
503blockedAnti-bot blocked every proxy we triedRetry later only if retry_after is present
500errorThe scraper crashed or hit a bugRequest a revision of the API
400Malformed request (bad header, missing session creds)Fix the request
401Missing/invalid/expired API keyCheck your key
404Scraper (or pinned version) doesn’t exist or isn’t yoursCheck the scraper_id
502 is not a Parse outage and should not be auto-retried. It means the target site answered the scraper with a non-2xx (e.g. a 404 for an ID that doesn’t exist, a 401 for bad upstream credentials, a transient site 500). Read upstream_status_code and snippet to see what the site actually said before deciding whether to retry.

422 — stale_input (your input is the problem)

The scraper rejected your input before or during the upstream call — wrong type, missing required field, or a resource the site says is gone.
{
  "error": {
    "status": "stale_input",
    "kind": "input_format_invalid",
    "message": "trip_type must be 'one_way' or 'round_trip'",
    "upstream_status_code": 400,
    "url": "https://example.com/api/search"
  },
  "status_code": 422
}
  • kind: "input_format_invalid" — a parameter is malformed. Fix it against the endpoint’s input_params.
  • kind: "input_not_found" — the specific thing you named (a job ID, a product SKU) was confirmed gone by the site (often a 410). Not retryable with the same input.

502 — upstream_error (the target site failed)

The scraper reached the site, but the site returned a non-2xx. The body tells you exactly what came back:
{
  "error": {
    "status": "upstream_error",
    "upstream_status_code": 503,
    "message": "The target site returned HTTP 503. See `snippet` for the upstream response body.",
    "snippet": "Service Unavailable"
  },
  "status_code": 502
}
Decide based on upstream_status_code: a 404/410 usually means your input pointed at nothing (don’t retry); a 5xx from the site may be transient (retry with backoff); a 401/403 may mean the API’s stored credentials need attention (revise the API).

503 — blocked (anti-bot stopped us)

Parse rotated through proxies and every attempt hit the site’s bot protection.
{
  "error": {
    "status": "blocked",
    "block_type": "datadome",
    "vendor": "datadome",
    "kind": "antibot_solvable",
    "attempts": 3,
    "retry_after": 60,
    "message": "Service temporarily unavailable - site protection blocking all proxies"
  },
  "status_code": 503
}
  • retry_after present (and a Retry-After header) → transient; retry after that many seconds.
  • retry_after: null (and no Retry-After header) → kind is antibot_unsolvable or ip_burned; retrying soon won’t help. If it persists, the API may need a revision.

500 — error (the scraper bugged out)

The scraper crashed or detected an internal fault. This is the API’s problem, not yours.
{
  "error": {
    "status": "error",
    "kind": "scraper_bug",
    "message": "The scraper crashed during execution. This could be due to bad input, broken scraper code, or a website update."
  },
  "status_code": 500
}
Fix: revise the API — POST /dispatch/tasks/{task_id}/revise with a description (e.g. “the get_paper endpoint 500s on valid IDs”). If it’s a marketplace/canonical API, the revision improves it for everyone.

429 — rate limited

{
  "error": {
    "error": "Rate limit exceeded",
    "message": "Too many requests in a short burst. Retry in 5s.",
    "limit_type": "burst",
    "retry_after": 5
  },
  "status_code": 429
}
  • limit_type: "burst" — you exceeded the short-term token bucket. retry_after is seconds until the next token.
  • limit_type: "daily" — you hit your daily cap. retry_after is seconds until UTC midnight.
Every execution response carries rate-limit headers so you can pace yourself before getting a 429:
HeaderMeaning
X-RateLimit-RemainingTokens left in the burst bucket
X-RateLimit-ResetUnix time when the next token is available
X-RateLimit-Daily-RemainingRequests left today (tiers with a daily cap)
Retry-AfterSeconds to wait (sent on 429, and on retryable 503)
X-Credits-Charged / X-Credits-RemainingCredits this call cost / your balance
Authenticated login endpoints have a stricter cap (3 attempts/hour per API) — see Authenticated APIs.

400 / 401 / 404 — request problems

  • 400 — a malformed request: an invalid API-Snapshot-Version header, or session_id/encryption_key sent only one of the pair. Body: {"error": "<reason>", "status_code": 400}.
  • 401{"error": "Missing X-API-Key header" | "Invalid API key" | "API key expired", "status_code": 401}. Send a valid pmx_… key in X-API-Key (header name is case-insensitive; the value is not). See Authentication.
  • 404{"error": "Scraper with ID '…' not found", "status_code": 404}. The scraper or pinned version doesn’t exist, or isn’t yours — Parse returns 404 rather than reveal another account’s resource. Use the scraper_id from your completed task’s generated_api.
A bare JSON {"detail":"Not Found"} (note: detail, not error) means the path doesn’t exist, not the scraper. Check you’re calling POST /scraper/{scraper_id}/{endpoint_name} exactly, on https://api.parse.bot.

Build failures (task status: "failed")

A dispatch/revision task can finish failed rather than completed; the task’s error field says why. Retry with a clearer task description, revise it, or — if may_require_auth was true — build it as an Authenticated API from the dashboard.

Still stuck?

  • Confirm the base URL: https://api.parse.bot.
  • Verify your key with a cheap call: GET /dispatch/tasks.
  • Reach out to support from the dashboard — click the chat icon in the bottom-right corner to start a conversation with us. Grab the X-Railway-Request-Id response header from the failing call and include it; it lets us trace your exact request.