Skip to main content
Tech Tutorials & Programming24 min readJul 20, 2026

How to Use a Proxy With Playwright in Python and Node.js

Yazan Sharawi
Yazan Sharawi

Jul 20, 2026

To use a proxy with Playwright, pass a proxy object either when launching the browser or when creating a browser context. The object needs a proxy server and can also include an HTTP proxy username, password, and comma-separated bypass list.

Use a browser-level proxy when every page should use the same exit. Use a context-level proxy when different workers, accounts, or scraping sessions need different IP addresses. Playwright supports HTTP, HTTPS, and SOCKS5 proxy endpoints, but there is one important limitation: its built-in username and password fields do not support SOCKS5 authentication.

This guide uses complete Python sync, Python async, and Node.js/TypeScript programs. It also covers one proxy per browser context, sticky sessions, rotation boundaries, visible-IP testing, Proxidize credentials, Docker, and exact error messages.

TL;DR

  • Put the endpoint in server, such as http://proxy.example:8080 or socks5://proxy.example:1080.
  • Put HTTP proxy credentials in separate username and password fields. Do not embed them in server.
  • Configure chromium.launch(proxy=...) or chromium.launch({ proxy }) for one browser-wide proxy.
  • Configure browser.new_context(proxy=...) or browser.newContext({ proxy }) to assign one proxy to one isolated browser context.
  • Keep a sticky proxy exit and the context’s cookies together for multi-step workflows.
  • Verify the browser’s exit IP by opening an IP-check URL inside the proxied page. A Node.js fetch() or Python requests.get() call tests the runtime, not the browser.
  • Playwright rejects SOCKS5 username/password authentication. Use an IP-allowlisted SOCKS5 endpoint or the provider’s authenticated HTTP endpoint instead.

For most projects, the safest starting point is an authenticated HTTP proxy assigned to a single browser context. First, confirm that the context returns the expected exit IP; then load the actual target website. Once that basic Playwright proxy configuration works, you can add concurrent contexts, sticky sessions, or controlled proxy rotation without mixing network problems with application logic. The examples below follow that sequence and use environment variables so the same code can run with a neutral proxy endpoint or your Proxidize credentials.

30-Second Playwright Proxy Setup

If Playwright and Chromium are already installed, these are the smallest working authenticated HTTP proxy examples. Replace the neutral hostname and credentials with your proxy provider’s values, then run the example for your language.

Python

Install Playwright if needed:

python

Save this as proxy_check.py:

python

Run it:

python

Node.js

Install Playwright if needed:

javascript

Save this as proxy-check.js:

javascript

Run it:

javascript

Both examples should print a response resembling:

json

What Proxy Features Does Playwright Support?

Playwright can route browser traffic through an HTTP, HTTPS, or SOCKS5 proxy at browser or browser-context scope. Its documented proxy object has four fields.

FieldRequiredPurposeExample
`server`YesProxy scheme, hostname, and port`http://proxy.example:8080`
`username`NoUsername for HTTP proxy authentication`project-user`
`password`NoPassword for HTTP proxy authentication`secret-value`
`bypass`NoComma-separated hosts that connect directly`localhost,127.0.0.1,.internal.example`

The official Playwright network guide documents browser-wide and per-context proxy settings for HTTP(S) and SOCKSv5. The proxy API reference specifies that username and password are for HTTP proxy authentication.

Every host matched by bypass connects without the proxy. Keep the list narrow, account for redirected hostnames, and never add a target merely to make a failing proxy test pass. Otherwise, part of the workflow can expose the automation host’s direct IP.

The proxy scheme identifies the connection to the proxy, not the target page:

  • http://proxy.example:8080 can load both HTTP and HTTPS websites. For an HTTPS target, the browser normally asks the HTTP proxy to create a tunnel with CONNECT and then performs TLS through that tunnel.
  • https://proxy.example:8443 means the client-to-proxy connection itself uses TLS. Use it only when the proxy provider explicitly supplies an HTTPS proxy endpoint.
  • socks5://proxy.example:1080 asks the browser to use SOCKS5.

Do not change an HTTP proxy endpoint to https:// merely because the website URL begins with https://. The provider determines the proxy endpoint’s scheme.

For a deeper protocol comparison, see HTTP vs SOCKS5 proxies.

Versions Used in This Guide

These examples were tested on July 20, 2026 with the following versions:

