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 (a Referer, a custom User-Agent, a cookie), pass a headers dictionary to get, post, or put.
from zenrows import ZenRowsClient

client = ZenRowsClient("YOUR_ZENROWS_API_KEY")
url = "https://www.scrapingcourse.com/ecommerce/"

response = client.get(url, headers={
    "Referer": "https://www.google.com",
    "User-Agent": "MyCustomUserAgent",
})

print(response.text)

What happens when you pass headers

As soon as you pass a headers argument, the SDK automatically sets custom_headers=True in the request params for you, so you don’t need to add that yourself. This tells ZenRows to use your headers for the target request instead of its own defaults.
Sending custom headers overwrites ZenRows’ own optimized defaults for that request. This can reduce success rates on sites with strong anti-bot protection, since ZenRows’ default headers are tuned to look like real browser traffic. Only override headers when you have a specific reason to (for example, a required Referer or session cookie).

Overriding the default User-Agent

The SDK sends its own User-Agent (zenrows/<version> python) on every request so ZenRows can identify SDK traffic. If you include a User-Agent key in your headers dictionary, it replaces this default:
response = client.get(url, headers={"User-Agent": "MyCustomUserAgent"})

Combining with params

headers and params are independent arguments, so you can use both together:
response = client.get(
    url,
    params={"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: This is expected per the warning above. 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 SDK’s headers argument (forwarded to the target) and not accidentally modifying request options meant for ZenRows itself, like params.
  • 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 logs/requests: This is set automatically whenever you pass a non-empty headers dictionary; 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 dictionary to get, post, or put sets custom_headers=True automatically.
Yes, ZenRows forwards them to the target as provided. This is precisely why overriding them can lower success rates on protected sites; you lose ZenRows’ tuned defaults.
No. headers is forwarded to the target website, not to ZenRows’ API. ZenRows-specific options belong in params.