Launch Parameters
Launch parameters let you configure the browser environment for every REST API call (/pdf, /screenshot, /content, /scrape, etc.).
For BrowserQL and BaaS v2 launch configuration, see BrowserQL Launch Parameters and BaaS Launch Parameters.
- A Browserless API token from your account dashboard
How to Pass Launch Parameters
As Query String Parameters
Append individual parameters directly to the request URL. This is the simplest approach for toggling a few options:
https://production-sfo.browserless.io/screenshot?token=YOUR_API_TOKEN_HERE&headless=false&stealth=true
As a JSON Launch Payload
For complex configurations, especially when passing Chrome flags, use a single &launch= parameter containing a JSON object. Here's the raw JSON for readability:
{
"headless": false,
"stealth": true,
"args": ["--window-size=1920,1080"]
}
Why you must encode the JSON
JSON contains characters like {, ", and : that have special meaning in URLs. If you pass raw JSON directly in a query string, the server won't parse it correctly. You need to either URL-encode or base64-encode the JSON before sending it.
URL-encoded, the above JSON becomes:
%7B%22headless%22%3Afalse%2C%22stealth%22%3Atrue%2C%22args%22%3A%5B%22--window-size%3D1920%2C1080%22%5D%7D
And the full request URL looks like:
https://production-sfo.browserless.io/screenshot?token=YOUR_API_TOKEN_HERE&launch=%7B%22headless%22%3Afalse%2C%22stealth%22%3Atrue%2C%22args%22%3A%5B%22--window-size%3D1920%2C1080%22%5D%7D
How to encode in code
Most languages handle encoding for you. You just need to pass the JSON string through the right function:
- cURL
- JavaScript
- Python
# Use --data-urlencode to let cURL handle encoding
LAUNCH='{"headless":false,"stealth":true,"args":["--window-size=1920,1080"]}'
curl -X POST \
"https://production-sfo.browserless.io/screenshot?token=YOUR_API_TOKEN_HERE" \
--data-urlencode "launch=$LAUNCH" \
-H 'Content-Type: application/json' \
-d '{"url": "https://example.com"}' \
-o screenshot.png
// URLSearchParams automatically URL-encodes values
const launchOptions = {
headless: false,
stealth: true,
args: ["--window-size=1920,1080"],
};
const params = new URLSearchParams({
token: "YOUR_API_TOKEN_HERE",
launch: JSON.stringify(launchOptions),
});
const url = `https://production-sfo.browserless.io/screenshot?${params}`;
import json
from urllib.parse import urlencode
# urlencode handles URL-encoding the JSON string
launch_options = {
"headless": False,
"stealth": True,
"args": ["--window-size=1920,1080"],
}
params = urlencode({
"token": "YOUR_API_TOKEN_HERE",
"launch": json.dumps(launch_options),
})
url = f"https://production-sfo.browserless.io/screenshot?{params}"
You can also base64-encode the JSON payload and pass it as &launch=<base64string>. This is an alternative to URL-encoding that some developers find easier to work with.
Combining Both Methods
When you use both query parameters and a launch payload in the same request, Browserless merges them. Individual query parameters take precedence.
For example, consider this request (shown unencoded for readability):
/screenshot?token=YOUR_API_TOKEN_HERE&headless=true&launch={"headless":false,"stealth":true}
The effective configuration would be:
{
"headless": true,
"stealth": true
}
The headless=true query parameter overrides the "headless": false inside the launch JSON.
Parameter Reference
Not all parameters are supported by every REST API endpoint. Check the REST API reference to verify which parameters are available for the specific endpoint you're using. The table below lists all available launch parameters:
| Parameter | Description | Default |
|---|---|---|
token | The authorization token for API access. | none |
timeout | Maximum session duration in milliseconds. The session will automatically close after this time to prevent overuse. Defaults to 60000ms. Maximum value depends on your plan (see Session Limits). | 60000 |
proxy | Routes browser traffic through a built-in proxy. Set proxy=residential for the residential pool (6 units/MB) or proxy=datacenter for the cheaper datacenter pool (2 units/MB). Omit to use the host machine's own IP. | none |
proxyCountry | Used with the built-in proxy to specify the exit node's country. Accepts ISO 3166 country codes (e.g., us, gb, de). If omitted, a random location is chosen. | none |
proxyCity | Used with the built-in proxy to specify the exit node's city (e.g., chicago, london). Requires Scale plan (500k+ units). | none |
proxySticky | Used with the built-in proxy to maintain the same proxy IP across a session (when possible). Useful for sites that expect consistent IP usage. | false |
proxyLocaleMatch | Used with the built-in proxy to automatically configure browser locale settings to match the proxy location. Recommended when using proxyCountry to improve stealth by aligning browser language preferences with the geographic region. | false |
proxyPreset | Website-specific proxy preset for the residential network. Use px_gov01 for government websites or px_ipv6 for Google domains (Maps, YouTube, etc.) to ensure optimal proxy vendor selection. | none |
externalProxyServer | External proxy server URL for user-provided proxies. Format: http(s)://[username:password@]host:port. When set, routes requests through this proxy instead of the built-in proxy. Credentials can be included directly in the URL. | none |
blockAds | Enables the built-in ad blocker (powered by uBlock Origin). Helps speed up scripts and reduce noise by blocking ads and trackers. Especially useful for scraping to avoid popups and clutter. Note: may cause some sites to fail to load correctly. | false |
blockAdsInclude | With blockAds=true, loads only the named uBlock Origin rulesets (comma-separated list or JSON array of ruleset ids) instead of all of them, lowering per-launch startup cost under load. Opt-in: omit it and blockAds loads the full extension, unchanged. See the BrowserQL launch parameters page for the recommended set and full ruleset list. | none |
blockConsentModals | Automatically blocks or dismisses cookie/GDPR consent banners. Available in BQL sessions and the /screenshot and /pdf REST APIs. In BQL, toggle it via the IDE or launch JSON. Useful for cleaner scraping by removing overlays. | false |
record | Enables session recording functionality for debugging and monitoring purposes. | false |
replay | Enables session recording for replay. When true, the session is recorded and can be replayed later. | false |
profile | Loads a previously saved authentication profile (cookies, localStorage, IndexedDB) into the session before your code runs. The profile must already exist for this token; create one via POST /profile. | none |
args | Array of Chrome command-line flags to pass at browser launch (e.g. ["--window-size=1280,720", "--lang=en-US"]). See the Chrome Flags section for available flags. | [] |
headless | Runs the browser in headless mode. Set to false to enable headful mode (with a GUI). While the GUI isn't visible in cloud environments, headful mode may help bypass bot detection. Note: it uses more resources. | true |
stealth | Enables stealth mode to reduce automation signals (similar to puppeteer-extra's stealth plugin). Set to true to enable stealth techniques. | false |
slowMo | Adds delays between browser actions to slow down automation. Useful for debugging or bypassing rate limits. Value in milliseconds. | 0 |
ignoreDefaultArgs | Controls which default Puppeteer/Playwright arguments to ignore when launching the browser. Can be a boolean or array of specific arguments to ignore. | false |
acceptInsecureCerts | Accepts insecure certificates during navigation. Useful for testing sites with self-signed certificates or certificate issues. | false |
Restricting ad-block rulesets (blockAdsInclude)
When blockAds=true, Chrome compiles all of uBlock Origin Lite's filter rulesets
on every browser launch. blockAdsInclude loads only the rulesets you specify,
lowering that startup cost under load. It is opt-in — omit it and blockAds=true
loads the full extension, unchanged.
?blockAds=true&blockAdsInclude=ublock-filters,easylist,easyprivacy,pgl,ublock-badware,urlhaus-full
The 6 ids above are the recommended, language-neutral core set (ads + trackers + malware) and lose no meaningful coverage for typical traffic. Add specific locale lists only if you scrape sites in that language. See the BrowserQL launch parameters page for the full ruleset breakdown.
Common Recipes
Scraping a Bot-Protected Site
Combine stealth mode with a proxy and ad blocking to maximize your chances of bypassing bot detection. Use proxy=residential for maximum stealth or proxy=datacenter for lower cost:
curl -X POST \
"https://production-sfo.browserless.io/scrape?token=YOUR_API_TOKEN_HERE&stealth=true&proxy=residential&proxyCountry=us&blockAds=true" \
-H 'Content-Type: application/json' \
-d '{
"url": "https://example.com",
"elements": [{ "selector": "h1" }]
}'
Generating a Clean PDF
Strip ads and cookie banners so your PDFs render cleanly:
curl -X POST \
"https://production-sfo.browserless.io/pdf?token=YOUR_API_TOKEN_HERE&blockAds=true&blockConsentModals=true" \
-H 'Content-Type: application/json' \
-d '{
"url": "https://example.com",
"options": {
"format": "A4",
"printBackground": true
}
}' \
-o clean-output.pdf
Using Your Own Proxy
Route traffic through your own proxy server by passing credentials in the URL:
curl -X POST \
"https://production-sfo.browserless.io/content?token=YOUR_API_TOKEN_HERE&externalProxyServer=http://user:pass@proxy.example.com:8080" \
-H 'Content-Type: application/json' \
-d '{
"url": "https://example.com"
}'
Full Example
A realistic scenario: taking a screenshot of a bot-protected site using stealth mode, a US residential proxy, and ad blocking.
- cURL
- JavaScript
- Python
curl -X POST \
"https://production-sfo.browserless.io/screenshot?token=YOUR_API_TOKEN_HERE&stealth=true&proxy=residential&proxyCountry=us&blockAds=true&blockConsentModals=true" \
-H 'Content-Type: application/json' \
-d '{
"url": "https://example.com",
"options": {
"type": "png",
"fullPage": true
}
}' \
-o screenshot.png
import fs from "fs/promises";
const TOKEN = "YOUR_API_TOKEN_HERE";
const params = new URLSearchParams({
token: TOKEN,
stealth: "true",
proxy: "residential",
proxyCountry: "us",
blockAds: "true",
blockConsentModals: "true",
});
const takeScreenshot = async () => {
const response = await fetch(
`https://production-sfo.browserless.io/screenshot?${params}`,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
url: "https://example.com",
options: {
type: "png",
fullPage: true,
},
}),
}
);
if (!response.ok) {
const text = await response.text();
throw new Error(`HTTP ${response.status}: ${text}`);
}
const buffer = Buffer.from(await response.arrayBuffer());
await fs.writeFile("screenshot.png", buffer);
console.log("Screenshot saved as screenshot.png");
};
takeScreenshot().catch(console.error);
import requests
TOKEN = "YOUR_API_TOKEN_HERE"
params = {
"token": TOKEN,
"stealth": "true",
"proxy": "residential",
"proxyCountry": "us",
"blockAds": "true",
"blockConsentModals": "true",
}
payload = {
"url": "https://example.com",
"options": {
"type": "png",
"fullPage": True,
},
}
response = requests.post(
"https://production-sfo.browserless.io/screenshot",
params=params,
json=payload,
)
response.raise_for_status()
with open("screenshot.png", "wb") as f:
f.write(response.content)
print("Screenshot saved as screenshot.png")
FAQ & Troubleshooting
Why am I getting a 401 Unauthorized error?
Your API token is missing or invalid. Include it as a ?token= query parameter or in the Authorization header. Verify the token in your account dashboard.
My request returns an empty response
The page may not have finished loading. Increase waitForTimeout or use waitForSelector to wait for specific content before extracting data.