ComponentTested versionNote
Playwright for Python`1.61.0`Pinned in `requirements.txt`
Playwright for Node.js`1.61.0`Pinned to match the Docker image
Python`3.11.2`Playwright currently documents Python 3.8+
Node.js`24.13.1`Current Playwright docs support the latest Node.js 22.x, 24.x, or 26.x
BrowserChrome for Testing `149.0.7827.55`Installed by Playwright 1.61.0 in the tested environment
Docker image`mcr.microsoft.com/playwright:v1.61.0-noble`Keep the package and image versions aligned

The npm playwright package had a 1.61.1 patch available at publication time. The sample intentionally pins 1.61.0 because the current official Docker tag is v1.61.0-noble.

Playwright’s Docker documentation warns that mismatched package and image versions can prevent the package from locating the expected browser executable.

When upgrading, update the package, reinstall its browser, and update the Docker image together.

Complete Project Setup

The complete project uses this structure:

bash

Start by creating an environment file:

bash

Use a neutral authenticated HTTP proxy configuration like this:

bash

Keep .env out of Git. In production, inject the same values through a CI secret store, container secret, or managed runtime configuration instead of baking them into code or images.

How to Use a Proxy With Playwright in Python

Playwright for Python exposes synchronous and asynchronous APIs. The proxy dictionary uses the same field names in both.

Install the pinned dependency and Chromium:

bash

Export the proxy settings through your shell or secrets manager before running either program. If you source a .env file, quote secrets correctly when they contain shell metacharacters.

Complete Python Sync Example

Save this as proxy_sync.py:

python

Run it after exporting the variables:

python

Expected output resembles this:

bash

198.51.100.27 is an IANA documentation address. Your output should contain the proxy’s real public exit IP.

Complete Python Async Example

Use the async API when the rest of the application already uses asyncio or when coordinating several contexts without blocking the event loop.

Save this as proxy_async.py:

python

Run it with:

python

The async API does not make one browser page intrinsically faster. Its advantage is that the application can coordinate independent I/O-bound tasks without blocking.

Limit concurrency according to the proxy pool, destination rate limits, memory, and the number of browser contexts the host can sustain.

How to Use a Proxy With Playwright in Node.js and TypeScript

Install Playwright and a TypeScript runner:

javascript

Save this complete example as proxy.ts:

javascript

Node.js 22 and later can load the environment file directly:

javascript

The JavaScript equivalent uses the same runtime calls. Remove the type-only import, ProxySettings alias, type annotations, and as { ip: string }, then save the file as proxy.mjs.

Browser-Level vs Context-Level Proxies

Playwright offers two useful proxy scopes. Neither setting is page-level.

ScopePythonNode.jsBest use
Browser-wide`chromium.launch(proxy=proxy)``chromium.launch({ proxy })`Every context and page uses one endpoint
Per context`browser.new_context(proxy=proxy)``browser.newContext({ proxy })`Each isolated worker or session can use a different endpoint

For one global Python proxy, move the dictionary from new_context() to launch():

bash

For one global Node.js proxy:

bash

Browser-wide configuration is simple and prevents accidental direct contexts. It is a good fit when a job uses one static or provider-managed gateway.

Context-level configuration is the better fit for a pool. A BrowserContext is an independent browser session with isolated cookies, cache, and storage. That makes the context a natural boundary for both application state and proxy identity.

Do not try to change a page’s proxy after creating the context. Close the old context and create a new one with the next proxy.

How to Use One Proxy per Browser Context

The following TypeScript program assigns a separate proxy to each context inside one browser process. Each page verifies the visible IP through its own context.

javascript

Expected output:

bash

The order may vary because both tasks run concurrently. A production project can read these assignments from a Git-ignored JSON file so credentials do not need to appear in source.

Use bounded concurrency in production. Opening 500 contexts at once can exhaust memory, proxy connection limits, ephemeral ports, or the target’s permitted request rate even when 500 proxy IPs are available.

How Does Playwright Proxy Authentication Work?

For an authenticated HTTP proxy, keep the endpoint and credentials separate:

bash

The equivalent Node.js configuration is:

javascript

Do not use this familiar cURL-style URL as Playwright’s server value:

bash

Playwright’s public API does not document credentials embedded in server. Its current proxy normalizer rebuilds the server from the URL protocol and host, while authentication comes from the separate username and password properties.

Use those fields even if the provider exports a combined proxy URL.

Pass passwords as their original string when using separate fields. Do not percent-encode @, :, /, or other characters as though the password were part of a URL.

