> ## 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 Go SDK

> Send custom headers to the target website through the ZenRows Go 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, like a `Referer` or a session `Cookie`, set the `CustomHeaders` field on `RequestParameters`.

```go theme={null} theme={null}
package main

import (
    "context"
    "fmt"
    "log"
    "net/http"

    scraperapi "github.com/zenrows/zenrows-go-sdk/service/api"
)

func main() {
    client := scraperapi.NewClient(
        scraperapi.WithAPIKey("YOUR_ZENROWS_API_KEY"),
    )

    response, err := client.Get(
        context.Background(),
        "https://www.scrapingcourse.com/ecommerce/",
        &scraperapi.RequestParameters{
            CustomHeaders: http.Header{
                "Referer": []string{"https://www.google.com"},
            },
        },
    )
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(response.String())
}
```

## What happens when you set CustomHeaders

As soon as `CustomHeaders` 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 when `custom_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                                     |

<Warning>
  Setting a `User-Agent` (or any other browser-fingerprinting header from the table above) in `CustomHeaders` 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](https://docs.zenrows.com/universal-scraper-api/features/headers) in the Universal Scraper API docs for the full explanation.
</Warning>

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

## Combining with other parameters

`CustomHeaders` is just one field on `RequestParameters`, so it combines naturally with everything else:

```go theme={null} theme={null}
response, err := client.Get(
    context.Background(),
    url,
    &scraperapi.RequestParameters{
        UsePremiumProxies: true,
        CustomHeaders: http.Header{
            "Referer": []string{"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 `CustomHeaders` first 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 `CustomHeaders` on `RequestParameters` (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 `Cookie` header explicitly in `CustomHeaders` on every call if you need to maintain a session.
* **`custom_headers=true` shows up unexpectedly in logs**: This is set automatically whenever `CustomHeaders` is 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 on `JSRender` and `UsePremiumProxies`:

| Configuration                                | Cost multiplier vs. basic |
| -------------------------------------------- | ------------------------- |
| Basic request                                | 1x                        |
| `JSRender: true`                             | 5x                        |
| `UsePremiumProxies: true`                    | 10x                       |
| `JSRender: true` + `UsePremiumProxies: true` | 25x                       |

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

## FAQ (Frequently Asked Questions)

<AccordionGroup>
  <Accordion title="Do I need to set custom_headers myself?">
    No. Setting a non-empty `CustomHeaders` field on `RequestParameters` sets `custom_headers=true` automatically.
  </Accordion>

  <Accordion title="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.
  </Accordion>

  <Accordion title="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.
  </Accordion>
</AccordionGroup>
