Blog

Playwright SOCKS5 Authentication: What Works in 2026

Playwright and Puppeteer can't send a SOCKS5 username and password. Here is why, and how to fix it with proxy-chain or gost, with working code.

6 min read

Playwright SOCKS5 authentication does not work. Chromium has no support for a SOCKS5 username and password, so Playwright and Puppeteer cannot pass one on. The fix is a small local forwarder: it holds the login, and the browser connects to it with no password.

Elusive proxies are SOCKS5 with a username and password. There are no HTTP proxies and no IP-whitelist login, so every automation setup with Elusive needs this step. This guide is about scripts. For manual Chrome use, see Chrome won't take a SOCKS5 password.


Key takeaways

  • Playwright refuses username and password with a socks5:// server. It throws an error before the browser starts.
  • Puppeteer's page.authenticate() is for HTTP authentication. It does not log in to a SOCKS5 proxy.
  • Run a local forwarder with the login inside. Point the browser at http://127.0.0.1:PORT with no password.
  • In Node, proxy-chain does this in three lines. For Python or any language, use gost.
  • Use a hostname in the SOCKS5 link, so site lookups happen at the proxy. Then run a DNS leak check.

What the tools do with SOCKS5 and a password

Chromium. Chromium's network docs say SOCKS5 authentication is not supported. A --proxy-server=socks5://... flag has no place for a login.

Playwright. The docs describe username and password only for HTTP proxies. In the current Playwright source, passing a login with a socks5:// server throws this error:

Browser does not support socks5 proxy authentication

Playwright issue #10567, "Support socks5 proxy with authentication", is still open. The maintainers say the browsers do not support it. Firefox is listed as unsupported in that thread too. WebKit is unclear there, and the docs promise nothing, so don't count on it.

Puppeteer. page.authenticate() supplies credentials for HTTP authentication, per the Puppeteer docs. It does not mention proxies or SOCKS. Chromium never asks for a SOCKS5 login, so there is nothing for it to answer.

One more check: Playwright's own Chromium launch code adds a flag for socks5:// servers that stops local DNS lookups, so names are resolved by the proxy. That helps, but it needs the password you cannot give.


The fix: a local forwarder

The forwarder listens on your machine as an open HTTP proxy. It takes each request and sends it on to your SOCKS5 proxy, adding the login. The browser only knows the local address.

Both options below are used the same way:

  1. Start the forwarder with your HOST, PORT, USER and PASS.
  2. Give the browser http://127.0.0.1:<local port> as its proxy, with no login.
  3. Stop the forwarder when the script ends.

Keep the forwarder bound to 127.0.0.1, so nobody else on your network can use it.


Option A: proxy-chain (Node)

proxy-chain is an npm package from Apify. Its anonymizeProxy() function starts a local proxy for any upstream that needs a login. In the current source (v3.0.1, Node 20.11 or newer) it accepts http, https, and the SOCKS types socks, socks4, socks4a, socks5 and socks5h. The README documents it mostly for HTTP, but the code handles SOCKS upstreams.

Install it next to your browser library:

npm install proxy-chain

Puppeteer:

import puppeteer from 'puppeteer';
import { anonymizeProxy, closeAnonymizedProxy } from 'proxy-chain';

const local = await anonymizeProxy('socks5://USER:PASS@HOST:PORT');

const browser = await puppeteer.launch({ args: [`--proxy-server=${local}`] });
const page = await browser.newPage();
await page.goto('https://example.com');
console.log(await page.title());

await browser.close();
await closeAnonymizedProxy(local, true);

Playwright (Node):

import { chromium } from 'playwright';
import { anonymizeProxy, closeAnonymizedProxy } from 'proxy-chain';

const local = await anonymizeProxy('socks5://USER:PASS@HOST:PORT');

const browser = await chromium.launch({ proxy: { server: local } });
const page = await browser.newPage();
await page.goto('https://example.com');
console.log(await page.title());

await browser.close();
await closeAnonymizedProxy(local, true);

anonymizeProxy() returns a string like http://127.0.0.1:53124. The port is random unless you pass { url, port }. closeAnonymizedProxy(url, true) closes it and drops open connections.

