ScreenshotNeo

BlogHow-to

How to Add Custom Headers to Website Screenshot Requests

Pass Authorization, API key, and other custom headers to the page a screenshot browser loads. Learn the GET and POST patterns, secure credentials, and fix common failures.

By the ScreenshotNeo team29 September 202612 min read

How to Add Custom Headers to Website Screenshot Requests

To add a custom header to a website screenshot, pass it as a rendering option to the screenshot provider. The provider’s browser must send the header when it requests the target page; adding Authorization to your own request to the screenshot API usually authenticates only that API call and does not forward it to the target website. Header option names, encoding, and supported behavior differ by provider, so use the provider’s current API contract.

This guide shows ScreenshotOne’s documented repeated headers query option and JSON POST pattern, plus a Browserless request example. It also covers authentication, multiple headers, redirects, cookies, security, diagnostics, and when to use a managed API such as ScreenshotNeo.

1. Understand which request gets the header

There are usually two separate HTTP requests in a screenshot workflow:

The screenshot API call and the browser’s request to the target page are separate; configure target headers for the browser request.
The screenshot API call and the browser’s request to the target page are separate; configure target headers for the browser request.
  1. Your application calls the screenshot service. This request may carry the service API key or token.
  2. The screenshot service launches a browser that requests the target page. This is where target-specific headers such as Authorization, X-API-Key, or X-Tenant-ID need to be configured.

A header on step one is not automatically copied to step two. Configure target headers in the provider’s documented screenshot options. Keep the screenshot service credential distinct from the target-site credential, even if both happen to be called an API key.

Credential or header Sent to Purpose
Screenshot service access key or token Screenshot provider Authorizes use of the capture API
Authorization: Bearer … Target page/browser request Authenticates the browser with the website
X-API-Key: … Target page/browser request Authenticates with a target service that expects this header

2. ScreenshotOne: pass one or more custom headers

ScreenshotOne documents a headers option in the form Header-Name:Header-Value. Multiple headers can be sent by repeating the headers query parameter. Its authenticated-pages guide documents both an Authorization header and an X-API-Key header. [Authenticated pages; Options reference]

For example, this request sends a bearer credential and a request ID to the browser that loads the target URL. URL-encode the header values and target URL, especially when they contain spaces, ampersands, plus signs, or other reserved characters.

https://api.screenshotone.com/take?access_key=ACCESS_KEY&url=https%3A%2F%2Fexample.com&headers=Authorization%3A%20Bearer%20TOKEN&headers=X-Request-ID%3A%20123

Equivalent header settings in a request builder can be easier to read and less error-prone than concatenating a URL manually:

headers = [
  "Authorization: Bearer TOKEN",
  "X-Request-ID: 123"
]

Pass the list using the provider’s documented syntax for your client. ScreenshotOne documents that explicitly supplied headers can override values implicitly set by options such as cookies or authorization. Avoid configuring the same credential in multiple places unless you have checked which value takes precedence. [ScreenshotOne options]

cURL with repeated query parameters

curl -G builds a GET request. Use --data-urlencode for every value so shell characters and header content are encoded correctly. The -o option saves the returned image bytes instead of printing them to the terminal.

curl -G 'https://api.screenshotone.com/take' \
  --data-urlencode 'access_key=ACCESS_KEY' \
  --data-urlencode 'url=https://example.com/account' \
  --data-urlencode 'headers=Authorization: Bearer TOKEN' \
  --data-urlencode 'headers=X-Request-ID: 123' \
  -o screenshot.png

Replace ACCESS_KEY and TOKEN with credentials supplied through a secret manager or environment variables in real deployments. The illustrative placeholders above are not usable credentials.

Python with requests

When a client library accepts query parameters as a sequence of pairs, repeated names are preserved. That matters here: a dictionary cannot represent two entries with the same key.

import os
import requests

