> ## Documentation Index
> Fetch the complete documentation index at: https://docs.zenrows.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Custom Headers with the Python SDK

> Send custom headers to the target website through the ZenRows Python SDK.

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`.

```python theme={null} theme={null}
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.

<Warning>
  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).
</Warning>

## 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:

```python theme={null} theme={null}
response = client.get(url, headers={"User-Agent": "MyCustomUserAgent"})
```

## Combining with params

`headers` and `params` are independent arguments, so you can use both together:

```python theme={null} theme={null}
response = client.get(
    url,
    params={"premium_proxy": True},
    headers={"Referer": "https://www.google.com"},
)
```

<Note>
  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.
</Note>

## 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`:

| Configuration                           | Cost multiplier vs. basic |
| --------------------------------------- | ------------------------- |
| Basic request                           | 1x                        |
| `js_render=True`                        | 5x                        |
| `premium_proxy=True`                    | 10x                       |
| `js_render=True` + `premium_proxy=True` | 25x                       |

See [ZenRows Pricing](/first-steps/pricing).

## FAQ (Frequently Asked Questions)

<AccordionGroup>
  <Accordion title="Do I need to set custom_headers myself?">
    No. Passing a non-empty `headers` dictionary to `get`, `post`, or `put` sets `custom_headers=True` automatically.
  </Accordion>

  <Accordion title="Will my custom headers always be used exactly as sent?">
    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.
  </Accordion>

  <Accordion title="Can I set headers meant for ZenRows itself (like an API version header)?">
    No. `headers` is forwarded to the target website, not to ZenRows' API. ZenRows-specific options belong in `params`.
  </Accordion>
</AccordionGroup>