http_credentials in Python and httpCredentials in Node.js are different settings. They authenticate to a website that returns 401 Unauthorized; they do not authenticate to a forward proxy that returns 407 Proxy Authentication Required.

How to Use a SOCKS5 Proxy With Playwright

An unauthenticated or source-IP-allowlisted Playwright SOCKS5 proxy needs only server:

bash

The equivalent Node.js configuration is:

bash

Playwright does not use cURL’s socks5h:// spelling. Configure socks5:// in the proxy object.

Browser DNS behavior is controlled by the browser engine and proxy path, so validate DNS behavior separately if avoiding local resolution is a requirement.

SOCKS5 Authentication Limitation

Do not add username and password to a SOCKS5 proxy object. Current Playwright source rejects the configuration before the browser navigates:

bash

The same validation applies to Python because its driver uses Playwright core. The current Playwright source code contains this explicit check.

Use one of these alternatives:

  1. Allowlist the automation server’s public IP with the proxy provider and omit username and password.
  2. Use the provider’s authenticated HTTP proxy endpoint.
  3. Put a trusted local forwarding proxy in front of the authenticated SOCKS5 upstream, then point Playwright at the local endpoint. This adds an operational component, so secure and monitor it like any other credential-bearing service.

Do not remove authentication from a publicly reachable SOCKS5 server merely to make the Playwright code connect.

How Do Sticky Sessions and Rotation Work With Playwright?

Playwright creates browser state; the proxy provider controls the exit-IP assignment. A sticky session works only when the provider maps the same endpoint or session credential to the same exit for the required duration.

The safest design is a one-to-one mapping:

bash

Some providers encode a session ID in the username. A generic example might look like this:

bash

That username syntax is provider-specific. Do not invent a suffix without checking the provider’s documentation.

Other providers expose sticky versus random behavior in a dashboard while keeping the endpoint stable. Either way, Playwright passes the credentials; it does not decide when the provider rotates the exit.

WorkflowRecommended boundary
Independent public page checksUse a new context and, when appropriate, a new exit for each task
Pagination with server-side session stateKeep one context and one sticky exit throughout the page sequence
Login, cart, checkout, or multi-step formKeep cookies and the IP address together for the entire workflow
Geo-specific testKeep one context on one verified, location-specific exit
Failed or blocked identityClose the context, retire the proxy session, and restart from a safe checkpoint

Per-request rotation can be a poor fit for browser automation. One page load can create dozens of parallel connections for HTML, JavaScript, CSS, images, APIs, and WebSockets.

If the gateway assigns a different IP to each connection, one logical page can appear to come from several addresses. Use a sticky mode for any workflow that expects continuity.

See the IP rotation guide for the operational differences between fixed, random, round-robin, per-request, and sticky rotation.

How to Use Proxidize With Playwright

Proxidize supplies the four values Playwright needs: hostname, port, username, and password.

Its dashboard can export a proxy in either of these combined formats:

bash

Or:

bash

Translate either format into separate Playwright fields.

For an HTTP endpoint, the .env file should look like this:

bash

Then run any of the complete examples without changing its code.

The current Proxidize setup documentation describes HTTP and SOCKS5 selection, generated credentials, Per-Proxy rotation intervals, and Per-GB Sticky IP or Random IP behavior.

For a long-lived Playwright context:

  • On a Per-GB access point, select Sticky IP before copying the credentials.
  • On a Per-Proxy endpoint, choose a rotation interval that is longer than the workflow or rotate manually between completed contexts.
  • If refreshing a sticky session generates new credentials, update the context assignment before creating the next context.

For a Proxidize SOCKS5 endpoint, Playwright’s SOCKS5 authentication limitation still applies.

Create an IP-whitelist access point in the Proxidize dashboard, choose SOCKS5, allowlist the automation host’s public IP, and configure:

bash

Proxidize’s residential proxy access-point documentation documents both user/password and IP-whitelist authentication, as well as HTTP, SOCKS5, Sticky IP, and Random IP options.

Remember that source-IP authentication stops working if the automation host’s public IP changes and the allowlist is not updated.

How to Verify the Visible Proxy IP

Always test from inside the browser page. This checks the same browser network path that the target website will see.

In Python:

python

In Node.js:

javascript

Expected body:

json

Compare it with a direct request from the same machine:

bash

Then test the proxy independently of Playwright:

bash

For an IP-allowlisted SOCKS5 proxy:

bash

socks5h is cURL syntax that asks the proxy to resolve the hostname. Continue to use socks5:// in Playwright.

