The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Set the proxy at the layer that creates the browser session. With a hosted Browserless endpoint, add your proxy as the externalProxyServer query parameter. With native Playwright, pass server, username, and password to browser.newContext(). With self-hosted Browserless, add Chromium’s --proxy-server flag to the WebSocket URL. The scope matters: a launch-level proxy and a context-level proxy are not interchangeable, especially when using Chrome DevTools Protocol (CDP).
This guide shows the complete patterns, authenticated credentials, geographic and sticky-session options, verification steps, failure recovery, and the operational trade-offs of residential, datacenter, hosted, and self-hosted proxies.
Choose the proxy scope before writing code
A proxy can be applied when the remote browser launches or when an individual browser context is created. Those scopes determine which pages share an egress IP and which contexts can use different proxies.
| Connection or deployment | Where to configure the proxy | Important behavior |
|---|---|---|
| Browserless hosted API | externalProxyServer query parameter |
Works in both native Playwright and CDP connection modes; third-party proxy use requires a paid cloud-unit plan. Free plans reject it with HTTP 401. |
| Native Playwright connection | browser.newContext({ proxy: ... }) |
Each context can have its own proxy and credentials. |
| Playwright over CDP | Launch/query settings, or the default context | The default context carries launch-level settings. A newly created context does not inherit those settings. |
| Self-hosted Browserless Docker | Chromium --proxy-server flag in the WebSocket URL |
Browserless does not bundle a proxy server; you supply and operate one. |
Use a URL in the form http://[username:password@]host:port or https://[username:password@]host:port. If a username or password contains @, :, /, ?, #, or another reserved character, percent-encode it before placing it in a connection URL.
Browserless hosted API: pass an external proxy
Browserless documents externalProxyServer for routing a session through a proxy you provide. The complete WebSocket pattern is:
#1 Best Overall
wss://production-sfo.browserless.io?token=YOUR_TOKEN&externalProxyServer=http%3A%2F%2Fuser%3Apass%40proxy.example.com%3A8080
The value after externalProxyServer= is URL-encoded. In decoded form it is http://user:[email protected]:8080. Build this string programmatically rather than concatenating unescaped credentials:
const proxy = 'http://user:[email protected]:8080';
const endpoint = 'wss://production-sfo.browserless.io?token=' +
encodeURIComponent('YOUR_TOKEN') +
'&externalProxyServer=' + encodeURIComponent(proxy);
Omit the proxy parameter when you want direct egress through the host’s own IP. Browserless states that third-party proxy use is available on paid cloud-unit plans; a free plan returns 401 for this option.
Playwright: configure an authenticated proxy
Native Playwright connection
For a native Playwright connection, create the context with the proxy object. This keeps the proxy at context scope, so separate contexts can use different egress routes.
import { chromium } from "playwright-core";
const browser = await chromium.connectOverCDP(
"wss://production-sfo.browserless.io?token=YOUR_TOKEN"
);
const context = await browser.newContext({
proxy: {
server: "http://proxy.example.com:8080",
username: "username",
password: "password"
}
});
const page = await context.newPage();
await page.goto("https://example.com", { waitUntil: "domcontentloaded" });
console.log(await page.title());
await browser.close();
The server value contains the scheme, host, and port. Keep credentials in environment variables or a secret manager in production; do not commit them to source control or print the full connection URL in logs.
Rank #2
- Used Book in Good Condition
CDP inheritance gotcha
The example above uses Browserless’s CDP endpoint, but CDP has a significant scope rule: Browserless opens a default context that carries launch-level settings. If you need that launch-level proxy, use the existing default context instead of creating a new one:
const browser = await chromium.connectOverCDP(
"wss://production-sfo.browserless.io?token=YOUR_TOKEN&externalProxyServer=http%3A%2F%2Fuser%3Apass%40proxy.example.com%3A8080"
);
const defaultContext = browser.contexts()[0];
const page = await defaultContext.newPage();
await page.goto("https://example.com");
A newly created CDP context may bypass the launch-level proxy. Native Playwright connections support multiple independent contexts with context-level proxy settings; CDP is Chromium-only and exposes the default-context behavior described above.
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallPuppeteer: use the connection or Chromium flags
Hosted Browserless connection
Pass the same Browserless query parameter through Puppeteer’s WebSocket connection:
import puppeteer from "puppeteer-core";
const browser = await puppeteer.connect({
browserWSEndpoint:
"wss://production-sfo.browserless.io?token=YOUR_TOKEN&externalProxyServer=http%3A%2F%2Fuser%3Apass%40proxy.example.com%3A8080"
});
const page = await browser.newPage();
await page.goto("https://example.com", { waitUntil: "domcontentloaded" });
console.log(await page.title());
await browser.close();
Environment variables are not a universal browser proxy
Puppeteer’s configuration guide lists HTTP_PROXY, HTTPS_PROXY, and NO_PROXY for downloading and running the browser. Those variables do not automatically configure every page request, and puppeteer-core ignores Puppeteer configuration files and environment variables. For a remote Browserless session, use the connection/query setting or the provider’s launch configuration explicitly.
Rank #3
Self-hosted Browserless Docker
The open-source deployment does not include a proxy service. Supply your own proxy and pass Chromium’s flag for the session. Puppeteer example:
const browser = await puppeteer.connect({
browserWSEndpoint:
"ws://localhost:3000?token=YOUR_TOKEN&--proxy-server=http://proxy.example.com:8080"
});
const page = await browser.newPage();
await page.goto("https://example.com");
The same --proxy-server query pattern works when connecting to a self-hosted Browserless instance with Playwright over CDP. Treat custom Chromium arguments cautiously: Playwright warns that unsupported arguments can break browser functionality. Add one flag at a time and remove it if a session stops launching.
Free tools Windows power users keep installed
One-click scans. No signup required.
Residential, datacenter, geography, and session choices
Residential versus datacenter routing
| Route | Browserless documented rate | Detection and cost trade-off |
|---|---|---|
| Residential | 6 units/MB | Described by Browserless as harder to detect, but costs more units. |
| Datacenter | 2 units/MB | Lower unit cost, but more easily detected. |
These are provider-documented rates, not an independent benchmark. Choose residential routing when the target’s reputation checks are the problem; choose datacenter routing when predictable cost is more important and the target accepts it.
Country, city, and locale
proxyCountry accepts an ISO country code. proxyCity targets a city, but Browserless documents that city-level targeting requires a Scale plan with at least 500,000 units. proxyLocaleMatch can align browser language and formatting with the proxy location, reducing an obvious mismatch between IP geography and locale.
Rank #4
Keeping an IP stable
Plain REST and WebSocket requests use a random proxy node by default. Add proxySticky=true when you need the same IP where possible, such as a multi-step flow that expects session continuity. “Sticky” is a routing request, not a guarantee that an IP can never change.
Verify the egress path before testing the target
- Start with a clean session. Close old pages and create the context or connection with the intended proxy settings.
- Visit an IP-inspection page. Read the reported public address from inside the browser. Browserless’s examples use an IP-inspection page for this check.
- Compare the result with the expected proxy location. Confirm country, city (if requested), and whether the address belongs to the expected network.
- Only then open the target site. This separates proxy authentication and routing failures from target-site blocks.
- Record the verdict safely. Log a request identifier and high-level outcome, not the proxy password or complete signed WebSocket URL.
Troubleshooting common failures
HTTP 401 when using an external proxy
Cause: Browserless requires a paid cloud-unit plan for third-party proxy use. Fix: confirm the account’s plan and units, or remove externalProxyServer when direct egress is acceptable.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Proxy authentication fails
Cause: wrong credentials, a malformed scheme, or reserved characters that were not encoded. Fix: test the proxy URL independently, encode the username and password, and verify the host and port. In a query string, encode the complete proxy URL rather than only the password.
The browser shows the original IP
Cause: the setting was applied at the wrong scope. Fix: use browser.newContext({ proxy }) for native Playwright, the Browserless query parameter for hosted sessions, or --proxy-server for self-hosted Chromium. In CDP mode, use browser.contexts()[0] when relying on launch-level inheritance.
A newly created CDP context bypasses the proxy
Cause: launch-level settings are attached to Browserless’s default context, not automatically copied to a new context. Fix: use the default context, or switch to a native Playwright connection and set a context-level proxy explicitly.
Best Value
Puppeteer environment variables have no effect
Cause: you are using puppeteer-core, which ignores Puppeteer configuration files and environment variables, or you expected download settings to proxy page traffic. Fix: configure the remote connection or Chromium launch directly.
Custom flags make Playwright unstable
Cause: an unsupported Chromium argument conflicts with Playwright. Fix: remove nonessential flags, retain only the proxy argument, and add options back individually while checking that the browser still launches.
Performance, reliability, and cost considerations
- Bandwidth is a direct cost driver. Browserless documents 6 units/MB for residential routing and 2 units/MB for datacenter routing, so large pages, media, and repeated retries consume more units.
- Proxy distance affects latency. A city or country route farther from the target or browser region can add connection time. Match geography only when the application needs it.
- Sticky routing helps workflows, not throughput. Reusing an IP can reduce authentication surprises in a multi-step flow, while random nodes may distribute load across requests.
- Separate browser failures from proxy failures. An IP-inspection request before the target gives you a cheap, reproducible health check.
- Self-hosting shifts the burden. You control the Browserless container and proxy relationship, but you must supply the proxy, secure credentials, monitor availability, and handle rotation yourself.
Or skip the browser setup
If your requirement is a clean website screenshot rather than an interactive browser session with your own egress IP, ScreenshotNeo provides a one-request screenshot API. It removes cookie and consent banners, newsletter popups, and chat widgets before capture; bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing status. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.
See the parameter reference in the ScreenshotNeo documentation. cURL:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Python:
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
ScreenshotNeo includes full-page and element captures, device presets, custom CSS and JavaScript, waits, request blocking, PDF output, signed links, asynchronous jobs, bulk capture, and caching. It does not replace a proxy-controlled interactive session; use the Browserless patterns above when the target must see your proxy IP.
Recommended Free Tools
The Free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 screenshots, and every feature is included on every plan. Create a free ScreenshotNeo account.
FAQ
Frequently Asked Questions
How should proxy credentials be handled in CI?
Store them in the CI platform’s encrypted secrets, construct the connection URL at runtime, and redact WebSocket URLs and proxy values from logs. Rotate credentials independently of application code.
Can I use one proxy for some pages and another for others?
Yes with native Playwright: create separate browser contexts and give each context its own proxy object. Do not assume a newly created CDP context inherits launch-level settings; use the default context or a native connection.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →

