Skip to main content
By default, ZenRows sends an optimized set of headers to the target site on your behalf. If you need to forward specific headers instead, like a Referer or a session Cookie, pass a headers object as part of the third argument to get or post.
const { ZenRows } = require("zenrows");

const client = new ZenRows("YOUR_ZENROWS_API_KEY");
const url = "https://www.scrapingcourse.com/ecommerce/";

const response = await client.get(url, {}, {
  headers: {
    Referer: "https://www.google.com",
  },
});

console.log(await response.text());

What happens when you pass headers

As soon as you pass a non-empty headers object, the SDK automatically sets custom_headers=true on the request for you, so you don’t need to add that yourself. This enables your custom headers for the target request while ZenRows continues to manage browser-fingerprinting headers automatically.

Headers you can and can’t override

Not every header can be customized. ZenRows always manages browser-fingerprinting headers itself to keep success rates high and avoid anti-bot detection, even when custom_headers is enabled:
HeaderCustomizable?
RefererYes
CookieYes
AuthorizationYes
Most other headersYes, once custom_headers=true is set
User-AgentNo, always managed by ZenRows
Sec-Ch-Ua, Sec-Ch-Ua-Mobile, Sec-Ch-Ua-PlatformNo
Accept-Encoding, Accept-LanguageNo
Sec-Fetch-Mode, Sec-Fetch-Site, Sec-Fetch-User, Sec-Fetch-DestNo
Connection, Upgrade-Insecure-Requests, Cache-ControlNo
Passing a User-Agent (or any other browser-fingerprinting header from the table above) in the headers object has no effect on the request sent to the target site. ZenRows ignores it and keeps using its own managed value to maintain a consistent, realistic browser fingerprint. See Custom Headers in the Universal Scraper API docs for the full explanation.
The SDK does send its own User-Agent (zenrows/<version> node) as part of the HTTP request it makes to ZenRows’ API endpoint. This identifies the request as coming from the Node.js SDK for ZenRows’ own logging, it is not the header ZenRows sends to the target website. If you pass a User-Agent key in headers, it replaces this value on the request to ZenRows’ API, but that still has no bearing on what the target site receives.

Combining with request parameters

The config object and headers are independent arguments, so you can use both together:
const response = await client.get(
  url,
  { premium_proxy: true },
  { headers: { Referer: "https://www.google.com" } },
);
If a request keeps failing after you add custom headers, try removing them first to confirm whether they’re the cause. ZenRows’ defaults are usually the safer starting point.

Troubleshooting

  • Success rate drops after adding custom headers: Remove your custom headers first to confirm whether they’re the cause; ZenRows’ defaults are usually the safer starting point.
  • Header doesn’t seem to reach the target site: Confirm you’re using the headers argument (forwarded to the target) and not accidentally modifying the config object meant for ZenRows itself.
  • Cookies aren’t persisting across requests: Each SDK call is a separate, stateless request. Pass the Cookie header explicitly on every call if you need to maintain a session.
  • custom_headers shows up unexpectedly in requests: This is set automatically whenever you pass a non-empty headers object; it’s not something you need to remove.

Pricing

Custom headers don’t change the cost multiplier on their own. Cost still depends on js_render and premium_proxy:
ConfigurationCost multiplier vs. basic
Basic request1x
js_render: true5x
premium_proxy: true10x
js_render: true + premium_proxy: true25x
See ZenRows Pricing.

FAQ (Frequently Asked Questions)

No. Passing a non-empty headers object to get or post sets custom_headers=true automatically.
No. User-Agent is one of several browser-fingerprinting headers ZenRows always manages for the request to the target, regardless of what you pass in headers. See the table above for the full list.
No. headers is forwarded to the target website, not to ZenRows’ API. ZenRows-specific options belong in the config object (the second argument).