Playwright

Use NyxonProxies with Playwright in Python and Node.js: proxy at launch, a proxy per browser context, sticky sessions, bypass lists, saving traffic and errors.

Playwright takes the proxy server, username and password as one option, at launch or per browser context. It handles the gateway's login itself, so no extension or handler is needed.

Install

pip install playwright
playwright install chromium

Proxy at launch

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(proxy={
        "server": "http://geo.gw.nyxon.sh:8080",
        "username": "USERNAME-country-us",
        "password": "PASSWORD",
    })
    page = browser.new_page()
    page.goto("https://api.ipify.org?format=json")
    print(page.inner_text("body"))
    browser.close()

Keep the credentials in username and password. Written into the server URL, they are not sent.

One proxy per context

A browser context is an isolated session inside one browser, with its own cookies and storage. Give each context its own username with a session ID and each one keeps its own IP. This checks a page from three countries, with the locale and time zone matched to each exit:

python
import secrets
from playwright.sync_api import sync_playwright

MARKETS = {
    "us": ("en-US", "America/New_York"),
    "de": ("de-DE", "Europe/Berlin"),
    "gb": ("en-GB", "Europe/London"),
}

with sync_playwright() as p:
    browser = p.chromium.launch()
    for country, (locale, tz) in MARKETS.items():
        sid = secrets.token_hex(4)
        context = browser.new_context(
            proxy={
                "server": "http://geo.gw.nyxon.sh:8080",
                "username": f"USERNAME-country-{country}-session-{sid}-time-20",
                "password": "PASSWORD",
            },
            locale=locale,
            timezone_id=tz,
        )
        page = context.new_page()
        page.goto("https://ipinfo.io/json")
        print(country, page.inner_text("body"))
        context.close()
    browser.close()

In Node.js the same object goes to browser.newContext({ proxy: { ... }, locale, timezoneId }). Pages in one context share its proxy. There is no per-page proxy.

Rotating or sticky

Loading one page opens several connections, often one per host. On a rotating username, those connections can leave from different IPs, so one page view can arrive from several addresses. For logins, carts and multi-step forms, use a session ID per context and a time longer than the task. To get a new IP, close the context and open a new one with a new session ID. See Rotating and sticky sessions.

Skip the proxy for some hosts

bypass takes a comma-separated list of hosts to reach directly:

python
browser = p.chromium.launch(proxy={
    "server": "http://geo.gw.nyxon.sh:8080",
    "username": "USERNAME",
    "password": "PASSWORD",
    "bypass": "localhost,127.0.0.1,.internal.example",
})

A leading dot matches subdomains. List local addresses yourself if they should go direct: Playwright sends 127.0.0.1 through the proxy otherwise.

Save traffic: block heavy files

Images, fonts and video make up most of a page's weight. Abort them before they leave the browser and they never reach the proxy:

python
def block_heavy(route):
    if route.request.resource_type in {"image", "media", "font"}:
        return route.abort()
    return route.continue_()


page.route("**/*", block_heavy)
page.goto("https://www.wikipedia.org/")

Leave stylesheets alone if you take screenshots or depend on the layout.

SOCKS5

Chromium cannot log in to a SOCKS5 proxy. With a username and password on a socks5:// server, the launch fails with Browser does not support socks5 proxy authentication. Use the HTTP port: it carries HTTPS sites through an encrypted tunnel, so you lose nothing.

Errors

Chrome's codes appear in Playwright's errors with a net:: prefix:

ErrorCause
ERR_PROXY_CONNECTION_FAILEDWrong host or port, or a firewall.
ERR_INVALID_AUTH_CREDENTIALSNo credentials were sent, for example because they were written into server.
ERR_HTTP_RESPONSE_CODE_FAILURECredentials were sent and refused, usually a wrong password.
ERR_TUNNEL_CONNECTION_FAILEDThe gateway answered the tunnel request with an error such as 502.
Browser does not support socks5 proxy authenticationA SOCKS5 server with credentials. Use the HTTP port.
TimeoutError on page.gotoThe page took too long. Residential routes are slower than direct ones, so raise the limit, for example page.goto(url, timeout=60000).

Last updated

Still stuck?

People answer the live chat around the clock. Send the proxy line you used (without the password) and the error you see.