--- layout: page title: headers permalink: /parameters/headers/ parent: Parameters nav_order: 50 description: >- Add custom HTTP headers when screenshotting a URL. --- # Using headers {: .no_toc } {: .fs-9 } Add custom HTTP headers to a URL screenshot request. {: .fs-6 .fw-300 }
## How it works The `headers` parameter adds custom HTTP headers when the API loads a page from `url`. By default, they are sent only with top-level page navigations to the requested URL's origin. Custom headers are restricted by origin: - The requested URL's origin is always allowed. - Requests to another origin receive the headers only when that exact origin is listed in `additional_header_origins`. - Subrequests for resources like CSS, images, and JavaScript receive the headers only when `include_headers_on_subrequests` is `true`. An origin is the combination of scheme, hostname, and port. For example, `https://example.com`, `http://example.com`, and `https://api.example.com` are different origins. This restriction prevents custom headers from leaking through cross-origin redirects or third-party resources. This parameter is available for URL screenshots. It is not used when rendering HTML/CSS or templates. Common uses include: - Supplying a session `Cookie` for a page you are authorized to access. - Sending an `Authorization` header to a protected application. - Passing a custom header that selects test content or safely bypasses a challenge on a site you control. - Overriding `User-Agent` for a specific render. {% include hint.md title="Protect secrets" text="Avoid exposing long-lived credentials in screenshot requests. Prefer short-lived, narrowly scoped tokens. Never put secrets in a create-and-render URL because URLs can be stored in browser history, access logs, analytics, and referrer data." %} {% include hint.md title="User-Agent behavior" text="User-Agent configures Chrome's browser-level user agent and applies to all requests made by the page. Other custom headers follow the origin restrictions documented here." %} ## Request formats ### JSON For a JSON request, pass `headers` as a flat object whose properties are header names and string values: ```json { "url": "https://example.com/account", "headers": { "Cookie": "session=short-lived-session-value", "X-Preview-Mode": "enabled" } } ``` The object has a maximum depth of one. Nested objects and arrays are not supported. ### Form submission For an `application/x-www-form-urlencoded` form submission, repeat the `headers` field once for each header. Each field uses `name:value`: ```bash curl -X POST https://hcti.io/v1/image \ -u 'UserID:APIKey' \ --data-urlencode 'url=https://example.com/account' \ --data-urlencode 'headers=Cookie:session=short-lived-session-value' \ --data-urlencode 'headers=X-Preview-Mode:enabled' ``` The API splits each entry at the first colon, so a header value can contain additional colons. ### Create-and-render URL For a [signed create-and-render request](/getting-started/create-and-render/), repeat the `headers` query parameter using the same `name:value` format: ```text url=https%3A%2F%2Fexample.com%2Fpreview&headers=X-Preview-Mode%3Aenabled&headers=X-Release%3A2026-07 ``` Every repeated parameter, in its exact order and encoding, must be included when calculating the HMAC token. Use create-and-render headers only for non-sensitive values. The complete header names and values are visible in the URL. ## Header rules and limits - A request can include up to 20 custom headers. - Header names are case-insensitive and must not be repeated. For example, `Authorization` and `authorization` are the same name. - A header name can be up to 512 ASCII characters. Valid HTTP header names use ASCII letters, digits, and the standard header-name punctuation characters. - A header value can be up to 8,192 UTF-8 bytes. - Header values cannot contain control characters other than a horizontal tab. - Hop-by-hop, proxy, forwarding, connection, host, and other infrastructure-controlled headers cannot be overridden. Header names beginning with `Proxy-`, `Sec-`, or `X-Forwarded-` are also restricted. Validation is performed by the API. Invalid, duplicate, restricted, or oversized headers return a request error. ## additional_header_origins {: #additional-header-origins } | Type | Default | Description | |:-----|:--------|:------------| | `Array of strings` | `[]` | Additional exact HTTP or HTTPS origins allowed to receive custom `headers`. | Use `additional_header_origins` when an authorized cross-origin navigation or subrequest also needs the custom headers: ```json { "url": "https://app.example.com/private-report", "headers": { "Authorization": "Bearer short-lived-token" }, "additional_header_origins": [ "https://api.example.com", "https://assets.example.com:8443" ], "include_headers_on_subrequests": true } ``` Each value must be an exact origin in the form `scheme://host[:port]`: - Only `http` and `https` origins are supported. - Paths, queries, fragments, credentials, and wildcards are not allowed. - A trailing `/` is optional. - You can include up to 20 unique origins, each up to 512 UTF-8 bytes. - Equivalent or duplicate origins are ignored. - `headers` must also be present when using `additional_header_origins`. For form and create-and-render requests, repeat the parameter once per origin: ```text additional_header_origins=https%3A%2F%2Fapi.example.com&additional_header_origins=https%3A%2F%2Fassets.example.com%3A8443 ``` Include every repeated value in the exact query string used to calculate a create-and-render HMAC token. ## include_headers_on_subrequests {: #include-headers-on-subrequests } | Type | Default | Description | |:-----|:--------|:------------| | `Boolean` | `false` | Also send custom `headers` with subrequests to the requested URL's origin and any `additional_header_origins`. | Set `include_headers_on_subrequests` to `true` only when subrequests for resources like CSS, images, and JavaScript also require the same headers: ```json { "url": "https://example.com/private-report", "headers": { "Authorization": "Bearer short-lived-token" }, "include_headers_on_subrequests": true } ``` Requests to origins outside the requested URL's origin and `additional_header_origins` never receive the custom headers. Keep `include_headers_on_subrequests` set to `false` when the header is needed only for the main page. For a practical use case, see [Bypassing Cloudflare challenges for sites you control](/guides/debugging/cloudflare-challenges/). {% include code_footer.md version=3 %}