A Playwright proxy is an object with server, username and password, passed either to launch() for the whole browser or to new_context() for one context. Per-context proxies are how you run several IPs from one browser process.
browser = p.chromium.launch(proxy={"server": "http://HOST:PORT", "username": "USERNAME", "password": "PASSWORD"})
The snippets on this page ran on 2026-09-29 with Playwright 1.63 for Python and for Node.js, driving Chrome, against two local authenticating HTTP proxies and a SOCKS5 proxy that enforces credentials.
Before you start: copy your proxy details
- Open your order in the dashboard at https://app.proxyhive.io.
- Copy HOST, PORT, USERNAME and PASSWORD. Each ISP or datacenter IP is its own endpoint, with its own HTTP, HTTPS and SOCKS5 ports listed on the order. With Playwright, use the HTTP port unless you have allowlisted your IP (see SOCKS5 below).
- Export them:
export PROXY_SERVER="http://HOST:PORT" PROXY_USER=USERNAME PROXY_PASS=PASSWORD
Browser automation against logged-in or session-heavy sites is where static ISP proxies earn their keep: the address stays the same for the whole term.
Playwright Python proxy: launch-level
import os
from playwright.sync_api import sync_playwright
proxy = {
"server": os.environ["PROXY_SERVER"],
"username": os.environ["PROXY_USER"],
"password": os.environ["PROXY_PASS"],
}
with sync_playwright() as p:
browser = p.chromium.launch(proxy=proxy)
page = browser.new_page()
page.goto("https://api.ipify.org?format=json")
print(page.inner_text("body"))
browser.close()
The fields match the Playwright network docs: server is required, username and password are optional, and bypass takes a comma-separated list of hosts that should skip the proxy, such as "localhost,.internal.example".
Playwright Node.js proxy
The same object in JavaScript:
import { chromium } from 'playwright';
const browser = await chromium.launch({
proxy: {
server: process.env.PROXY_SERVER,
username: process.env.PROXY_USER,
password: process.env.PROXY_PASS,
},
});
const page = await browser.newPage();
await page.goto('https://api.ipify.org?format=json');
console.log(await page.textContent('body'));
await browser.close();
Keep credentials in username and password, not in the server URL. Playwright answers the proxy's 407 challenge with them for you, which is the part Puppeteer and Selenium make you handle yourself.
Playwright per-context proxy for rotation
A context is an isolated browser profile: its own cookies, storage and, if you give it one, its own proxy. One browser process can hold many.
import os
from playwright.sync_api import sync_playwright
servers = os.environ["PROXY_SERVERS"].split(",")
with sync_playwright() as p:
browser = p.chromium.launch()
for server in servers:
context = browser.new_context(proxy={
"server": server,
"username": os.environ["PROXY_USER"],
"password": os.environ["PROXY_PASS"],
})
page = context.new_page()
page.goto("https://api.ipify.org?format=json")
print(server, page.inner_text("body"))
context.close()
browser.close()
In Node it is browser.newContext({ proxy: { server, username, password } }), and our run showed the two contexts leaving through their two proxies from one browser. If your IPs have different credentials, keep server, username and password together per IP in whatever list you load.
Rotation here means one IP per context, not per request. That is the right shape for browsers: a site that sees one session hop between addresses mid-login is more suspicious than one that sees a stable address. The trade-offs are laid out in rotating vs static proxies.
Proxy authentication with an IP allowlist
If your automation runs on a server with a fixed address, switch the IP to allowlist authentication on the order in the dashboard and add that server's public IP. Then proxy={"server": "http://HOST:PORT"} is all Playwright needs. It also unlocks SOCKS5, below.
Playwright SOCKS5 proxy: no authentication
Playwright accepts socks5://HOST:PORT as a server. It does not accept SOCKS5 with credentials: set a username or password and launch() throws Browser does not support socks5 proxy authentication. That check lives in Playwright's proxy normalisation, so it applied to both Chromium and Firefox in our run. Your options:
- Use the HTTP port with username and password (simplest; the page traffic is still encrypted end to end inside the tunnel).
- Allowlist your IP and use
socks5://HOST:SOCKS5_PORTwith no credentials.
HTTP vs SOCKS5 proxies explains why option 1 costs a browser nothing.
Verify the exit IP
The snippets above print the proxied address from https://api.ipify.org?format=json. Compare it with the IP on your order, and with the address the same code prints without the proxy option. If both match, the proxy is being ignored: check that you passed it to the browser or context that opened the page.
Timeouts and retries
Proxied page loads are slower than direct ones, especially the first request of a context, which pays for the CONNECT and the TLS handshake. Set timeouts on the context and retry navigations that fail:
context.set_default_navigation_timeout(45_000)
for attempt in range(3):
try:
page.goto(url, wait_until="domcontentloaded")
break
except Exception:
if attempt == 2:
raise
wait_until="domcontentloaded" avoids waiting on third-party trackers that never settle and whose traffic you pay for.
Common Playwright proxy errors
| Error | Cause | Fix |
|---|---|---|
Browser does not support socks5 proxy authentication | socks5:// server plus username or password | HTTP port, or allowlist and drop credentials |
net::ERR_HTTP_RESPONSE_CODE_FAILURE on goto | The proxy answered 407 to the credentials | Re-copy username and password |
net::ERR_PROXY_CONNECTION_FAILED | Wrong host or port | Check the port for the protocol in server |
Timeout 30000ms exceeded | Slow first load, or a heavy page | Raise the navigation timeout; use domcontentloaded |
Status codes from the target itself are covered in proxy error codes.
Next steps
- Same setup in Puppeteer or Selenium, both of which need more work for authenticated proxies.
- Fetch without a browser from Node with undici or axios.
- Connection reference: the docs.