Playwright Proxy Setup: What Chromium Supports and What It Does Not
The proxy works in curl. You paste the same endpoint into Playwright and the page fails with a connection error. Nothing is wrong with the proxy or the browser code. Chromium handles proxy authentication differently from command-line clients, and that difference decides your setup.
Chromium can authenticate to an HTTP proxy. It cannot authenticate to a SOCKS5 proxy. If your provider gives you a SOCKS5 username and password, the browser needs a local bridge or an HTTP endpoint.
| Client | HTTP proxy auth | SOCKS5, no auth | SOCKS5 with auth |
|---|---|---|---|
| Playwright / Chromium | Yes, separate fields | Yes | No, use a bridge |
| Puppeteer / Chromium | Yes, page.authenticate | Yes | No, use a bridge |
| Selenium / Chrome | Yes, usually via extension or bridge | Yes | No, use a bridge |
| curl / Python requests | Yes | Yes | Yes |
Playwright proxy setup, two ways
For an HTTP proxy, pass the server and credentials as separate fields. Playwright ignores credentials embedded in the server URL, so the username and password must be their own keys.
For an authenticated SOCKS5 session, launch the browser against a loopback HTTP-to-SOCKS5 bridge. The bridge listens on 127.0.0.1, accepts a plain HTTP proxy connection from Chromium, and performs the SOCKS5 handshake upstream with your credentials. Chromium only sees a local HTTP proxy.
Playwright supports a proxy per browser context. Pages inside one context share that proxy, so a new page does not give you a new exit. Create a new context when you want a new session, and run one bridge per session so the upstream credentials do not get mixed.
Puppeteer needs two pieces
Puppeteer sets the proxy at launch and authenticates at the page level. Put only the scheme, host, and port in the launch argument. Credentials go through page.authenticate before the first navigation.
Three details trip people up. Embedded credentials in --proxy-server produce ERR_NO_SUPPORTED_PROXIES. Authentication is applied per page, but Chrome caches the first credentials for the browser, so a second page with different credentials will still use the first. And a failed authentication often resolves with a 407 response instead of throwing, so check the status.
For SOCKS5, Puppeteer has the same limit as Playwright. Use --proxy-server=socks5://host:port only when the proxy needs no login. With a login, point Chrome at the loopback bridge instead.
Selenium exposes the same Chromium limit
Selenium passes Chrome's proxy flags through ChromeOptions. The browser behind it is still Chromium, so authenticated SOCKS5 fails the same way. Proxy authentication in Chrome usually needs an extension or a local authenticating proxy. The loopback bridge avoids both and keeps the credentials out of the browser profile.
Rotate exits with contexts, not pages
Browser rotation is a context-level decision. One context, one exit. If you open ten pages in the same context, all ten leave through the same bridge and the same upstream session.
Create a session and a bridge for each worker, create one Playwright context per worker, and close the context when the job finishes. Puppeteer can do something similar with browser contexts in recent versions, but separate browsers are the safer default when you need isolated credentials.
Chromium does not send loopback addresses through a proxy by default. Verify the exit against an external IP echo, not against a local service. If the echo returns the same IP for every worker, the bridge or the upstream session is being shared.
What the proxy will not fix
A proxy changes the IP and the ASN. It does not change the TLS fingerprint, the WebDriver surface, the font list, the canvas output, or the request rate. Headless Chromium fails some of those checks before the page finishes loading, and a residential exit only makes the IP part look better.
Fix the browser surface first, then rotate. A new IP that gets blocked in two seconds is a more expensive way to fail.
What a browser session costs
ProxyBase residential starts at $3 per GB and mobile at $5 per GB. A browser burns more bandwidth than a raw HTTP client because it fetches images, fonts, and scripts. Budget two to five times the page size you measured with curl, and set a spend cap on the session before the first run.
Frequently Asked Questions
Does Playwright support SOCKS5 proxies?
It supports unauthenticated SOCKS5 because Chromium understands the protocol without credentials. It does not support authenticated SOCKS5. Use a loopback HTTP-to-SOCKS5 bridge when the session requires a username and password.
Can Puppeteer use a proxy with a username and password?
Yes for HTTP and HTTPS proxies. Launch with --proxy-server, then call page.authenticate before navigating. It answers an HTTP 407 challenge, so it cannot authenticate a SOCKS5 proxy.
Why does Chromium ignore proxy credentials in the URL?
Chromium does not read userinfo from a proxy URL. Pass credentials as separate fields in Playwright, or through page.authenticate in Puppeteer. Embedded credentials commonly produce ERR_NO_SUPPORTED_PROXIES.
How do I rotate proxies in Playwright?
Create a new browser context with a new proxy or bridge address for each session. Pages inside one context share the exit. Closing and recreating the context is the rotation event.
Why does my proxy work in curl but not in Chromium?
curl and Python support authenticated SOCKS5. Chromium does not. A SOCKS5 endpoint with a username and password connects in curl and fails in the browser with ERR_SOCKS_CONNECTION_FAILED.
Does a proxy make headless Chrome undetectable?
No. Detection also looks at the TLS fingerprint, the WebDriver surface, fonts, canvas output, header order, and request rate. Rotating exits without changing those signals gives you a fresh IP that gets blocked the same way.