params = [
    ("access_key", os.environ["SCREENSHOTONE_ACCESS_KEY"]),
    ("url", "https://example.com/account"),
    ("headers", f"Authorization: Bearer {os.environ['TARGET_TOKEN']}"),
    ("headers", "X-Request-ID: 123"),
]

response = requests.get(
    "https://api.screenshotone.com/take",
    params=params,
    timeout=90,
)
response.raise_for_status()

with open("screenshot.png", "wb") as image_file:
    image_file.write(response.content)

Install the client with python -m pip install requests. Before writing output, production code can also inspect the response content type and handle provider error responses according to its API contract.

Node.js with fetch

URLSearchParams supports repeated keys with append. Do not put two headers into one value separated by a comma unless the provider explicitly documents that form.

const params = new URLSearchParams();
params.append('access_key', process.env.SCREENSHOTONE_ACCESS_KEY);
params.append('url', 'https://example.com/account');
params.append('headers', `Authorization: Bearer ${process.env.TARGET_TOKEN}`);
params.append('headers', 'X-Request-ID: 123');

const response = await fetch(
  `https://api.screenshotone.com/take?${params.toString()}`,
  { signal: AbortSignal.timeout(90000) }
);

if (!response.ok) {
  throw new Error(`Screenshot request failed: ${response.status} ${await response.text()}`);
}

const image = Buffer.from(await response.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('screenshot.png', image));

This uses a Node.js runtime with global fetch, AbortSignal.timeout, and environment variables available. Use a runtime-supported timeout mechanism if your Node version does not provide AbortSignal.timeout.

3. Use POST JSON for long or sensitive inputs

GET requests are convenient, but their query strings can become long when you include HTML, Markdown, many options, or bulky header values. Query strings may also be recorded in proxy logs, server access logs, monitoring systems, or browser history. ScreenshotOne documents POST with JSON to https://api.screenshotone.com/take, with Content-Type: application/json, and a maximum POST body size of 100 MiB. [ScreenshotOne documentation]

Use the provider’s documented JSON representation for header options. The following illustrates the POST transport and target URL; confirm the exact options schema against the current API reference before shipping.

curl 'https://api.screenshotone.com/take' \
  -X POST \
  -H 'Content-Type: application/json' \
  --data '{
    "access_key": "ACCESS_KEY",
    "url": "https://example.com/account",
    "headers": [
      "Authorization: Bearer TOKEN",
      "X-Request-ID: 123"
    ]
  }' \
  -o screenshot.png

POST keeps these values out of the URL, but it does not make them invisible: the request body still contains secrets and must be protected in application logs, tracing, and error reporting. Use HTTPS and limit access to logs that may capture request bodies.

4. Authenticate to the target page correctly

First identify how the target website authenticates a normal browser request. Use the same mechanism for the screenshot browser where supported:

Send only the target’s required credential, and keep it out of public URLs and logs.
Send only the target’s required credential, and keep it out of public URLs and logs.
  • Bearer token: pass Authorization: Bearer … as a target header when the site expects bearer authentication.
  • API key: pass the exact header name and value required by the site, for example X-API-Key: …. Header names are generally case-insensitive in HTTP, but use the documented spelling.
  • Session cookie: use the provider’s cookie option when the site authenticates through browser cookies. Do not assume an API key can substitute for a session cookie.
  • Basic authentication or another scheme: match the target’s documented scheme and ensure any special characters are encoded according to the provider’s option format.

ScreenshotOne documents both a header form and an equivalent authorization=Bearer … option for authenticated pages, as well as cookies for sites that use cookie-based authentication. Its options reference says custom headers may take precedence over headers implicitly configured by cookie or authorization options. [Authenticated pages; Options reference]

A successful API response does not prove the target page was authenticated. Check the resulting image for a login screen, access-denied message, or content belonging to a different account. Ensure the token has only the permissions needed to view the target content, and rotate it if it is exposed.

5. Browserless alternative: configure a POST screenshot request

