Proxies for cloud browsers: VMs, containers and hosted services
Where the browser runs and how its traffic leaves are separate decisions. Configure the netdash proxy where the browser is launched: in your own code on a VM or container, or in a hosted service's session settings.
- Updated
- Reading time
- 8 min
- Checked against
- 5 sources
A cloud browser proxy setup has two separate parts: the machine or service the browser runs on, and the way its traffic leaves for the web. netdash only covers the second part. It isn't a browser host: you run the browser yourself, on a VM or in a container, or you rent one from a hosted browser service and give that service your netdash proxy. For the agent side of this setup, see proxies for AI agents.
netdash is an HTTP proxy with username and password authentication. HTTPS sites go through a CONNECT tunnel, so the proxy server always starts with http://. The username carries the exit country and, for a sticky session, a session ID and a TTL in minutes.
Three layers, configured separately
- 01
Where the browser runs
Your laptop, a cloud VM, a container, or a managed browser service from another vendor. This is the compute layer.
- 02
How its traffic leaves
The browser is configured to use a netdash proxy. This is the network layer netdash provides.
- 03
Where the traffic goes
Websites and APIs you are permitted to access, reached from the exit country you chose.
| Layer | What you decide | Where it's set |
|---|---|---|
| 1. Where the browser runs | A laptop, a cloud VM, a container, or a hosted browser service | Your infrastructure, or your account with the service |
| 2. How its traffic leaves | The netdash plan, gateway, exit country and session | The browser's launch options, or the hosted service's session settings |
| 3. Where the traffic goes | Sites and APIs you're permitted to access | Your task and the site's terms, not a proxy setting |
Moving a browser to the cloud changes layer 1 only. Without a proxy, a browser on a cloud VM reaches websites from the cloud provider's address in that region. With the netdash proxy, it reaches them from an exit IP in the country you choose, wherever the browser runs.
Your own browser on a VM or container
Launch the browser exactly as in the Playwright and Puppeteer guides: the proxy settings don't change on a server. Three things do need attention:
- Credentials at run time. Pass
NETDASH_USERNAMEandNETDASH_PASSWORDas environment variables when the container starts. Don't bake them into an image or commit them in a Compose file. - Outbound access. The VM or container needs outbound TCP to the gateway host on your plan's port: 1000, 2000, 3000 or 4000, as listed in the proxy format reference. The examples use
scale-us.netdash.io:2000. - A pinned image. Playwright's Docker docs recommend pinning the image to a specific version; it should match the Playwright version in your project.
# NETDASH_USERNAME and NETDASH_PASSWORD come from your shell or CI secrets.
# "-e NAME" without a value copies the variable from the current environment.
docker run --rm --init --ipc=host \
--user pwuser --security-opt seccomp=seccomp_profile.json \
-e NETDASH_USERNAME -e NETDASH_PASSWORD \
-v "$PWD":/work -w /work \
mcr.microsoft.com/playwright:v1.64.0-noble \
node contexts.mjsPlaywright's Docker docs recommend --init, and --ipc=host when you use Chromium. For sites you don't control, the same docs recommend running the browser as a separate user (pwuser) together with a seccomp profile, which they link to. contexts.mjs stands for your own script, for example the per-context example from the Playwright guide, with Playwright installed in the project at the image's version.
Keep NETDASH_USERNAME and NETDASH_PASSWORD in a .env file or your secret manager, never in source control or in a chat with an assistant.
Remote browsers you connect to
When your code connects to a browser that runs somewhere else, over the Chrome DevTools Protocol or another WebSocket endpoint, the proxy belongs to that browser's launch, not to the code that connects. Set it where the browser is started: in the launch command on your own browser server, or in the hosted service's session settings below.
Some clients let you create a new browser context with its own proxy over a remote connection. Whether that works depends on the connection type and the service, so confirm the exit IP with https://api.ipify.org?format=json before you rely on it.
Cloud browser proxy settings in hosted services
Several hosted browser services accept your own proxy when you create a session. Each needs the same three values from netdash: the gateway (scale-us.netdash.io, port 2000), a username with the country and, for a sticky session, the session parameters, and your password.
The configurations below follow each provider's documentation, linked under Sources. They are not tested by netdash, and netdash has no partnership with these providers. Some services accept an external proxy only on certain plans, so check your plan with the provider. If a service also sells its own proxies, use one proxy layer for a given site, not both.
Browserbase
Pass an external proxy when you create the session. Browserbase validates the proxy connection at session creation and throws an error if it can't connect, so a wrong password or a blocked port shows up right away. Its docs also say that not all proxy providers are supported, so start with a short test session. An optional domainPattern limits an entry to matching domains; entries apply in order and the first match wins. Browserbase lists custom proxies for its Developer plan and above.
import { Browserbase } from "@browserbasehq/sdk";
const bb = new Browserbase({ apiKey: process.env.BROWSERBASE_API_KEY });
const session = await bb.sessions.create({
proxies: [
{
type: "external",
server: "http://scale-us.netdash.io:2000",
username: `${process.env.NETDASH_USERNAME}-cc-US-session-a1b2c3d4-ttl-30`,
password: process.env.NETDASH_PASSWORD,
},
],
});
console.log("Session:", session.id);Connect your Playwright or Puppeteer client to the session as the Browserbase docs describe, then open https://api.ipify.org?format=json to see the exit IP.
Amazon Bedrock AgentCore Browser
AgentCore takes the proxy in proxyConfiguration when you call StartBrowserSession, and you can't change it during the session: start a new session for a different country or session ID. The server field is a hostname without a scheme, the port has its own field, and the credentials come from an AWS Secrets Manager secret with username and password keys. The identity that starts the session needs secretsmanager:GetSecretValue on that secret.
AgentCore requires an HTTP or HTTPS proxy that supports CONNECT for HTTPS, which is how netdash works. Usernames may contain letters, digits and @ . _ + = -, so the -cc- and -session- parameters fit; check that your password uses only the characters the AWS docs allow (no colons, spaces or quotes). Domains in bypass.domainPatterns bypass the proxy and connect directly; the AWS docs suggest that for AWS endpoints.
aws secretsmanager create-secret --name "netdash-us-session-a1b2c3d4" \
--secret-string '{"username":"USERNAME-cc-US-session-a1b2c3d4-ttl-30","password":"PASSWORD"}'import boto3
client = boto3.client("bedrock-agentcore", region_name="us-east-1")
response = client.start_browser_session(
browserIdentifier="aws.browser.v1",
name="netdash-us-session",
proxyConfiguration={
"proxies": [{
"externalProxy": {
"server": "scale-us.netdash.io", # hostname only, no scheme
"port": 2000,
# The ARN that create-secret printed
"credentials": {"basicAuth": {"secretArn": "arn:aws:secretsmanager:REGION:ACCOUNT_ID:secret:netdash-us-session-a1b2c3d4"}},
}
}],
"bypass": {"domainPatterns": [".amazonaws.com"]},
},
)
print("Session:", response["sessionId"])Each secret holds one username, so create one secret per country and session combination. AgentCore doesn't validate the proxy when the session starts: an unreachable gateway or a wrong password shows up as browser error pages, which you can see in Live View. It doesn't retry failed requests either.
Browserless
Browserless takes an external proxy as the externalProxyServer query parameter on the connection URL, with the credentials inside the proxy URL. URL-encode the proxy URL, as its docs say, especially when the password contains special characters. Browserless documents external proxies as HTTP(S) only and rejects them on its free plan with a 401.
import puppeteer from "puppeteer-core";
const { BROWSERLESS_TOKEN, NETDASH_USERNAME, NETDASH_PASSWORD } = process.env;
const username = `${NETDASH_USERNAME}-cc-US-session-a1b2c3d4-ttl-30`;
const proxyUrl = `http://${username}:${encodeURIComponent(NETDASH_PASSWORD)}@scale-us.netdash.io:2000`;
const browser = await puppeteer.connect({
browserWSEndpoint: `wss://production-sfo.browserless.io?token=${BROWSERLESS_TOKEN}&externalProxyServer=${encodeURIComponent(proxyUrl)}`,
});
try {
const page = await browser.newPage();
await page.goto("https://api.ipify.org?format=json", { timeout: 30_000 });
console.log(await page.evaluate(() => document.body.innerText));
} finally {
await browser.close();
}Use the regional endpoint from your Browserless account in place of production-sfo.
Sessions and countries in hosted browsers
The username carries the exit country and the session, so each hosted session gets the netdash username you give it at creation:
- Browserbase: one
externalentry per country, with adomainPatternwhen different sites need different exit countries. - AgentCore: one secret per username, and a new browser session to change it.
- Browserless: the proxy is part of the connection URL, so each connection can use its own username.
Reusing a session ID keeps the same exit IP for the TTL while that IP stays available. Pick a TTL longer than the hosted session runs; the dashboard presets are 15 minutes, 30 minutes, 12 hours and 7 days. Use GB for the United Kingdom, not UK, and the -eu gateway for exits in Europe. The sticky session syntax has the details.
Errors and fixes
| Symptom | Cause | Fix |
|---|---|---|
| Every page times out from your own VM or container | A firewall or security group blocks outbound traffic to the gateway port | Allow outbound TCP to the gateway host on your plan's port |
| Browserbase session creation fails with a proxy error | Browserbase couldn't connect through the proxy at creation: wrong host, port or password | Test the same values with the cURL example from the quickstart, then create the session again |
| AgentCore session starts, but pages show proxy errors | AgentCore doesn't validate the proxy at creation; the server, port or secret is wrong | Check server (hostname only), port and the secret's username and password keys; start a new session |
| AgentCore pages fail even with the right password | The secret contains characters AgentCore doesn't accept | Check the allowed characters in the AWS docs |
Browserless answers 401 when you pass externalProxyServer | Third-party proxies need a paid Browserless plan | Check your plan with Browserless |
| Browserless can't use the proxy | The proxy URL isn't URL-encoded in the query string | Wrap it in encodeURIComponent |
| The exit IP is in the wrong country | The service's own proxy and your external proxy are both configured for the site, or the username has another -cc- value | Use one proxy layer per site; check the country code in the username |
netdash forwards your traffic unchanged. It doesn't solve CAPTCHAs, render JavaScript or retry requests. Targeting is country-level.
Use it responsibly
Respect robots.txt and each site's terms, keep request rates reasonable and back off when a site slows you down. Don't collect personal data without a lawful basis or open content behind logins or paywalls without authorization. netdash doesn't solve CAPTCHAs or bot challenges, and your browsers shouldn't try to get past them either: if a site rate-limits or challenges your requests, slow down, check its terms, or use its official API. Read how we expect netdash to be used.
Next steps
- Playwright proxy setup
Launch and context proxies in Playwright for Node.js and Python, including Playwright Test.
- Troubleshooting
407 errors, connection failures, timeouts and the wrong exit country, with the cause of each.
- Browser automation
Run browser workflows from a chosen country with per-context sessions.
Also useful: the Puppeteer guide, the agent frameworks guide and rotating and sticky sessions.
Stuck? See troubleshooting or email support with your username (without the password) and the error message.
Email supportSources
Third-party behaviour described on this page was checked against these documents.
- 01Playwright docs: Docker (image tags, version pinning, recommended flags)Accessed 2026-10-09
- 02Docker docs: docker container run, setting environment variables (-e)Accessed 2026-10-09
- 03Browserbase docs: Proxies (external proxies, domainPattern, validation at session creation)Accessed 2026-10-09
- 04Amazon Bedrock AgentCore Developer Guide: Using browser proxiesAccessed 2026-10-09
- 05Browserless docs: Proxies (externalProxyServer)Accessed 2026-10-09
Spotted something out of date? Tell us.