Errors
Errors come back as JSON with an HTTP status code. The status tells you whether to fix the request or simply retry.
Error format
HTTP/1.1 400 Bad Request
Content-Type: application/json
{ "success": false, "error": "header/footer requires a margin large enough to hold them" }
Always check the status code before saving the body: an error response is JSON, not a PDF or an image.
Status codes
| Status | Meaning | What to do | Retry? |
|---|---|---|---|
200 | Success. The body is the file, or JSON with encode / response_type=json. | Nothing. | – |
400 | The request is invalid: a wrong parameter value, both or neither of url and html, a blocked address, an unsupported option, or the page could not be loaded. | Read the error message and fix the request. | No |
401 | The API key is missing or not valid. | Check how the key is sent; see authentication. | No |
402 | Your plan's monthly render allowance is used up. | Wait for the new month (it resets on the 1st, UTC) or move to a larger plan. | No |
404 | The selector matched no element on the page. | Check the selector, or wait for the element with wait_for_selector. | No |
408 | Rendering took longer than the timeout (at most 30 seconds). | Make the page lighter, block ads and trackers, or use wait_until=load instead of networkidle. | Once, maybe |
413 | The request body is larger than 10 MB. | Load large images from URLs instead of embedding them, or compress them. | No |
429 | The render queue is full at this moment. | Wait and retry with backoff. | Yes |
500 | Unexpected error while rendering. | Retry once; if it repeats, write to support with the time of the request. | Once |
502, 503 | The service is restarting or a component is briefly unavailable. | Retry with backoff. | Yes |
Common messages
| Message | Cause |
|---|---|
The source URL points to a blocked or unresolvable address | The address is private, local, a cloud metadata address, or its domain does not resolve. |
Could not load the source: net::ERR_... | The page could not be reached from Jeddah: wrong address, site down, or it refuses the connection. |
The source URL returned HTTP 404 | Only with raise_for_status: the page itself answered with an error. |
header/footer requires a margin ... | A header or footer was sent without margin. |
Not supported: ... never stored | An option that stores the file was sent (webhook, store, s3_destination and similar). |
selector and full_page cannot be combined | Choose one. |
body must be object | The body is not JSON. Send Content-Type: application/json with a JSON object. |
Rendering timed out ... | See 408 above. |
Retrying safely
Render requests have no side effects, so retrying never creates duplicates. Retry 429, 502 and 503 with an increasing wait (for example 2, 4, 8 seconds) and honour a Retry-After header when there is one. Do not retry 4xx errors other than 408 and 429: they will fail again. Ready-made retry loops are in the code examples.