Basic usage
Retries are off by default (retries: 0). Pass a retries count to the client constructor to turn them on:
retries: 2, a failed request is attempted up to 2 additional times (3 attempts total) before the SDK resolves with the last response it received.
When to enable retries
Enableretries (2-3 is a reasonable starting point) whenever you’re running requests at scale or in production, anywhere a transient failure shouldn’t fail your whole job. Leave retries: 0 (the default) for quick one-off scripts or debugging, where you’d rather see the raw failure immediately than wait through automatic retry attempts.
Which failures get retried
| Status code | Meaning |
|---|---|
422 | Unprocessable Entity |
503 | Service Unavailable |
504 | Gateway Timeout |
fetch, like a DNS failure or dropped connection) also trigger a retry. 429 and 500/502 responses are not retried automatically; they’re returned as-is on the first attempt.
Between attempts, the SDK waits using exponential backoff: 2^attempt * 1000 milliseconds, so 1s, then 2s, then 4s, and so on for each subsequent retry.
Handling failures
The SDK treats HTTP error status codes and network-level problems differently. Pick the tab that matches what you’re dealing with:- HTTP error status
- Network-level exceptions
Even after all retry attempts are exhausted, the SDK resolves with the final Unlike some HTTP libraries, native
Response object. It does not throw for a non-2xx status, matching how native fetch behaves. Always check the response before trusting its content:fetch (and this SDK) has no built-in raise_for_status() equivalent. Throw manually if you want an exception:Troubleshooting
- Response still fails after retries are exhausted: Check
response.statusand look it up in API Error Codes. Some failures (like an invalidapikey) won’t be fixed by retrying and need a code change instead. - A
429isn’t being retried: This is expected. The Node.js SDK’s retry list only covers422,503, and504, plus network errors. Handle429by lowering yourconcurrencyor adding your own backoff, see Concurrency. - Retries seem to take a long time: That’s the exponential backoff by design (
2^attempt * 1000ms). Lowerretriesif latency matters more than success rate for your use case. - Getting a rejected promise instead of an error response: That only happens for network-level failures (DNS errors, dropped connections), not HTTP error status codes. Wrap the call in
try/catchas shown above.
Pricing
Retried attempts that fail are not billed. Only the final successful response counts. This makesretries effectively free insurance against transient failures:
| Configuration | Cost multiplier vs. basic |
|---|---|
| Basic request | 1x |
js_render: true | 5x |
premium_proxy: true | 10x |
js_render: true + premium_proxy: true | 25x |
404 and 410 responses count as successful and are billed, since the request itself completed correctly.FAQ (Frequently Asked Questions)
What's the default number of retries?
What's the default number of retries?
- Retries are disabled unless you explicitly pass
retriesto the constructor.
Why doesn't the SDK retry 429 or 500 responses?
Why doesn't the SDK retry 429 or 500 responses?
The current Node.js SDK’s retry list only includes
422, 503, 504, and network errors. This differs from some other ZenRows SDKs, so don’t assume a 429 will be retried automatically here.Am I charged for retried requests that eventually fail?
Am I charged for retried requests that eventually fail?
No. Only successful requests consume your ZenRows balance.
Look up a specific error code
For a full breakdown of ZenRows error codes (likeAUTH002 or RESP001) and how to resolve each one, see the API Error Codes reference.