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
| Code | Meaning | What to do |
|---|---|---|
200 | Success | Read data. Still check data.status_code. |
400 | Bad request | A parameter is missing or invalid. Fix the body. |
401 | Unauthorized | API key missing or invalid. Check the X-API-Key header. |
402 | Payment required | Balance exhausted, monthly quota used up, or direct proxy locked on trial. Check the code field. |
429 | Too many requests | You hit a rate limit. Back off and retry. |
500 | Server error | Transient on our side. Retry with backoff. |
502 | Unlock failed | We could not unlock the target. Try js_rendering or a different proxy country. |
503 | Service unavailable | Maintenance or overload. Retry shortly. |
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"
}
code | HTTP | Meaning |
|---|---|---|
CONCURRENCY_LIMIT | 429 | Too many in-flight requests for your plan. A Retry-After header is included. Lower concurrency or upgrade. See Rate limits. |
MONTHLY_QUOTA_EXCEEDED | 402 | Your subscription's monthly included requests are used up. Upgrade or wait for the reset. |
PROXY_LOCKED | 402 | Direct 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). |
Two layers of status
There are two status codes to watch:
- The HTTP status of the OmniScrape API call (above).
200means we processed your request. - The target site's status, in
data.status_code. You can get HTTP200from us withdata.status_code: 404because 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"])
Recommended retry strategy
- Retry
429,500,502,503with 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 tojs_renderingand 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) 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.