Browserless documents a REST POST /screenshot endpoint. Its service token is passed as a query parameter; the JSON body contains a target url and an options object. The output can be PNG, JPEG, or WebP according to the selected type. The example below follows the documented request shape for a full-page PNG. [Browserless screenshot API]

curl -X POST 'https://production-sfo.browserless.io/screenshot?token=YOUR_API_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"url":"https://example.com/","options":{"fullPage":true,"type":"png"}}' \
  --output screenshot.png

Do not assume that a provider’s own REST token configures authentication to the destination page. Confirm the Browserless documentation for the specific mechanism and version you use to set target browser request headers. Browserless also documents launch parameters for its REST browser environment; validate endpoint, option names, supported output, and limits against its current docs before adopting them. [Screenshot REST API; Browserless documentation]

6. Handle multiple headers, encoding, and redirects

Repeated parameters are different from comma-separated text

If the service contract says to repeat headers, encode each header as its own parameter. These are not necessarily equivalent:

headers=Authorization%3A%20Bearer%20TOKEN&headers=X-Request-ID%3A%20123

One value such as headers=Authorization: Bearer TOKEN, X-Request-ID: 123 may be treated as a single malformed header. Use a sequence of pairs in Python or append in JavaScript to preserve duplicates.

Encode values once

When building a URL yourself, encode spaces and reserved characters in the target URL and header values. Prefer a URL builder or the client’s parameter-encoding feature over hand-encoding. Do not encode an already encoded value a second time; double encoding can cause the target to receive literal percent sequences.

Check redirects and host boundaries

An authenticated URL may redirect to a different hostname, sign-in page, or canonical path. Whether custom authorization headers are retained across a redirect depends on browser and provider behavior, and forwarding a credential to another host can be unsafe. Avoid relying on cross-host redirects for authenticated captures. If possible, request the final page URL directly and use a narrowly scoped credential. Inspect the final screenshot and provider response details for evidence of a redirect or login page.

Use the right request method

Adding headers does not change the target page’s navigation method: screenshot tools generally navigate to a URL, which is usually a GET. If the page requires a POST body to render, check whether the provider supports that workflow; do not assume a screenshot API’s own POST means the browser will POST to the target.

7. Keep access keys and target credentials private

  • Store service keys and target credentials in environment variables or a secrets manager, not source control.
  • Do not publish unsigned screenshot URLs containing keys or target tokens. Anyone who can read a URL may be able to use its credentials while they remain valid.
  • Redact Authorization, cookies, and API-key values from request logs, exception messages, analytics, and support tickets.
  • Use credentials scoped to the smallest set of pages and permissions necessary; expire or rotate them under your organization’s credential policy.
  • Do not put confidential authenticated-page screenshots in public storage or public caches.

ScreenshotOne’s docs recommend environment variables or a secrets manager for keys and caution against public unsigned URLs that expose them. Treat target-page credentials with the same care. [ScreenshotOne documentation]

8. Troubleshooting custom-header screenshot requests

Symptom Likely cause What to check or change
Screenshot shows a login page Header is configured on the client-to-provider request, not as a target render option; wrong token or auth scheme Use the provider’s target-header option. Compare the scheme and scope with a working browser or API request.
Only one of several headers arrives Repeated query keys collapsed into a map or one comma-separated value Use repeated parameters, a sequence of pairs, or the provider’s documented JSON array/object form.
Provider reports missing or invalid option Wrong parameter name, unsupported POST shape, or malformed header expression Check the current API contract; encode values with a URL builder and test with one simple header first.
Target returns 401 or 403 content Expired credential, insufficient scope, wrong host, IP policy, or endpoint-specific auth rules Verify the same credential against the target’s documented flow and confirm the screenshot browser reaches the expected host.
Header appears corrupted Spaces or reserved characters were not encoded, or a value was encoded twice Let the HTTP client serialize query parameters; inspect a redacted request representation.
Works without redirect but fails with redirect Redirect changes hostname, path, or auth requirements Capture the final URL directly where possible; avoid depending on cross-host credential forwarding.
Screenshot is an error page or blank Target load failure, bot protection, JavaScript error, or capture timing issue Check the URL in a normal browser, wait for the needed selector or content, and review the provider’s response/error metadata.
Request times out Slow target, blocking resource, or timeout shorter than page readiness Set a suitable client timeout, use the provider’s supported wait controls, and avoid retrying immediately without bounds.
Image file contains text or JSON instead of an image Provider returned an API error body with a non-success status Check HTTP status and content type before saving the body as an image; log a redacted error.

