How to Add Authentication Headers to Browserless Screenshot Requests
Authenticate current Browserless screenshot requests with the `token` query parameter, and learn how that differs from logging in to the page being captured.
For the current Browserless Screenshot REST API, pass your Browserless API token as the token query parameter. The request is a POST to your fleet’s /screenshot endpoint with a JSON body. A Content-Type: application/json header tells Browserless how to read that body; it is not the authentication credential. See the Browserless Screenshot API documentation and its connection and fleet URL guidance.
POST https://production-sfo.browserless.io/screenshot?token=YOUR_API_TOKEN
Content-Type: application/json
{"url":"https://example.com/","options":{"fullPage":true,"type":"png"}}
Use the region and host assigned to your account. Keep the real token in an environment variable or secret store, and check the HTTP status before saving the response as an image.
Authenticate to Browserless with cURL
This complete request saves the returned screenshot bytes as a PNG. Replace the example region if your account uses another shared-fleet region, and set BROWSERLESS_TOKEN in your shell or secret manager first.
curl --fail-with-body --silent --show-error \
-X POST "https://production-sfo.browserless.io/screenshot?token=${BROWSERLESS_TOKEN}" \
-H "Content-Type: application/json" \
-H "Cache-Control: no-cache" \
--data '{"url":"https://example.com/","options":{"fullPage":true,"type":"png"}}' \
--output screenshot.png
--fail-with-body makes HTTP errors visible as failures instead of quietly writing an error response into screenshot.png. Avoid shell tracing or printing the expanded URL in logs because the token is in the query string.
Send the request from Python
Install the HTTP client with python -m pip install requests. This script obtains the token from the environment, checks the response status, and writes the image bytes.
import os
import requests
response = requests.post(
"https://production-sfo.browserless.io/screenshot",
params={"token": os.environ["BROWSERLESS_TOKEN"]},
headers={
"Content-Type": "application/json",
"Cache-Control": "no-cache",
},
json={
"url": "https://example.com/",
"options": {"fullPage": True, "type": "png"},
},
timeout=90,
)
response.raise_for_status()
with open("screenshot.png", "wb") as image_file:
image_file.write(response.content)
Using params lets Requests encode the query parameter. The timeout is a client-side limit; choose a value appropriate for the page and your application.
Send the request from Node.js
This example uses the built-in fetch API available in modern Node.js. It constructs the URL safely, checks for an HTTP error, and writes the response bytes to a file.
import { writeFile } from "node:fs/promises";
const token = process.env.BROWSERLESS_TOKEN;
if (!token) throw new Error("Set BROWSERLESS_TOKEN first");
const endpoint = new URL("https://production-sfo.browserless.io/screenshot");
endpoint.searchParams.set("token", token);
const response = await fetch(endpoint, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Cache-Control": "no-cache",
},
body: JSON.stringify({
url: "https://example.com/",
options: { fullPage: true, type: "png" },
}),
signal: AbortSignal.timeout(90_000),
});
if (!response.ok) {
const detail = await response.text();
throw new Error(`Browserless returned HTTP ${response.status}: ${detail}`);
}
await writeFile("screenshot.png", Buffer.from(await response.arrayBuffer()));
What the token authenticates
The token authenticates your caller to Browserless. It does not sign in to the website named by url. Those are separate security boundaries:
| Credential or setting | Purpose |
|---|---|
?token=YOUR_API_TOKEN |
Authenticates the API request to Browserless. |
Content-Type: application/json |
Describes the format of the request body. |
| Target site’s cookie or bearer credential | Would authenticate the browser to the destination website, if supplied through a supported page-auth mechanism. |
The current Screenshot API material documents the Browserless token and screenshot request schema, but the sources reviewed for this guide do not establish that /screenshot forwards arbitrary custom headers to the destination page. Do not put a target site’s cookie or bearer token in the Browserless API Authorization header and assume it will be sent to the page. Check the current endpoint schema for a documented target-auth option; if the endpoint does not support it, use a documented browser workflow that sets page request headers or session state.
Choose the correct Browserless endpoint and request options
For shared fleet, the screenshot URL follows this pattern: https://REGION.browserless.io/screenshot?token=YOUR_TOKEN. The documented shared regions include hosts such as production-sfo, production-lon, and production-ams. Use the region assigned to your account. Private-fleet and enterprise accounts should use their assigned private host; a private-fleet token sent to a shared-fleet URL can result in HTTP 401. See the official connection URL guidance.
The request uses POST, a JSON body, and a page URL. PNG is the default output; the documented options support selecting another image format such as JPEG or WebP. For a full-page capture, set options.fullPage to true. For an element capture, the API documents a top-level selector; for a fixed rectangle, use options.clip. Refer to the current screenshot schema for option names and accepted values.
{
"url": "https://example.com/",
"options": {
"fullPage": true,
"type": "png"
}
}
REST requests are standalone and do not require installing Puppeteer or Playwright client libraries. For a different image type, change the documented screenshot option and save the response with a matching file extension and content handling.
Keep API authentication and page authentication separate
If the Browserless API request succeeds but the screenshot shows a login screen, the Browserless token worked: the rendered destination page still lacks its own session. First verify whether the current /screenshot request schema supports the exact target-site authentication mechanism you need. The sources linked above do not confirm arbitrary target-header forwarding for this route, so avoid relying on undocumented behavior.
For the same reason, a generic Authorization: Bearer … header on the API call is not a substitute for the documented ?token= parameter for this screenshot endpoint. Browserless has older BaaS v1 documentation showing Base64 Basic Authorization, but that version is no longer actively supported and is not the current screenshot REST pattern. See the legacy BaaS guidance and use the endpoint-specific current docs for new screenshot requests.
Troubleshooting authentication and screenshot errors
| Symptom | Likely cause | Fix |
|---|---|---|
| HTTP 401 | Missing or invalid token, wrong fleet host, or private-fleet token sent to a shared host. | Confirm the token is passed as token in the URL, then match the endpoint host to the account’s assigned region or private fleet. |
| HTTP 404 or route error | Wrong URL path, such as omitting /screenshot or calling another API route. |
Use POST https://REGION.browserless.io/screenshot with the query token. |
| Request rejected or body cannot be parsed | The JSON content type is missing, or the body is not valid JSON. | Send Content-Type: application/json and a JSON body containing the page url. |
| An image file contains text or is unreadable | An HTTP error response was saved as if it were an image. | Check the HTTP status before writing the response bytes; use cURL’s --fail-with-body, Requests’ raise_for_status(), or response.ok in Node. |
| Screenshot shows a destination login page | Browserless API authentication succeeded, but the target site has not been authenticated. | Check the endpoint’s documented target-auth support. Do not assume the Browserless API token or its Authorization header is forwarded to the destination. |
| Token appears in logs | Query strings can be captured by request logging, tracing, or error reporting. | Redact the token query value in logs, keep credentials in a secret store, and rotate a token if it has been exposed. |
| Request times out | The page or capture took longer than the client timeout, or the remote page is slow. | Choose a suitable client timeout, inspect the response and target URL, and retry only when the failure is plausibly transient. Avoid rapid retry loops. |
Performance, reliability, and cost considerations
- Keep the request small. Capture only the required page, element, or clip. Full-page screenshots can involve more content and image bytes than a viewport capture.
- Set bounded timeouts. A client timeout prevents a stalled request from hanging your application indefinitely. Handle timeout and HTTP failures explicitly.
- Retry selectively. Retry transient network errors and appropriate server failures with a bounded backoff. Do not retry authentication failures until the token or host configuration is corrected.
- Protect the token in transit and logs. Use HTTPS, environment-backed secrets, and query-string redaction. The endpoint’s documented token location is a query parameter, which may be included in URL logs unless filtered.
- Plan around the service account and usage terms. This guide does not state Browserless prices, quotas, latency, or uptime because those values are not established in the technical sources cited here. Check your current Browserless account and plan for applicable limits and costs.
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. Make one GET request to capture a URL; the API returns an image or PDF. Its API docs cover the available request options.
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://stripe.com \
-o shot.webp
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`ScreenshotNeo returned HTTP ${res.status}`);
await import('node:fs/promises').then(({ writeFile }) => writeFile('shot.webp', Buffer.from(await res.arrayBuffer())));
ScreenshotNeo removes cookie banners, newsletter popups, and chat widgets before capture. Bot checks, blank pages, and failed loads are never billed, and response headers indicate the page verdict and billing status. Its MCP server lets AI agents use take_screenshot, get_page_info, and capture_pdf. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots.
Create a free ScreenshotNeo account to get 1,000 screenshots a month with no card.
FAQ
Does the current Browserless screenshot API use a Bearer token?
For the current /screenshot REST endpoint, use the token query parameter. The older Basic Authorization example belongs to legacy BaaS v1 documentation.
Is Content-Type the authentication header?
No. Content-Type: application/json identifies the POST body’s format. The Browserless credential is the token query parameter.
Can I use the Browserless token to access a private page on another site?
No. It authenticates the request to Browserless. Target-site login requires a separate, endpoint-supported session or authentication mechanism.
Do I need a browser automation library for this REST call?
No. The REST endpoint accepts a standalone HTTP POST, so cURL or a standard HTTP client is sufficient.


