Skip to main content
Web scraping requests occasionally fail for transient reasons, like a temporary server hiccup or a dropped connection. The SDK can retry these automatically so you don’t have to write that logic yourself.

Basic usage

Retries are off by default (retries: 0). Pass a retries count to the client constructor to turn them on:
const { ZenRows } = require("zenrows");

const client = new ZenRows("YOUR_ZENROWS_API_KEY", { retries: 2 });

const response = await client.get("https://www.scrapingcourse.com/ecommerce/");
With 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

Enable retries (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

The Node.js SDK retries a narrower set of status codes than some other ZenRows SDKs. Only these trigger a retry:
Status codeMeaning
422Unprocessable Entity
503Service Unavailable
504Gateway Timeout
Network-level errors (a rejected 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.
You aren’t charged for retried attempts that fail. Only successful responses count toward your usage. See the Retry Failed Requests guide for more on how this works.

Handling failures

The SDK treats HTTP error status codes and network-level problems differently. Pick the tab that matches what you’re dealing with:
Even after all retry attempts are exhausted, the SDK resolves with the final Response object. It does not throw for a non-2xx status, matching how native fetch behaves. Always check the response before trusting its content:
const response = await client.get(url, { js_render: true });

if (response.ok) {
  console.log(await response.text());
} else {
  console.log(`Failed after retries: ${response.status} - ${await response.text()}`);
}
Unlike some HTTP libraries, native fetch (and this SDK) has no built-in raise_for_status() equivalent. Throw manually if you want an exception:
const response = await client.get(url);

if (!response.ok) {
  throw new Error(`Request failed with status ${response.status}`);
}

Troubleshooting

  • Response still fails after retries are exhausted: Check response.status and look it up in API Error Codes. Some failures (like an invalid apikey) won’t be fixed by retrying and need a code change instead.
  • A 429 isn’t being retried: This is expected. The Node.js SDK’s retry list only covers 422, 503, and 504, plus network errors. Handle 429 by lowering your concurrency or adding your own backoff, see Concurrency.
  • Retries seem to take a long time: That’s the exponential backoff by design (2^attempt * 1000 ms). Lower retries if 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/catch as shown above.

Pricing

Retried attempts that fail are not billed. Only the final successful response counts. This makes retries effectively free insurance against transient failures:
ConfigurationCost multiplier vs. basic
Basic request1x
js_render: true5x
premium_proxy: true10x
js_render: true + premium_proxy: true25x
404 and 410 responses count as successful and are billed, since the request itself completed correctly.

FAQ (Frequently Asked Questions)

  1. Retries are disabled unless you explicitly pass retries to the constructor.
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.
No. Only successful requests consume your ZenRows balance.

Look up a specific error code

For a full breakdown of ZenRows error codes (like AUTH002 or RESP001) and how to resolve each one, see the API Error Codes reference.