Errors
Understand API error responses and how to recover from common scraping failures.
ScrapeRouter uses conventional HTTP response codes for API-level failures such as validation, authentication, credits, concurrency, and platform timeouts. A completed scrape attempt returns HTTP 200; target-level failures are represented inside the JSON body via status_code and errors.
HTTP status codes
| Status | Description |
|---|---|
200
|
ScrapeRouter completed the scrape attempt. Inspect JSON status_code and errors for the target result. |
400
|
Bad request - invalid parameters or malformed JSON |
401
|
Unauthorized - missing or invalid API key |
402
|
Payment required - insufficient credits |
429
|
Too many requests - concurrency or rate limit exceeded |
500
|
Internal server error |
504
|
ScrapeRouter processing timed out before a result could be returned |
Scrape result failures
A response like HTTP 200 with JSON status_code: 504 means the ScrapeRouter API completed successfully, but the selected scraper or target request timed out. Client code should treat errors as failure context and should not rely on HTTP status alone.
Error response format
Error responses include an errors array with one or more normalized error objects:
{
"errors": [
{
"code": "authentication_required",
"message": "Authentication credentials were not provided",
"field": null,
"details": null
}
]
}
Payment errors (402) use the same normalized envelope:
{
"errors": [
{
"code": "insufficient_credits",
"message": "Insufficient credits",
"field": null,
"details": null
}
]
}
Validation errors may return multiple field-specific entries in errors:
{
"errors": [
{
"code": "invalid_field",
"message": "Input should be a valid URL, relative URL without a base",
"field": "url",
"details": null
},
{
"code": "invalid_field",
"message": "Scraper 'invalid' not found",
"field": "scraper",
"details": null
}
]
}
Handling errors
import requests
response = requests.post(
"https://www.scraperouter.com/api/v1/scrape/",
headers={"Authorization": "Api-Key {your_api_key}"},
json={"url": "https://example.com", "scraper": "auto"},
)
data = response.json()
if response.status_code == 429:
print("Rate limited, retrying...")
elif not response.ok:
print(f"API error {response.status_code}: {data}")
elif data.get("errors") or not (200 <= (data.get("status_code") or 0) < 400):
print(f"Scrape failed: {data.get('status_code')} {data.get('errors')}")
else:
print(data["content"])
const response = await fetch("https://www.scraperouter.com/api/v1/scrape/", {
method: "POST",
headers: {
"Authorization": "Api-Key {your_api_key}",
"Content-Type": "application/json",
},
body: JSON.stringify({ url: "https://example.com", scraper: "auto" }),
});
const data = await response.json();
if (response.status === 429) {
console.log("Rate limited, retrying...");
} else if (!response.ok) {
console.error(`API error ${response.status}:`, data);
} else if (data.errors?.length || data.status_code < 200 || data.status_code >= 400) {
console.error("Scrape failed:", data.status_code, data.errors);
} else {
console.log(data.content);
}