If cURL fails, fix the endpoint, authentication, allowlist, DNS, firewall, or provider status before debugging Playwright.

If cURL works and the Playwright page fails, compare the proxy scheme and confirm that the credentials are separate fields.

Proxidize also generates a cURL test from the selected dashboard settings. For more command-line patterns, see how to use cURL with a proxy.

How to Run Playwright With a Proxy in Docker

Containerization changes three things that commonly break an otherwise correct proxy configuration:

  1. 127.0.0.1 inside the container refers to the container, not the Docker host.
  2. Proxy secrets must be injected into the running container.
  3. The installed Playwright package must match the browser binaries in the Docker image.

Node.js Dockerfile

bash

Python Dockerfile

bash

The Playwright images include browsers and operating-system dependencies, but the current official documentation says the Playwright language package itself must be installed separately.

Run the Node.js image with secrets supplied at runtime:

bash

Playwright recommends --init to handle the browser process tree correctly and --ipc=host for Chromium shared memory.

Its Docker guide also recommends running as a separate user with the supplied seccomp profile when crawling or scraping untrusted websites. The convenient root configuration is appropriate only for controlled testing against trusted pages.

Do not assume HTTP_PROXY, HTTPS_PROXY, or ALL_PROXY automatically configures page traffic. Those environment variables can affect package downloads, browser installation, Docker, and other command-line clients.

Set Playwright’s explicit proxy object for browser navigation.

If the proxy runs on the Docker host, use a host-reachable name such as host.docker.internal where supported or add an explicit host-gateway mapping. A remote Proxidize DNS hostname does not need that mapping.

Common Playwright Proxy Errors and Fixes

Start with the visible-IP URL, not the full scraping workflow. It removes login state, selectors, JavaScript behavior, and target-specific blocks from the first test.

Exact message or symptomLikely causeTestFix
`browserType.launch: Browser does not support socks5 proxy authentication``username` or `password` was supplied with `socks5://`Remove the two fields and launch againUse an IP-allowlisted SOCKS5 endpoint or an authenticated HTTP proxy
`page.goto: net::ERR_PROXY_CONNECTION_FAILED`Wrong hostname or port, dead endpoint, firewall issue, or container routing problemRun `nc -vz proxy.example 8080`, then test with cURL through the proxyCorrect the endpoint, open the route, or replace the failed proxy
`page.goto: net::ERR_TUNNEL_CONNECTION_FAILED`The HTTP proxy refused `CONNECT`, blocks the target port, or received the wrong protocolRun `curl --verbose --proxy ... https://...` and inspect the `CONNECT` exchangeUse the correct scheme or port, or ask the provider whether destination port 443 is allowed
`407 Proxy Authentication Required`Credentials are missing, incorrect, expired, or sent in the wrong formatUse the provider’s generated cURL commandPut credentials in Playwright’s separate proxy fields and reset them if needed
`net::ERR_INVALID_AUTH_CREDENTIALS`The proxy rejected the username or passwordCompare the setup with a known-good provider testCorrect the credentials; do not use website `httpCredentials` for proxy authentication
`page.goto: Timeout 30000ms exceeded.`Slow or dead proxy, authentication challenge loop, stalled TLS connection, or slow targetTest the IP-check URL and target separately, then inspect `DEBUG=pw:api` logsFix the underlying phase; increase the timeout only after confirming the request simply needs more time
`net::ERR_NAME_NOT_RESOLVED`DNS failure for the target or a bypassed hostResolve the hostname locally and compare HTTP proxy and SOCKS5 testsFix DNS or bypass rules, or use a proxy path that resolves the destination as intended
`net::ERR_CERT_AUTHORITY_INVALID`TLS interception or an untrusted certificate chainInspect the certificate through the same proxyInstall the required trusted CA in the runtime or browser environment; do not hide the problem with `ignore_https_errors`
`Target page, context or browser has been closed`Browser crash, memory pressure, premature cleanup, or mismatched Docker image and package versionsRead the browser logs and compare the installed package and image versionsAlign versions, close contexts gracefully, and correct container memory or sandbox settings

nc checks only whether a TCP port is reachable. A successful connection does not prove that the service is the expected proxy protocol or that authentication and tunneling work.

The cURL request provides the next level of evidence.

A Fast Diagnostic Sequence

bash

Stop at the first failed step.

Increasing the Playwright timeout cannot repair an invalid hostname, closed port, rejected credential, unsupported SOCKS5 authentication method, or untrusted certificate.

For detailed Playwright logs in Node.js:

