Referer or a session Cookie, set the CustomHeaders field on RequestParameters.
What happens when you set CustomHeaders
As soon asCustomHeaders is non-empty, the SDK automatically sets custom_headers=true as a query parameter 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 whencustom_headers is enabled:
| Header | Customizable? |
|---|---|
Referer | Yes |
Cookie | Yes |
Authorization | Yes |
| Most other headers | Yes, once custom_headers=true is set |
User-Agent | No, always managed by ZenRows |
Sec-Ch-Ua, Sec-Ch-Ua-Mobile, Sec-Ch-Ua-Platform | No |
Accept-Encoding, Accept-Language | No |
Sec-Fetch-Mode, Sec-Fetch-Site, Sec-Fetch-User, Sec-Fetch-Dest | No |
Connection, Upgrade-Insecure-Requests, Cache-Control | No |
The SDK does send its own
User-Agent (zenrows-go/<version>) as part of the HTTP request it makes to ZenRows’ API endpoint. This identifies the request as coming from the Go SDK for ZenRows’ own logging, it is not the header ZenRows sends to the target website.Combining with other parameters
CustomHeaders is just one field on RequestParameters, so it combines naturally with everything else:
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: This is expected per the warning above. Remove
CustomHeadersfirst to confirm whether it’s the cause; ZenRows’ defaults are usually the safer starting point. - Header doesn’t seem to reach the target site: Confirm you’re setting
CustomHeadersonRequestParameters(forwarded to the target), not adding it somewhere else, like a header on the outgoing request to ZenRows’ own API. - Cookies aren’t persisting across requests: Each SDK call is a separate, stateless request. Set the
Cookieheader explicitly inCustomHeaderson every call if you need to maintain a session. custom_headers=trueshows up unexpectedly in logs: This is set automatically wheneverCustomHeadersis non-empty, it’s not something you need to remove.
Pricing
Custom headers don’t change the cost multiplier on their own. Cost still depends onJSRender and UsePremiumProxies:
| Configuration | Cost multiplier vs. basic |
|---|---|
| Basic request | 1x |
JSRender: true | 5x |
UsePremiumProxies: true | 10x |
JSRender: true + UsePremiumProxies: true | 25x |
FAQ (Frequently Asked Questions)
Do I need to set custom_headers myself?
Do I need to set custom_headers myself?
No. Setting a non-empty
CustomHeaders field on RequestParameters sets custom_headers=true automatically.Will my custom headers always be used exactly as sent?
Will my custom headers always be used exactly as sent?
Non-fingerprinting headers like
Referer, Cookie, and Authorization are forwarded exactly as you set them. Browser-fingerprinting headers like User-Agent are never forwarded as sent, ZenRows always manages those regardless of what you pass. This is why overriding headers you can customize can still lower success rates on protected sites, since you lose ZenRows’ tuned defaults for that request.Can I set headers meant for ZenRows itself, like an API version header?
Can I set headers meant for ZenRows itself, like an API version header?
No.
CustomHeaders is forwarded to the target website, not to ZenRows’ API. ZenRows-specific options belong in the other RequestParameters fields, or in CustomParams for anything not yet exposed as a typed field.