Playwright takes a proxy as one small object with four fields: server, bypass, username and password. You can pass it when you launch the browser or when you create a context. The fields behave exactly as Playwright's own code says, and two of its rules catch most people: a login inside the server URL disappears, and a SOCKS5 proxy cannot take a login at all.
This guide follows Playwright's documentation and source on its main branch, read on October 13, 2026, with version 1.64.0 of October 7, 2026, the latest release on npm. We ran none of the code for this page.
Set the proxy at launch or per context
Playwright's network guide puts it in one line: "Proxy can be either set globally for the entire browser, or for each browser context individually." At launch, the proxy covers every context in that browser.
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch({
proxy: { server: 'http://203.0.113.7:8080', username: 'user', password: 'pass' },
});
const page = await browser.newPage();
await page.goto('https://httpbin.org/ip');
console.log(await page.textContent('body'));
await browser.close();
})();
Per context, the proxy covers that context only. The option's documentation reads "Network proxy settings to use with this context. Defaults to none." Playwright describes contexts as "isolated clean-slate environments", each with its own cookies and storage, so two contexts in one browser can use two proxies at once.
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch()
context = browser.new_context(
proxy={"server": "http://203.0.113.7:8080", "username": "user", "password": "pass"}
)
page = context.new_page()
page.goto("https://httpbin.org/ip")
print(page.text_content("body"))
context.close()
browser.close()
The same object works for chromium, firefox and webkit. The server accepts both kinds of proxy: "HTTP and SOCKS proxies are supported, for example" http://myproxy.com:3128 or socks5://myproxy.com:3128. A server without a scheme counts as HTTP: "Short form myproxy.com:3128 is considered an HTTP proxy."
Why user:pass in the server URL disappears
Many tools accept http://user:pass@host:port. Playwright does not keep that part. Its function normalizeProxySettings parses the server and rebuilds it with one line, server = url.protocol + '//' + url.host;. Protocol and host survive, and the username and password inside the URL are gone before the browser starts. A proxy that needs a login then answers 407 Proxy Authentication Required.
server: http://user:pass@host
the login sits in the URL
normalizeProxySettings
keeps protocol and host only
Proxy answers 407
no login reached it
username and password fields
the login in its own fields
// Dropped: Playwright keeps only protocol and host from this URL
const context = await browser.newContext({
proxy: { server: 'http://user:pass@203.0.113.7:8080' },
});
// Kept: the login in its own fields
const context2 = await browser.newContext({
proxy: { server: 'http://203.0.113.7:8080', username: 'user', password: 'pass' },
});
The fields are documented for HTTP proxies: "Optional username to use if HTTP proxy requires authentication." Playwright turns them into a Basic credential, and one of its code paths adds the header Proxy-Authorization itself. Our guide to 407 Proxy Authentication Required covers the proxy's side of that exchange.
SOCKS5: no login, and names resolve at the proxy
A socks5:// server works, without a username or password. The same normalizing function refuses the combination: with a login on a SOCKS5 server it throws "Browser does not support socks5 proxy authentication", and for SOCKS4 "Socks4 proxy protocol does not support authentication". So a SOCKS5 proxy that needs a login cannot be used this way. Use the provider's HTTP endpoint with the fields, or let the provider admit your address without a password.
On Chromium, Playwright adds one more argument for a SOCKS5 proxy: --host-resolver-rules with "MAP * ~NOTFOUND , EXCLUDE" and the proxy's own host. Every local DNS lookup except the proxy's fails on purpose, so hostnames resolve at the proxy.
Hosts that skip the proxy
The bypass field takes a comma-separated list, and the docs give the example ".com, chromium.org, .domain.com". For Chromium, Playwright turns the list into Chrome's own switch, --proxy-bypass-list, and rewrites a leading dot as a wildcard (t.startsWith('.') ? '*' + t : t).
What Playwright does with each proxy setting
| Setting | Result | Where |
|---|---|---|
| Server, no scheme | HTTP proxy | The docs |
| user:pass in server | Dropped | Its source |
| SOCKS5 with login | Error | Its source |
| SOCKS5 on Chromium | DNS at proxy | Its source |
| bypass list | Skips proxy | The docs |
Playwright docs (network.md, params.md) and server source (browserContext.ts, chromium.ts), main branch, read October 13, 2026
Spreading work over several proxies
Two set-ups keep the code simple. Give each new context its own proxy from your list, and close the context when its work is done. Or point every context at one rotating gateway: one host and port in the proxy object, with the outgoing address changing behind it.
const browser = await chromium.launch();
for (const proxy of proxies) { // [{ server, username, password }, ...]
const context = await browser.newContext({ proxy });
try {
const page = await context.newPage();
await page.goto('https://httpbin.org/ip', { timeout: 20000 });
console.log(proxy.server, await page.textContent('body'));
} finally {
await context.close();
}
}
await browser.close();
Use addresses you are allowed to use. Each site's terms and robots.txt apply whatever address a request comes from.
Check the exit
Load an address-echo page through the context and compare it with your own address. If the two match, the proxy is not in use; the usual causes are a login left in the server URL or a context created without the proxy. Our proxy checker tests a proxy from your own connection before you put it into a script.
What a site can see
A proxy changes the address a request comes from. Automation itself is visible by design: MDN describes navigator.webdriver as the property that tells a page whether the browser is "controlled by automation." Whether a site accepts automated browsers is that site's decision. This page gives no way to hide automation or to get past a site's checks.
What other guides get wrong
- SpyderProxy says "Use stealth patches. Libraries like playwright-stealth hide automation flags (navigator.webdriver and friends) that anti-bot systems check." The flag exists so a page can tell an automated browser; hiding it works around the site's own checks.
- ZenRows writes that a proxy lets you "avoid IP bans and access geo-restricted content", and skips what Playwright does with a login inside the server URL.
- Oxylabs answers the detection question with tools "that will help ensure smooth and block-free data-gathering". A site that blocks automated browsers has decided, and a proxy leaves that decision as it was.
- Bright Data says a proxy "helps mask your real IP address and bypass rate limiters", and shows how to change the User-Agent "To avoid detection". Both work around the site's own rules.
- ScrapingBee suggests rotating user agents so requests "appear to come from different browsers and devices, reducing the chances of getting blocked".
Where HProxy fits
Our residential proxies put a rotating gateway behind one host and port, which suits the set-up above, with the login in the username and password fields, from $0.44 per GB. Premium lines take SOCKS5 as well as HTTP, and an IP whitelist admits your machine's address without a password, so a SOCKS5 line works in Playwright with no login to send. Premium also holds one address for up to 24 hours, from $1.00 per GB.
What we could not find out
- How Firefox and WebKit resolve names behind a SOCKS5 proxy. We read Playwright's Chromium launcher only.
- Whether every proxy accepts the Basic credential Playwright sends. Playwright's code sends Basic; we used no proxy.
- How releases before 1.64 behaved. We read the main branch.
Sources
Read on October 13, 2026.
- Playwright documentation source: network.md (HTTP Proxy), params.md (the proxy option) and browser-contexts.md.
- Playwright server source: browserContext.ts and chromium.ts.
- npm: playwright, version 1.64.0 of October 7, 2026.
- MDN: Navigator.webdriver.
- Demand data: Google Keyword Planner volumes and Search Console figures for this URL, July 15 to October 12, 2026.
- Guides we judged, read the same day and deliberately left unlinked: SpyderProxy, ZenRows, Oxylabs, Bright Data and ScrapingBee.