javascript

For Python:

python

Do not publish logs without reviewing them for proxy hostnames, account identifiers, target URLs, cookies, query parameters, and other sensitive data.

When Should a Proxy Request Be Retried?

Retry only failures that can plausibly recover. Blind retries increase load, spend bandwidth, and can turn a target-side rate limit into a longer block.

FailureRetry?Recommended action
Invalid proxy hostname, port, or schemeNoCorrect the configuration
`407` or invalid credentialsNoRefresh or correct the credentials
Certificate validation failureNoFix the trust chain
Unsupported SOCKS5 authenticationNoChange the authentication method or protocol
One connection reset on an otherwise healthy endpointLimitedRetry with exponential backoff and jitter
Proxy health check fails repeatedlyNot on the same endpointQuarantine it and select a healthy proxy
Target returns `429 Too Many Requests`Only as directedHonor `Retry-After`, reduce domain concurrency, and review the target’s permitted rate
Navigation timeoutMaybeIdentify whether the proxy or target stalled before retrying

Keep a retry budget per task. For example, allow two connection-level retries with jitter, then retire the context and proxy session.

Do not replay a non-idempotent action such as submitting a purchase or form unless the application can prove the first attempt did not succeed.

Proxy rotation is not a substitute for respectful request pacing. Follow applicable law, site terms, authorization boundaries, robots policies where relevant, and destination rate limits when using Playwright for web scraping, testing, or monitoring.

Playwright Proxy Deployment Checklist

Before moving the integration into production, confirm all of the following:

  • The proxy scheme, hostname, and port match the provider’s dashboard.
  • HTTP proxy credentials use separate username and password fields.
  • SOCKS5 uses no Playwright username/password fields.
  • The automation host’s public IP is current when using IP allowlisting.
  • The visible-IP check returns the intended proxy exit, not the host’s direct IP.
  • The location, ASN, and IP version match the workflow’s requirements.
  • Sticky mode holds one exit for the complete multi-step workflow.
  • Context cookies and storage are not reused across unrelated proxy identities.
  • Per-request rotation is disabled for workflows that need page-level continuity.
  • Navigation, connection, and task retry budgets are bounded.
  • Proxy credentials and browser storage state are excluded from source control and logs.
  • Docker and Playwright package versions match.
  • Container DNS and routing can reach the proxy endpoint.
  • TLS verification remains enabled.
  • Contexts close before the browser so traces, HAR files, and video artifacts can flush cleanly.

Conclusion

A reliable Playwright proxy integration has three parts: the correct proxy object, the correct isolation boundary, and an independent exit-IP test.

Use browser-level configuration for one shared endpoint. Use one browser context per proxy when workers need separate identities. Keep HTTP proxy credentials in their dedicated fields, use IP allowlisting for Playwright SOCKS5 proxies, and align sticky exits with browser cookies and storage.

Test the proxy before the target, rotate between contexts rather than in the middle of a stateful workflow, and treat timeouts and retries as diagnostic signals instead of default fixes.

The result is a proxy layer that behaves predictably in Python, Node.js, local development, and Docker.

FAQ

Got questions?
We've got answers.

Quick answers to the most common questions about this topic.

Pass a proxy dictionary to chromium.launch(proxy=proxy) for a browser-wide proxy or browser.new_context(proxy=proxy) for a context-level proxy.

Keep the same provider-issued sticky credentials and browser context together until the workflow finishes, then rotate both at the intended session boundary.

No, fix the proxy scheme, certificate chain, or authorized trust configuration instead of disabling TLS certificate verification.

The usual causes are incorrectly formatted credentials, SOCKS5 authentication, different DNS behavior, or running cURL and Playwright in different network environments.

Do not rely on these environment variables for browser traffic; pass an explicit proxy object to the browser or context.

Yes, an HTTP proxy can load HTTPS websites by creating an encrypted tunnel with the HTTP CONNECT method.

Yes, close the current context and create a new context with the next proxy while keeping the browser process open.

Not directly; create a separate browser context for each page that needs a different proxy.

Yes, use server: 'socks5://host:port' with an unauthenticated or source-IP-allowlisted SOCKS5 endpoint.

Yes, Playwright supports username-and-password authentication for HTTP proxies, but not for SOCKS5 proxies.

Pass a proxy object to chromium.launch({ proxy }) for a browser-wide proxy or browser.newContext({ proxy }) for a context-level proxy.

Ready to launch?

Proxies built for real operations.

For teams that depend on stability, not luck.