9. Performance, reliability, and cost considerations

Keep the capture focused

Authenticated pages may load dashboards, analytics, and large media. Capture only the URL and page region required by the job, and use provider-supported wait behavior appropriate to that page. Waiting for every network connection to become idle can be unreliable on pages with streaming or long-polling requests; a page-specific selector or bounded delay may be more predictable if the provider supports it.

Retry only transient failures

Do not retry every status or screenshot blindly. Invalid credentials and malformed options will not improve with repeated attempts. For transient network or provider failures, use a small bounded retry policy with backoff, and avoid launching duplicate captures when the first request may still be running. Confirm provider-specific rate limits and asynchronous job semantics in its current documentation.

Protect output and control retention

A screenshot of an authenticated page can contain personal, financial, or internal data. Apply the same access controls and retention rules as the source page. Check whether the provider or your own systems cache captures, how long artifacts and logs persist, and whether repeated capture can safely reuse an existing result. Do not infer provider caching or billing behavior without checking its published plan and API terms.

Estimate cost from capture volume and options

Before production, estimate monthly captures, likely retries, and any batch or asynchronous workflow charges. Verify current rates, quotas, limits, and whether failed captures or cache hits are billed for the provider you choose. A per-request price alone does not include engineering time spent on browser setup, credential rotation, retries, storage, and monitoring.

10. Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. Its GET endpoint takes a URL and returns PNG, JPEG, WebP, or PDF. The call below captures the example page as WebP:

curl -G "https://api.screenshotneo.com/v1/shot" \
  -d access_key=YOUR_API_KEY \
  --data-urlencode url=https://example.com/account \
  -o shot.webp

See the ScreenshotNeo documentation for the API options. Custom headers, cookies, and Authorization are supported, alongside controls such as viewport, full-page capture, wait conditions, and output format. Cookie and consent banners, newsletter popups, and chat widgets are removed before the shot; each cleanup step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers report the page verdict and billing status. An MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.

The Free plan includes 1,000 shots per month with no card. Paid plans start at $5 for 3,000 shots; all features are on every plan. Sign up for 1,000 free screenshots a month, with no card required.

11. Frequently asked questions

Does adding a header to my API call authenticate the page?

Usually not. It may authenticate you to the screenshot provider. Configure the header in the provider’s browser-rendering options so it is sent to the target page.

Use both only if the target requires them and the provider supports them. Check precedence rules: ScreenshotOne documents that explicit headers can override values set through cookies or its authorization option.

Should I use GET or POST?

Use GET for concise requests when the provider supports it. Use the documented POST JSON form for larger payloads or to keep values out of the URL, while still protecting request bodies and logs.

Why does my local browser work while the capture fails?

Your browser may have a session cookie, network access, or a logged-in state that the screenshot browser does not. Pass the required supported credential explicitly and check redirects, host access, and the final captured page.

12. Before shipping: a short checklist

  • Confirm the header option and encoding in the provider’s current documentation.
  • Verify that the credential is for the target page and is configured as a rendering option.
  • Preserve repeated headers correctly in your HTTP client.
  • Test authenticated content, redirects, and error responses without exposing secret values.
  • Check status and response content type before treating bytes as an image.
  • Set bounded timeouts and retries; review current rate limits, pricing, and retention.
  • Keep service keys and target credentials out of URLs, source control, and public logs.