Web Scraping & Automation

Playwright Proxies: Setup, Authentication and Per-Context Proxies

How to use proxies with Playwright in Node.js and Python: launch-level and context-level proxies, authentication, SOCKS5, rotating proxies, bypass lists and troubleshooting.

By Team of Monkeys Editorial Updated 5 min read Affiliate disclosure

This guide contains affiliate links to Geonode, Webshare and Rayobyte. If you buy through them we may earn a commission, at no extra cost to you.

Playwright proxies setup illustration showing a Playwright script assigning authenticated proxies to each browser context 3jdej38j4

Playwright's built-in proxy support

Playwright, Microsoft's browser automation library for Chromium, Firefox and WebKit, has first-class proxy support. Unlike Puppeteer, where authentication needs page.authenticate(), Playwright accepts a username and password directly in its proxy configuration, and it supports separate proxies per browser context out of the box.

John Watson Rooney shows how to plug proxies into both Python Requests and Playwright. Video: John Watson Rooney on YouTube

Launch-level proxy (Node.js)

javascript
import { chromium } from 'playwright';

const browser = await chromium.launch({
  proxy: {
    server: 'http://gate.example.com:7777',
    username: 'customer-USER-country-us',
    password: 'PASS',
  },
});
const page = await browser.newPage();
await page.goto('https://httpbin.org/ip');
console.log(await page.textContent('body'));
await browser.close();
Our editorial team, hard at work on your proxy questions (animated GIF) 3jdej38j4
Our editorial team, hard at work on your proxy questions. GIF via Tenor

Launch-level proxy (Python)

python
from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(proxy={
        "server": "http://gate.example.com:7777",
        "username": "customer-USER-country-us",
        "password": "PASS",
    })
    page = browser.new_page()
    page.goto("https://httpbin.org/ip")
    print(page.text_content("body"))
    browser.close()
A Python tutorial on rotating proxies for web requests, showing a simple rotation loop you can adapt. Video: NeuralNine on YouTube

Per-context proxies

Each browser context can have its own proxy, which is ideal for running several identities or locations in one browser:

javascript
const browser = await chromium.launch();
const us = await browser.newContext({
  proxy: { server: 'http://gate.example.com:7777', username: 'customer-USER-country-us', password: 'PASS' },
  locale: 'en-US',
  timezoneId: 'America/New_York',
});
const de = await browser.newContext({
  proxy: { server: 'http://gate.example.com:7777', username: 'customer-USER-country-de', password: 'PASS' },
  locale: 'de-DE',
  timezoneId: 'Europe/Berlin',
});

Note the locale and timezoneId options: Playwright makes it easy to match the browser to the proxy's location, which reduces fingerprint mismatches. See browser fingerprinting and proxies.

On older Playwright versions with Chromium on Windows, per-context proxies required launching the browser with a placeholder global proxy (for example proxy: { server: 'http://per-context' }). Current versions don't need this, but keep it in mind if you're on an old release.

SOCKS5

javascript
const browser = await chromium.launch({ proxy: { server: 'socks5://203.0.113.10:1080' } });

As with Puppeteer, SOCKS5 authentication isn't supported by Chromium in Playwright; use IP whitelisting or a local forwarder. See SOCKS5 proxies.

Bypassing the proxy for some hosts

javascript
proxy: { server: 'http://gate.example.com:7777', bypass: 'localhost,.internal.example.com' }

Rotating proxies in Playwright

Create a new context per session with a new session ID (for rotating residential) or the next proxy from your list (for static proxies):

javascript
const newSession = () => `customer-USER-country-us-session-${Math.random().toString(36).slice(2, 10)}`;

async function scrape(browser, url) {
  const ctx = await browser.newContext({
    proxy: { server: 'http://gate.example.com:7777', username: newSession(), password: 'PASS' },
  });
  try {
    const page = await ctx.newPage();
    const res = await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 45000 });
    return { status: res?.status(), html: await page.content() };
  } finally {
    await ctx.close();
  }
}

See proxy rotation strategies.

Proxy tip: If you need a pool to run this against, Geonode works with every tool in this guide: rotate per request for stateless pages, or hold a sticky session for logins and pagination. See using Geonode with Playwright for working code.

Saving bandwidth

Block heavy resources with routing:

javascript
await ctx.route('**/*', (route) => {
  const t = route.request().resourceType();
  return ['image', 'media', 'font'].includes(t) ? route.abort() : route.continue();
});

On per-GB residential proxies, this can cut costs dramatically.

Troubleshooting

ProblemFix
407 Proxy Authentication RequiredCheck username/password; ensure they're in the proxy object, not the server URL
ERR_PROXY_CONNECTION_FAILEDWrong host/port or scheme
Per-context proxy ignoredUpdate Playwright; on old versions use the per-context placeholder
SOCKS5 fails with credentialsWhitelist IP or use a forwarder

See common proxy errors.

Playwright vs Puppeteer for proxies

PlaywrightPuppeteer
Auth in configYesNo (page.authenticate())
Per-context proxyYes, matureYes, in recent versions
Locale/timezone per contextBuilt inVia page emulation
BrowsersChromium, Firefox, WebKitChrome/Chromium (Firefox experimental support)

Playwright proxy patterns by use case

Use casePattern
One proxy for everythingLaunch-level proxy
Many locations in parallelOne context per location with its own proxy, locale and timezone
Rotating residentialNew context per session with a new session ID
Logged-in accountsOne persistent context per account (launchPersistentContext) with a static ISP proxy
Mixed proxies and direct trafficbypass list for internal hosts