If your password has characters like @, : or /, URL-encode them in the link, for example with encodeURIComponent.

DNS. In the source, the SOCKS code hands the site's hostname to the proxy as a name. It does not resolve it on your machine first. socks5 and socks5h are both accepted. The package docs do not describe this, so run the leak check below.


Option B: gost (any language)

gost is a standalone Go program, so it works the same from Python, Java, .NET or a shell script. This is the current v3 syntax from the gost docs: -L is the local listener, -F is the upstream.

gost -L http://127.0.0.1:8080 -F socks5://USER:PASS@HOST:PORT

Leave it running in a terminal or as a service. Then point the browser at http://127.0.0.1:8080.

Python Playwright:

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(proxy={"server": "http://127.0.0.1:8080"})
    page = browser.new_page()
    page.goto("https://example.com")
    print(page.title())
    browser.close()

Puppeteer and Node Playwright take the same address: --proxy-server=http://127.0.0.1:8080 or proxy: { server: 'http://127.0.0.1:8080' }.

DNS. The browser sends the site name to gost in an HTTP request. In gost's SOCKS5 connector code, that name is passed to the SOCKS5 server as a domain name. We could not find a gost doc page that promises this, so test it. Elusive proxies accept domain names, so remote lookups work on that end.


One forwarder per proxy

A forwarder talks to one upstream. If you run several browsers, each on its own proxy:

  • Start one forwarder per proxy, each on its own local port.
  • With proxy-chain, call anonymizeProxy() once per proxy. Each call gets its own port.
  • With gost, run one process per proxy, or put several -L and -F pairs in a config file. See the gost docs.

A Sticky proxy keeps its IP up to 24 hours and runs on a real device that can go offline earlier, so close the forwarder and start a new one when you swap it. For a Rotating endpoint, one forwarder is enough, because the IP changes behind it. Pick what you need in the catalog.


Check DNS after setup

Open a leak test page with the script's browser, or use the steps in the DNS leak check. None of the DNS servers should belong to your own provider. For what the socks5 and socks5h names mean, see SOCKS5 vs SOCKS5h.

If you plan to run many requests, keep within each site's terms and use sensible rate limits.


Common errors

**Browser does not support socks5 proxy authentication.** You gave Playwright a socks5:// server with a username or password. Use a forwarder and pass the local HTTP address.

**net::ERR_PROXY_CONNECTION_FAILED.** The browser cannot reach the proxy you gave it. The forwarder is not running, or the local port is wrong.

**Invalid "proxyUrl" provided: URL must have one of the following protocols.** proxy-chain did not like the link. Check the scheme and that the link parses as a URL.

Page loads but shows your own IP. The browser is not using the forwarder. Check that the proxy option is on the right launch or newContext call.

Timeouts after a while. A Sticky IP may have gone offline. Replace it and restart the forwarder. A refund exists only for Sticky, only in its first hour, and only if it is offline or its IP or location does not match the listing.


FAQ

Does Playwright support SOCKS5 with a username and password?

No. Playwright throws Browser does not support socks5 proxy authentication if you try. The related issue (#10567) is still open. Use a local forwarder.

Can Puppeteer use page.authenticate() for a SOCKS5 proxy?

No. It answers HTTP authentication requests only. Use proxy-chain or gost and pass the local address in --proxy-server.

Is proxy-chain or gost better?

If your script is Node, proxy-chain starts and stops inside the script. If you use Python or another language, or want one process for many scripts, use gost.

Do I need socks5h for browser automation?

You need the proxy to resolve site names. Through a forwarder, the browser sends names, and both tools hand them on. Run a leak check to be sure.

Does this work with other browsers?

Yes. The browser only needs an HTTP proxy with no login, which every browser supports. Firefox and WebKit in Playwright accept the same proxy: { server } setting.

Get a proxy for your profiles

SOCKS5 with a username and password, ready to paste as HOST:PORT:USER:PASS. Sticky IPs for up to 24 hours, Static ISP for 7 to 90 days, or Rotating by the GB.