Skip to main content

Errors & Status Codes

When a request fails, success is false and an error field describes what happened. The HTTP status code tells you whether the problem is on your side, our side, or the target's side.

{
"success": false,
"error": "Target returned 403 after solver attempts",
"metadata": { "elapsed_time": 12.4, "solver_used": true }
}

Status codes

CodeMeaningWhat to do
200SuccessRead data. Still check data.status_code.
400Bad requestA parameter is missing or invalid. Fix the body.
401UnauthorizedAPI key missing or invalid. Check the X-API-Key header.
402Payment requiredBalance exhausted, trial expired, monthly quota used up, or direct proxy locked on trial. Check the code field.
429Too many requestsConcurrency limit (CONCURRENCY_LIMIT) or request-rate guard. Back off and retry.
500Server errorTransient on our side. Retry with backoff.
502Unlock failedWe could not unlock the target. Try js_rendering or a different proxy country.
503Service unavailableMaintenance, overload, or queue unavailable. Retry shortly.
504Gateway timeoutScrape job timed out (queue overload or very slow target). Retry with backoff.

Structured error codes

Some 4xx responses include a machine-readable code so you can branch in code without string-matching the message:

{
"success": false,
"error": "Concurrent request limit reached for your plan. Retry shortly.",
"code": "CONCURRENCY_LIMIT"
}
codeHTTPMeaning
CONCURRENCY_LIMIT429Too many in-flight requests for your plan. A Retry-After header is included. Lower concurrency or upgrade. See Rate limits.
MONTHLY_QUOTA_EXCEEDED402Legacy code for hard monthly caps. Current Startup/Growth plans bill overage at PAYG rates once included requests are used — you get a normal insufficient-balance 402 if balance cannot cover overage.
PROXY_LOCKED402Direct proxy access (/v1/proxy/fetch or proxy credential rotation) requires PAYG or an active plan. Trial users should use Web Unlocker or BaaS, or activate PAYG ($5 minimum top-up).
TRIAL_EXPIRED402The 7-day free trial window ended. Top up at least $5 via checkout to continue.
TRIAL_UPGRADE_REQUIRED402Trial accounts cannot switch to PAYG from the plan picker alone — complete a $5 minimum top-up first.
MIN_TOPUP400Checkout amount is below the $5 minimum (or above the $500 maximum).

Some 429 responses have no code field — e.g. "Rate limit exceeded. Please slow down." when you send requests faster than the per-account request-rate guard (~20 req/s). Back off briefly and retry. See Rate limits.

Two layers of status

There are two status codes to watch:

  1. The HTTP status of the OmniScrape API call (above). 200 means we processed your request.
  2. The target site's status, in data.status_code. You can get HTTP 200 from us with data.status_code: 404 because the page itself returned 404.
r = resp.json()
if not r["success"]:
handle_api_error(r["error"])
elif r["data"]["status_code"] >= 400:
handle_target_error(r["data"]["status_code"])
else:
use(r["data"]["content"])
  • Retry 429, 500, 502, 503, 504 with exponential backoff (e.g. 1s, 2s, 4s, 8s).
  • Do not retry 400, 401, 402 — the request will keep failing until you fix it.
  • For stubborn 502s, escalate the mode to js_rendering and switch proxy country.
import time, requests

def scrape_with_retry(payload, headers, attempts=4):
for i in range(attempts):
r = requests.post(
"https://api.omniscrape.io/v1/scrape",
headers=headers, json=payload, timeout=120,
)
if r.status_code in (429, 500, 502, 503, 504) and i < attempts - 1:
time.sleep(2 ** i)
continue
return r.json()

Billing on failure

Failed core unlock requests are not billed. If success is false, expect billing.charged to be 0.