Persistent contexts for accounts

For workflows that need cookies to survive between runs, use a persistent context with a dedicated proxy:

python
from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    ctx = p.chromium.launch_persistent_context(
        user_data_dir="profiles/account-01",
        proxy={"server": "http://203.0.113.21:8000", "username": "u", "password": "p"},
        locale="en-GB",
        timezone_id="Europe/London",
    )
    page = ctx.new_page()
    page.goto("https://example.com/account")
    ctx.close()

Each account keeps its own profile directory and static IP. See static residential proxies.

Checking the exit location per context

javascript
async function exitInfo(context) {
  const page = await context.newPage();
  await page.goto('https://ipinfo.io/json');
  const info = JSON.parse(await page.textContent('body'));
  await page.close();
  return info; // { ip, city, region, country, org, timezone }
}

You can use the returned timezone to set up a new context with matching settings, which reduces fingerprint mismatches. See browser fingerprinting and proxies.

Budget tip: Webshare is easy to plug into the tools in this guide: point your client at its backbone gateway and add a rotate or session suffix to the username, or download a direct proxy list and rotate it yourself. See using Webshare with Playwright.

Firefox and WebKit

Playwright's proxy options work across Chromium, Firefox and WebKit, which lets you vary browser engines as part of your fingerprint strategy. Behaviour details (such as SOCKS authentication) can differ by engine, so test each.

For more on browsers and proxies, see headless browser proxies and our Puppeteer proxies guide.

Playwright and proxies in test suites

Playwright Test can set a proxy in the config so every test runs through it, useful for testing your own site from another region:

javascript
// playwright.config.js
import { defineConfig } from '@playwright/test';
export default defineConfig({
  use: {
    proxy: { server: 'http://gate.example.com:7777', username: process.env.PROXY_USER, password: process.env.PROXY_PASS },
    locale: 'de-DE',
    timezoneId: 'Europe/Berlin',
  },
});

Define separate projects for different regions (each with its own proxy, locale and timezone) to run the same tests across markets. For QA of your own sites, datacenter proxies in each region are usually sufficient and cheap.

Residential tip: For lenient targets, Rayobyte rotating datacenter traffic costs about $0.30 per GB pay as you go, and you can move only the blocked domains to residential. Our guide to using Rayobyte with Playwright shows the setup.

Debugging proxy problems with the trace viewer

When a proxied Playwright run fails, the trace viewer often shows why faster than log statements. Record a trace around the failing flow:

javascript
const context = await browser.newContext({
  proxy: { server: 'http://gate.example.com:7777', username: 'USER', password: 'PASS' },
});
await context.tracing.start({ screenshots: true, snapshots: true });
const page = await context.newPage();
await page.goto('https://example.com');
await context.tracing.stop({ path: 'trace.zip' });

Open it with npx playwright show-trace trace.zip. The Network tab lists every request with its status and timing, so you can see:

  • Which requests failed and with what status. A wall of 407s points to credentials; 403s on the main document point to the target.
  • Whether a challenge page was served instead of content, from the snapshots.
  • Slow requests that suggest a slow exit, or resources you should be blocking to save bandwidth.

Keep traces off in normal runs, since they're large, and turn them on for failing jobs or a small sample. Treat trace files as sensitive: they can contain cookies and page content.

The official guide to Playwright's proxy settings covers the options used above. For errors and their meanings, see common proxy errors, and for comparing frameworks, headless browser proxies.

If you're deciding between Webshare and Geonode here, see Webshare vs Geonode for Playwright for a side-by-side look at products, pricing and setup.

Webshare users can follow Using Webshare Proxies with Playwright for a step-by-step version of this, including plan sizing and common errors.

For a third option, read Using Rayobyte Proxies With Playwright; our Rayobyte vs Geonode vs Webshare for Playwright comparison shows where Rayobyte, Geonode and Webshare each come out ahead.

Key takeaways

  • Playwright accepts proxy server, username and password directly at launch or per context.
  • Per-context proxies, with matching locale and timezoneId, make multi-location work straightforward.
  • SOCKS5 authentication isn't supported in Chromium; use IP whitelisting or a forwarder.
  • Rotate by creating a new context per session; block heavy resources with routing to save bandwidth.
  • Persistent contexts with static ISP proxies suit logged-in accounts. See headless browser proxies.

Choosing a provider for Playwright? Our guide to the best proxies in 2026 compares the proxy types that suit browser automation.

FAQ

Can Playwright use a different proxy for each page?

Per context, yes. Pages in the same context share the context's proxy.

Does Playwright work with residential proxies?

Yes, with any HTTP(S) proxy. Use sticky sessions per context.

What are the best proxies for Playwright?

Same as for Puppeteer: rotating residential with sticky sessions for protected sites, ISP for logged-in sessions, datacenter for lenient sites. See best proxies for web scraping.

Sources and further reading

Independent references that back up the points above, from standards bodies, governments, universities and non-profits. They open in a new tab.

Affiliate disclosure: Team of Monkeys is an affiliate of Geonode, Webshare and Rayobyte. Links and banners marked as sponsored, and links to Geonode, Webshare and Rayobyte in the text, use our referral links, and we may earn a commission if you buy through them, at no extra cost to you. Our explanations and comparisons are written to be useful whichever provider you choose.

Editorial note: Proxy providers change their pools, features and prices often, so treat any figures here as typical ranges at the time of writing and confirm current terms with the provider before you buy.