BotBrowser Proxy Configuration: HTTP and SOCKS5
Set a Puppeteer proxy or a Playwright proxy with --proxy-server, and choose HTTP, HTTPS, SOCKS5, SOCKS5H or QUIC per launch. This page covers the proxy server syntax, credentials, remote DNS with socks5h, and how to confirm the exit IP before a run.
The three common shapes: a Puppeteer proxy passed through
args, a Playwright proxy passed throughlaunch({ proxy })or the sameargs, and a SOCKS5 proxy wheresocks5h://moves DNS to the proxy. Per-context routes are covered in Per-Context Proxy.
A Puppeteer SOCKS5 proxy and a Playwright SOCKS5 proxy are the same --proxy-server=socks5://host:port launch value; the only difference is where the option is passed. Use socks5h:// instead of socks5:// when the proxy should resolve the hostname rather than the local resolver.
Configure HTTP, SOCKS, and QUIC proxies for stable browser identity and network privacy.
Prerequisites
- BotBrowser binary installed on your system. See INSTALLATION.md for platform-specific setup.
- Node.js 18 or later (for Playwright/Puppeteer examples).
- A profile file (
.encfor production,.jsonfor local development). - A proxy server with HTTP, HTTPS, SOCKS5, SOCKS5H, or QUIC proxy support.
Quick Start
Pass your proxy directly in the browser launch arguments using --proxy-server:
import { chromium } from "playwright-core";
const browser = await chromium.launch({
executablePath: process.env.BOTBROWSER_EXEC_PATH,
headless: true,
args: [
`--bot-profile=${process.env.BOT_PROFILE_PATH}`,
"--proxy-server=socks5://user:[email protected]:1080",
],
});
const page = await browser.newPage();
await page.goto("https://example.com");
console.log("Page title:", await page.title());
await browser.close();BotBrowser auto-detects timezone, locale, and language from the proxy exit IP. No additional configuration is needed for geographic consistency.
How It Works
BotBrowser extends the standard --proxy-server flag with two key enhancements:
-
Embedded credentials. Standard browsers require separate authentication. BotBrowser accepts
user:pass@host:portdirectly in the proxy URL, eliminating the need forpage.authenticate()or framework proxy options. -
Automatic geo-detection. When a proxy is configured via
--proxy-server, BotBrowser detects the proxy’s exit IP and configures timezone, locale, and language to match. This happens before the first page loads. See Proxy and Geolocation for the full pipeline.
Supported Protocols
| Protocol | URL Prefix | Description |
|---|---|---|
| HTTP | http:// | Standard HTTP proxy |
| HTTPS | https:// | TLS-encrypted proxy connection |
| SOCKS5 | socks5:// | SOCKS5 proxy with local DNS resolution |
| SOCKS5H | socks5h:// | SOCKS5 proxy with remote DNS resolution (hostname resolution stays within the tunnel) |
| QUIC | quic:// | QUIC proxy with HTTPS tunneling and MASQUE CONNECT-UDP support |
Credential Format
Embed username and password directly in the proxy URL:
protocol://username:password@hostname:portExamples:
# HTTP with credentials
--proxy-server=http://myuser:[email protected]:8080
# SOCKS5 with credentials
--proxy-server=socks5://myuser:[email protected]:1080
# SOCKS5H with credentials (DNS resolved through the proxy)
--proxy-server=socks5h://myuser:[email protected]:1080
# QUIC proxy with credentials
--proxy-server=quic://myuser:[email protected]:443Structured Usernames
Many proxy providers encode routing information in the username using commas or pipes. BotBrowser supports these formats:
--proxy-server=socks5://user_abc,type_mobile,country_GB,session_1234:[email protected]:1080Proxy credentials stay out of operational diagnostics and crash reports. Keep credentials in the profile or launch environment, and do not paste live credentials into public reports.
Common Scenarios
Why use —proxy-server instead of framework proxy options
Always configure the proxy through --proxy-server in the browser launch arguments, not through Playwright’s proxy option or Puppeteer’s page.authenticate().
// Correct: BotBrowser handles proxy and auto-detects geo info
const browser = await chromium.launch({
executablePath: BOTBROWSER_EXEC_PATH,
headless: true,
args: [
`--bot-profile=${BOT_PROFILE_PATH}`,
"--proxy-server=http://user:[email protected]:8080",
],
});
// Avoid: Playwright's built-in proxy skips BotBrowser's geo-detection
const browser = await chromium.launch({
proxy: { server: "http://proxy.example.com:8080" }, // Not recommended
});Using --proxy-server ensures BotBrowser can detect the proxy’s geographic location and configure timezone, locale, and language automatically. Framework proxy options operate at a different layer and do not trigger this detection.
Playwright example with SOCKS5
import { chromium } from "playwright-core";
const browser = await chromium.launch({
executablePath: process.env.BOTBROWSER_EXEC_PATH,
headless: true,
args: [
`--bot-profile=${process.env.BOT_PROFILE_PATH}`,
"--proxy-server=socks5://user:[email protected]:1080",
],
});
const page = await browser.newPage();
await page.addInitScript(() => {
delete window.__playwright__binding__;
delete window.__pwInitScripts;
});
await page.goto("https://example.com");
await browser.close();Puppeteer example with HTTP proxy
const puppeteer = require("puppeteer-core");
const browser = await puppeteer.launch({
executablePath: process.env.BOTBROWSER_EXEC_PATH,
headless: true,
defaultViewport: null,
args: [
`--bot-profile=${process.env.BOT_PROFILE_PATH}`,
"--proxy-server=http://user:[email protected]:8080",
],
});
const page = await browser.newPage();
await page.goto("https://example.com");
await browser.close();Puppeteer or Playwright with a SOCKS5 proxy
Puppeteer’s --proxy-server argument and Playwright’s launch({ proxy }) option are both passed to Chromium, but only the launch argument keeps the credentials, the SOCKS5 remote-DNS choice, and BotBrowser’s geo-detection in one place. Pass the same URL you would use on the command line:
// Puppeteer + SOCKS5: the URL carries the protocol, credentials, host, and port
const browser = await puppeteer.launch({
executablePath: process.env.BOTBROWSER_EXEC_PATH,
headless: true,
args: [
`--bot-profile=${process.env.BOT_PROFILE_PATH}`,
"--proxy-server=socks5://user:[email protected]:1080",
],
});// Playwright + SOCKS5H: hostnames resolve inside the tunnel, not on the local resolver
const browser = await chromium.launch({
executablePath: process.env.BOTBROWSER_EXEC_PATH,
headless: true,
args: [
`--bot-profile=${process.env.BOT_PROFILE_PATH}`,
"--proxy-server=socks5h://user:[email protected]:1080",
],
});| Need | Puppeteer | Playwright | Use in BotBrowser |
|---|---|---|---|
| Proxy URL with credentials | args: ["--proxy-server=..."] | args: ["--proxy-server=..."] | Supported; keep the URL in launch args |
| Username/password prompt | page.authenticate() | launch({ proxy: { username, password } }) | Not needed; geo-detection reads the launch argument instead |
| Remote DNS for SOCKS5 | socks5h:// in the URL | socks5h:// in the URL | Supported; socks5:// resolves locally |
| Headless and headful runs | same flag | same flag | Identical; the proxy layer does not depend on headless |
socks5:// versus socks5h:// is the only difference between the two snippets above. It changes who resolves the hostname, not which port or credentials you use. If a run works in a browser started by hand but fails under Puppeteer, compare the resolved --proxy-server value first: a framework-level proxy object usually strips it back to http://.
Headless browser proxy setup checklist
- Put
--proxy-serverin the launch arguments, not in the framework’s proxy option. - Check the URL format is
protocol://username:password@hostname:portand that reserved characters in the password are percent-encoded. - Choose
socks5h://when DNS must stay inside the tunnel,socks5://when local resolution is acceptable, andhttp://orhttps://when the provider only exposes an HTTP CONNECT endpoint. - Launch once with the proxy and read the exit IP, timezone, and locale from the page before trusting the profile. See Proxy and Geolocation.
Using SOCKS5H for remote DNS resolution
When privacy requires that DNS queries also go through the proxy tunnel, use socks5h://. This prevents DNS queries from leaking to your local resolver.
--proxy-server=socks5h://user:[email protected]:1080With socks5h, the proxy server resolves hostnames, so the target domain name is never visible to your local DNS resolver.
PAC routing and request callback
Use the standard --proxy-pac-url flag when proxy routing should be controlled by a PAC script:
--proxy-pac-url=file:///absolute/path/to/proxy.pacStandard PAC routing works through FindProxyForURL(url, host). Approved ENT Tier3 profiles can also define BotBrowser’s trusted request callback in the same PAC script:
function BotBrowserFindProxyForRequest(url, host, method, headersB64, bodyB64, bodyState) {
if (shExpMatch(url, "https://media.example.test/*")) {
return "SOCKS5 media-user:[email protected]:1080";
}
return "CONTINUE";
}Standard and request-aware PAC routes can include proxy credentials. Approved request callbacks loaded from file: or data: PAC sources can also return RESPONSE <raw_http_response_b64> or RESPONSE_FILE <path> for controlled synthetic responses. Keep PAC sources explicit and controlled. Use PAC auto-detect/WPAD only for standard routing. See PAC-Like Request Callback.
Troubleshooting / FAQ
| Problem | Solution |
|---|---|
| Proxy authentication fails | Verify credentials are embedded in the URL. Do not use page.authenticate(). |
| Puppeteer or Playwright reports a proxy error while a manual launch works | Log the browser arguments; a framework proxy object can replace --proxy-server. Pass the full URL in args. |
| SOCKS5 proxy resolves a hostname the target cannot see | Use socks5h:// so the proxy resolves it inside the tunnel. |
| Timezone does not match proxy location | Use --proxy-server in launch args, not framework proxy options. |
| Special characters in password | URL-encode special characters (e.g., @ becomes %40, # becomes %23). |
| DNS leaking to local resolver | Switch from socks5:// to socks5h:// so DNS resolves through the proxy. |
| Structured username not working | Ensure commas and pipes are in the username portion, not the password. |
| QUIC proxy does not carry HTTP/3 traffic | Confirm the proxy supports MASQUE CONNECT-UDP and that QUIC is not disabled for the browser session. |
Next Steps
- Proxy and Geolocation. How BotBrowser auto-detects geographic signals from your proxy IP.
- Per-Context Proxy. Assign different proxies to different BrowserContexts.
- Dynamic Proxy Switching. Change proxy at runtime without restarting.
- QUIC Proxy Routing. Route HTTPS and HTTP/3 traffic through a
quic://proxy. - PAC-Like Request Callback. Use trusted PAC scripts for routing and enterprise request callback workflows.
- WebRTC Leak Prevention. Protect against IP disclosure through WebRTC.
- DNS Leak Prevention. Prevent DNS queries from leaking outside the proxy tunnel.
- IPv4-Only Proxy Compatibility. Check destination address-family support and tunnel rejections.
- CLI Flags Reference. Complete list of all available flags.
Related documentation: CLI Flags Reference | Advanced Features | Getting Started with Playwright
Legal Disclaimer & Terms of Use • Responsible Use Guidelines. BotBrowser is for authorized fingerprint protection and privacy research only.
Related BotBrowser blog: Browser proxy configuration for SOCKS5 and HTTP