Integrations menu
Developer guide

Playwright Proxy: Authenticated Setup per Browser Context (Node.js and Python)

ProxyField works in Playwright with one setting per browser context: give each browser.newContext() its own proxy with server: 'http://gate.proxyfield.io:7000', a username and a password, such as username: '<login>-country-us' in one context and username: '<login>-country-de-session-he9f2qga-ttl-600' in another, and each context leaves through its own authenticated IP (US rotating, Germany sticky for 10 minutes). Playwright's network docs say a proxy can be "set globally for the entire browser, or for each browser context individually"; pass the same object to chromium.launch() for the whole browser. ProxyField residential proxies cost $2.95/GB for 1 GB and fall to $1.95/GB from 1,000 GB, with a 99.6% success rate, according to our service data. Start with the Easy Trial: 1 GB for $2.95, no subscription, and the traffic never expires.

residential IPs
412M+
from, traffic never expires
$1.95/GB
Easy Trial
1 GB for $2.95
gate.proxyfield.io:7000
What goes in Playwright's proxy option
Playwright proxy keyProxyField value
serverhttp://gate.proxyfield.io:7000: HTTP, HTTPS and SOCKS5 run on the same host and port
username<login>-country-us-city-new_york; the optional keys are -country-<cc>, -region-<region>, -city-<city>, -session-<id> and -ttl-<seconds> (30 to 129,600 s, 20 min when ttl is left out); add -mobile or -dc right after the login for mobile or rotating datacenter IPs (-dc takes the country only)
passwordyour ProxyField password
Where it goeschromium.launch({ proxy }) for the whole browser, or browser.newContext({ proxy }) for one context
SOCKS5Chromium sends no SOCKS5 username or password, so for a SOCKS5 server put your IP on the allowlist and use the port you set up in the dashboard, or stay on HTTP; tools that take a proxy URL with a login write socks5h:// with the same username and password
No passwordadd the machine's IP to the allowlist (up to 100 IPv4 addresses) and use the port you set up in the dashboard; leave out username and password
IP behavioura new IP on every request, or one IP for 30 s to 36 h with -session-<id>-ttl-<seconds>
Contexts at onceunlimited concurrent threads, so every context can run at the same time
Headersthe gateway adds no Via, X-Forwarded-For or Forwarded header; the headers Playwright sends pass through; your Proxy-Authorization is removed before the request goes to the site
Credentialsin your account dashboard; the configurator generates as many proxy lines as you need

Set up Playwright with ProxyField

  1. Check the login once with curl (section 1): if curl fails, Playwright fails too.
  2. Pass proxy: { server, username, password } to chromium.launch() to send the whole browser through the gateway.
  3. Or pass it to browser.newContext() to give each context its own username and IP.
  4. Open https://api.ipify.org?format=json in a page to see the exit IP.

The whole-browser proxy in Playwright for Python, with a New York exit IP.

Python
from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(proxy={
        "server": "http://gate.proxyfield.io:7000",
        "username": "<login>-country-us-city-new_york",
        "password": "<password>",
    })
    page = browser.new_page()
    page.goto("https://api.ipify.org")
    print(page.inner_text("body"))
    browser.close()

Playwright's own guide to the proxy option: Network: HTTP Proxy (Playwright docs).

JavaScript
const us = await browser.newContext({ proxy: { server: 'http://gate.proxyfield.io:7000', username: '<login>-country-us', password: '<password>' } });
const de = await browser.newContext({ proxy: { server: 'http://gate.proxyfield.io:7000', username: '<login>-country-de-session-he9f2qga-ttl-600', password: '<password>' } });
  • On a budget: 1 GB of residential for $2.95 or 20 GB of rotating datacenter for $5.80; datacenter at $0.29/GB for sites that don't block server IPs, residential from $2.95/GB for 1 GB to $1.95/GB from 1,000 GB for most scraping; no minimum purchase (budget table).
  • Cloudflare: a residential proxy fixes only the IP signal; Cloudflare also reads the browser fingerprint, TLS signature and behavior. Keep one context on one sticky IP per visit, slow down, stay on public pages and stop when the challenge repeats; challenge pages still cost traffic (section 10).
On this page 17 sections

A different authenticated proxy per browser context

Give each context its own proxy object with server, username and password. The username carries the country and the session, so two contexts in one browser leave through two different IPs:

JavaScript
// npm i playwright && npx playwright install chromium
const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch();
  // Context 1: rotating, a new US IP on every request
  const us = await browser.newContext({ proxy: {
    server: 'http://gate.proxyfield.io:7000',
    username: '<login>-country-us',
    password: '<password>',
  } });
  // Context 2: one German IP held for 10 minutes (sticky session)
  const de = await browser.newContext({ proxy: {
    server: 'http://gate.proxyfield.io:7000',
    username: '<login>-country-de-session-he9f2qga-ttl-600',
    password: '<password>',
  } });
  for (const context of [us, de]) {
    const page = await context.newPage();
    await page.goto('https://ipinfo.io/json');
    console.log(await page.textContent('body'));
  }
  await browser.close();
})();
Read moreShow less

Expected output: two JSON objects with different IPs, the first with "country": "US", the second with "country": "DE" (ipinfo.io's fields, shortened):

{ "ip": "<US exit IP>", "country": "US", ... }
{ "ip": "<DE exit IP>", "country": "DE", ... }

The same two contexts in Python (pip install playwright), with new_context(proxy=...):

Python
from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch()
    for username in ("<login>-country-us", "<login>-country-de-session-he9f2qga-ttl-600"):
        context = browser.new_context(proxy={"server": "http://gate.proxyfield.io:7000",
                                             "username": username, "password": "<password>"})
        page = context.new_page()
        page.goto("https://ipinfo.io/json")
        print(page.inner_text("body"))  # one US object, then one DE object, with different IPs
        context.close()
    browser.close()

The proxy object takes four fields (Playwright API reference): server (http://, https:// or socks5://; no scheme means HTTP), username, password and bypass, a comma-separated list of hosts that go direct, such as bypass: 'localhost,127.0.0.1,.internal.example.com'.

FeatureWhole browserOne context
Where proxy goeschromium.launch({ proxy }) (Python: launch(proxy=...))browser.newContext({ proxy }) (Python: new_context(proxy=...))
What it affectsevery context and page of that browserthe pages of that context only
Credentialsproxy.username, proxy.passwordthe same, per context
To change itclose and relaunch the browserclose the context and open a new one; the browser keeps running
Use it forone exit for everything, quick scriptsa different country, session or account per context

Why this is short with ProxyField: one host and port for HTTP, HTTPS and SOCKS5 (gate.proxyfield.io:7000), with the country, city and session in the username, so one proxy object per context is all the code you change; there is no list of proxy endpoints to manage.

Three rules from Playwright's network docs that this code follows:

  • A proxy can be set for the whole browser or for each context. Every page in a context shares that context's proxy, so a different proxy per page means one context per page.
  • Proxy credentials go in proxy.username and proxy.password. The docs allow a username and password for an HTTP(S) proxy; httpCredentials is for HTTP authentication on the website itself, not for the proxy.
  • A context's proxy is fixed when you create it. To change the proxy, close the context and open a new one; the browser keeps running.

In Playwright Test, create the contexts from the browser fixture:

TypeScript
import { test } from '@playwright/test';

test('two exit countries', async ({ browser }) => {
  for (const cc of ['us', 'de']) {
    const context = await browser.newContext({ proxy: {
      server: 'http://gate.proxyfield.io:7000',
      username: `<login>-country-${cc}`,
      password: '<password>',
    } });
    const page = await context.newPage();
    await page.goto('https://ipinfo.io/json');
    console.log(cc, await page.textContent('body'));
    await context.close();
  }
});

Replace <login> and <password> with the credentials from your dashboard. Access opens once the payment is confirmed. The Python version is in section 3.

The code uses Playwright's stable proxy option.

Connection settings

SettingValue
serverhttp://gate.proxyfield.io:7000 (HTTP, HTTPS and SOCKS5 on the same host and port)
username<login>, plus optional targeting: -country-us, -region-new_york, -city-new_york, -session-<id>-ttl-<seconds>
passwordyour password from the dashboard
Authenticationusername:password; with the IP allowlist, the port you set up in the dashboard
Rotationa new IP on every request by default
Sticky sessions30 s to 36 h (ttl-30 to ttl-129600); 20 min when -session-<id> has no ttl; an IP idle for 120 s gets a new IP
Threadsunlimited concurrent threads
Residential, mobile or rotating datacenterresidential by default; add -mobile after the login for mobile IPs, as in <login>-mobile-country-us, or -dc for rotating datacenter, as in <login>-dc-country-us (country targeting only)
Credentialsyour account dashboard; the configurator generates as many proxy lines as you need

Best proxies for Playwright on a budget

The lowest-cost way in is 1 GB of residential for $2.95 or 20 GB of rotating datacenter for $5.80. The lowest price per GB is rotating datacenter at $0.29/GB; for most scraping, use residential at $2.95/GB for 1 GB down to $1.95/GB from 1,000 GB; and blocking images, fonts and media cuts the bytes per page (in the example below, a 10,000-page job drops from about 20 GB to about 5 GB; example inputs, not measurements). Pick the lowest-cost proxy type your target accepts, then cut the bytes each page loads. Free public proxy lists are not a budget option for Playwright: they are shared, often already flagged, and their operators can read unencrypted traffic.

Read moreShow less
TargetProxy typeProxyField priceWhy
Your own staging site, sites that don't block server IPsRotating datacenter$0.29/GB (1-49 GB), $0.27 (50-249), $0.25 (250-999), $0.22 (1,000+)The lowest price per GB
Most public-data scrapingRotating residential$2.95/GB (1-9 GB), $2.79 (10-49), $2.65 (50-99), $2.49 (100-249), $2.29 (250-499), $2.09 (500-999), $1.95 (1,000+)Home ISP IPs, city targeting
Signed-in flows that keep one IP for weeksDedicated ISPfrom $2.29 per IP for 30 daysOne fixed IP per account
Targets that treat carrier IPs differentlyMobile 5G/4G$3.45/GB (1 GB) down to $2.45/GB (1,000+ GB)Carrier IPs, same balance as residential

No minimum purchase: the smallest payment for traffic is $2.95, the price of the Easy Trial. Many providers make you buy 2 GB or more to start; with ProxyField you can buy just 1 GB, on the same pool as a 1 TB order. The tier rate applies to the whole purchase, there is no subscription, and residential, mobile and datacenter traffic never expires.

What a budget buys (the tier rate applies to the whole purchase):

BudgetResidentialDatacenter
$2.95, just testing your Playwright code1 GB at $2.95 (the Easy Trial): about 2,000 pages at 0.5 MB with images blocked–
$5.902 GB at $2.9520 GB at $0.29 ($5.80)
$50.2218 GB at $2.79186 GB at $0.27
$132.5050 GB at $2.65530 GB at $0.25

The lowest-cost order to try: rotating datacenter ($0.29/GB) first; residential when pages come back blocked; a sticky residential session or a dedicated ISP IP (from $2.29 per IP per 30 days) only for signed-in flows; mobile ($3.45/GB for 1 GB) only when residential is treated differently from carrier IPs.

What a Playwright scrape costs (example inputs, not measurements; your dashboard shows real usage):

JobTrafficDatacenterResidentialMobile
10,000 pages, full load at about 2 MB eachabout 20 GB20 × $0.29 = $5.8020 × $2.79 = $55.8020 × $3.29 = $65.80
The same 10,000 pages with images, fonts and media blocked, about 0.5 MB eachabout 5 GB5 × $0.29 = $1.455 × $2.95 = $14.755 × $3.45 = $17.25

Datacenter costs least only where the target serves server IPs normally; test it with a small purchase first and move to residential if pages come back blocked. To see which type an exit IP is, look it up on https://ipinfo.io/json: its org field names the network that owns the IP. The blocking code is in section 8.

1. Check your credentials with cURL first (30 seconds)

Run one cURL command before you write any Playwright code: if it fails, Playwright will fail too.

Shell
# Any exit IP
curl -x http://gate.proxyfield.io:7000 -U "<login>:<password>" https://api.ipify.org

# An exit IP in New York, United States
curl -x http://gate.proxyfield.io:7000 -U "<login>-country-us-city-new_york:<password>" https://api.ipify.org

You should see an IP that is not yours. Check its country with https://ipinfo.io/json, or test your proxy in the ProxyField proxy checker (up to 100 proxies per check; your list and results are not stored). More flags and SOCKS5 examples: test the proxy with cURL.

2. Set a proxy for the whole browser (Node.js)

Set proxy in chromium.launch(), and every context and page of that browser goes through it.

JavaScript
const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch({
    proxy: {
      server: 'http://gate.proxyfield.io:7000',
      username: '<login>-country-us',
      password: '<password>',
    },
  });
  const page = await browser.newPage();
  await page.goto('https://api.ipify.org?format=json');
  console.log(await page.textContent('body')); // {"ip":"<exit IP>"}
  await browser.close();
})();

Notes:

  • Playwright takes the username and password as separate fields, so special characters in the password need no URL-encoding. Don't put user:pass@ inside server.
  • A server without a scheme, such as gate.proxyfield.io:7000, is read as an HTTP proxy.
  • To send some hosts direct, add bypass: 'localhost,.internal.example' to the proxy object.
  • firefox.launch() and webkit.launch() take the same proxy option.

3. Playwright proxy in Python (sync and async)

The Python API takes the same settings as a dict: proxy= on launch() for the whole browser, or on new_context() for one context. For proxies in plain Python scripts, see Python proxy setup.

Python
# pip install playwright && playwright install chromium
from playwright.sync_api import sync_playwright

PROXY = {
    "server": "http://gate.proxyfield.io:7000",
    "username": "<login>-country-us",
    "password": "<password>",
}

with sync_playwright() as p:
    browser = p.chromium.launch(proxy=PROXY)
    page = browser.new_page()
    page.goto("https://api.ipify.org?format=json")
    print(page.inner_text("body"))
    browser.close()

This async version gives each context its own country and prints the exit IP and country of each:

Python
import asyncio
from playwright.async_api import async_playwright

def proxy_for(username):
    return {"server": "http://gate.proxyfield.io:7000", "username": username, "password": "<password>"}

async def main():
    async with async_playwright() as p:
        browser = await p.chromium.launch()
        for username in ("<login>-country-us", "<login>-country-de-session-he9f2qga-ttl-600"):
            context = await browser.new_context(proxy=proxy_for(username))
            page = await context.new_page()
            await page.goto("https://ipinfo.io/json")
            print(username, await page.inner_text("body"))
            await context.close()
        await browser.close()

asyncio.run(main())

4. A different proxy per browser context: details

Each context has its own proxy, cookies and storage, and one browser process can run many contexts at once, which is lighter than launching one browser per proxy. Set locale and timezoneId to match the exit country, so the page's language and clock agree with its IP:

JavaScript
await browser.newContext({ proxy: proxyFor('us'), locale: 'en-US', timezoneId: 'America/New_York' });
await browser.newContext({ proxy: proxyFor('de'), locale: 'de-DE', timezoneId: 'Europe/Berlin' });

Older Playwright versions needed a launch-level proxy before contexts could set their own (Chromium on Windows threw Browser needs to be launched with the global proxy). If you see that error, update Playwright, or launch with proxy: { server: 'http://per-context' } and keep the per-context settings.

5. Country, city and sticky sessions

Targeting goes in the username. ProxyField targets by country, region (state) and city, covers all 50 US states, and charges the same price per GB for every targeting. Names are lowercase with underscores.

GoalUsername
Any exit IP<login>
United States<login>-country-us
A US state<login>-country-us-region-new_york
New York, United States<login>-country-us-city-new_york
Germany<login>-country-de
A sticky session of 10 minutes<login>-country-us-session-he9f2qga-ttl-600
A sticky session of 36 hours (the maximum)<login>-country-us-session-he9f2qga-ttl-129600

A sticky IP ends when its ttl runs out, after 120 s without traffic, or when its exit node drops: the gateway then retries once with a new session, so the IP may change, and an established connection that breaks is not restored. The carrier is not a targeting option. All parameters: targeting docs.

6. Rotating proxies in Playwright

You don't rotate proxies in Playwright code: the gateway gives a new IP on every request, or keeps one IP for a sticky session of 30 s to 36 h.

  • Sticky session per context for logged-in flows, multi-step forms and any sequence of pages that must come from one IP.
  • Rotation for independent page fetches, such as one product page or one search result per job.
JavaScript
const { chromium } = require('playwright');

const jobs = ['https://api.ipify.org?format=json', 'https://api.ipify.org?format=json', 'https://api.ipify.org?format=json'];

(async () => {
  const browser = await chromium.launch();
  for (const url of jobs) {
    // One context per job: fresh cookies, fresh connection, new exit IP.
    const context = await browser.newContext({
      proxy: { server: 'http://gate.proxyfield.io:7000', username: '<login>-country-us', password: '<password>' },
    });
    const page = await context.newPage();
    await page.goto(url);
    console.log(await page.textContent('body'));
    await context.close();
  }
  await browser.close();
})();

Browsers keep their connections to the proxy open and reuse them, so requests inside one page load can leave through the same IP. Open a new context when a task needs a new IP. More on both modes: rotating proxies with sticky sessions.

7. SOCKS5 in Playwright

Playwright connects to SOCKS5 proxies with a socks5:// server, but Chromium does not send a username and password to a SOCKS5 proxy: it stops at launch with Browser does not support socks5 proxy authentication. So for SOCKS5 in Chromium, add your own IP to the allowlist in the dashboard, leave the credentials out and connect to socks5://gate.proxyfield.io:<port>, where <port> is the port you set up in the dashboard; or stay on HTTP, http://gate.proxyfield.io:7000 with your username and password, which also carries HTTPS sites.

JavaScript
const { chromium } = require('playwright');

(async () => {
  // Allowlist your own IP in the dashboard first: no username or password here.
  // <port> is the port you set up in the dashboard for your allowlisted IP.
  const browser = await chromium.launch({ proxy: { server: 'socks5://gate.proxyfield.io:<port>' } });
  const page = await browser.newPage();
  await page.goto('https://api.ipify.org?format=json');
  console.log(await page.textContent('body'));
  await browser.close();
})();

With allowlisted access there is no username to carry targeting: with the allowlist, the product, location and session are set per port in the dashboard.

8. Cut traffic: block images, fonts and media

You pay per GB, so every image, font and video a page loads through the proxy uses your balance. Block them with context.route(), and the same pages cost fewer GB.

JavaScript
const { chromium } = require('playwright');

const BLOCKED = new Set(['image', 'font', 'media']);

(async () => {
  const browser = await chromium.launch({
    proxy: { server: 'http://gate.proxyfield.io:7000', username: '<login>-country-us', password: '<password>' },
  });
  const context = await browser.newContext();

  // 1. Abort images, fonts and media before they reach the proxy.
  await context.route('**/*', (route) =>
    BLOCKED.has(route.request().resourceType()) ? route.abort() : route.continue()
  );

  // 2. Add up the bytes of every finished request.
  const sizes = [];
  context.on('requestfinished', (request) => sizes.push(request.sizes()));

  const page = await context.newPage();
  await page.goto('https://example.com', { waitUntil: 'networkidle' });

  let bytes = 0;
  for (const s of await Promise.all(sizes)) {
    bytes += s.requestHeadersSize + s.requestBodySize + s.responseHeadersSize + s.responseBodySize;
  }
  console.log(`${(bytes / 1024).toFixed(1)} KB through the proxy`);
  await browser.close();
})();

Keep scripts and stylesheets: most pages need them to render. request.sizes() counts headers and bodies as the browser sees them and leaves out connection overhead, so treat the total as an estimate. Your dashboard shows real-time usage and the gigabytes you have left.

9. Headers, user agent and stealth

Set headers for a whole context with extraHTTPHeaders and userAgent in browser.newContext(), next to its proxy, and keep Accept-Language, locale and timezoneId in line with the exit country (scraping headers guide). The ProxyField gateway adds no Via, X-Forwarded-For or Forwarded header, passes your own headers through, and removes Proxy-Authorization before the request reaches the site.

Three projects add stealth on top of Playwright, and all three take the same proxy settings:

  • playwright-extra is a Node.js wrapper that brings puppeteer-extra plugins, including the stealth plugin, to Playwright. Its last release, 4.3.6, dates from March 2023.
  • playwright-stealth is a Python port of the stealth evasions. Version 2.0.3 came out in April 2026.
  • Camoufox is a Firefox-based anti-detect browser with a Playwright-style Python API. It accepts the same proxy dict, and with geoip=True it matches its locale and timezone to the proxy's exit IP. Version 0.5.8 came out in October 2026.

More options: Puppeteer alternatives. For browser profiles managed in a desktop app: proxies for antidetect browsers.

10. How do I get past Cloudflare when scraping with Playwright and residential proxies?

A residential proxy fixes only the IP signal: Cloudflare also reads the browser's fingerprint, TLS signature and behavior, and no proxy solves a challenge. So on public pages, within the site's terms, run one context on one sticky residential IP per visit with a matching locale and time zone, go slowly, and stop when the challenge repeats:

JavaScript
const context = await browser.newContext({
  proxy: { server: 'http://gate.proxyfield.io:7000', username: '<login>-country-us-session-cf1-ttl-1800', password: '<password>' },
  locale: 'en-US',
  timezoneId: 'America/New_York',
});
Read moreShow less

Challenge pages still cost traffic. Every "Just a moment..." page and every 403 or 429 the browser downloads counts as GB: at $2.79/GB (the 10–49 GB rate), a run that mostly gets challenge pages spends balance on nothing. Stop early, and block images, fonts and media (section 8) so failed loads cost less.

The checks, in order:

  1. Check that you may collect it. Public pages only; follow the site's terms and robots.txt. If you need more than public pages at a gentle rate, use the site's API or ask the owner for access.
  2. Name what fired. A plain 403 or 429 with no page usually means a firewall rule or a rate limit; a full-page interstitial titled "Just a moment..." is a challenge; an embedded widget is Turnstile. On Cloudflare's side these come from Bot Fight Mode (free plans), Super Bot Fight Mode (Pro, Business and Enterprise), Bot Management (Enterprise, a bot score on every request), WAF custom rules and rate limiting (Cloudflare bot solutions).
  3. Keep one IP per session. Use one context with one sticky session (<login>-country-us-session-<id>-ttl-1800) for a whole visit. Cloudflare keeps a passed challenge in the cf_clearance cookie, and a new IP or a new context can bring a new challenge.
  4. Match the browser to the IP. Set locale and timezoneId to the exit country (section 4), and use a real browser channel rather than a stripped-down build.
  5. Slow down. Fewer parallel contexts per site, pauses between pages, and only the pages you need (section 8).
  6. Stop when the challenge repeats. A challenge that comes back on every page means the rule is about the browser or the behavior, not the IP; more IPs will not change it.
What you getWhat it usually meansNext step
403 or 429 with no pagea firewall rule or a rate limitslow down; check that the page is public and allowed
A full page titled "Just a moment..."a challenge on this visit (Cloudflare's interstitial challenge pages: "The visitor cannot reach their destination without passing the challenge")keep one context on one sticky IP; stop if it returns on every page
An embedded Turnstile widgetthe site asks for a check at this stepdo not automate past it; use the site's API or ask the owner

If you own the Cloudflare-protected site, don't fight your own bot rules: add a WAF custom rule with the Skip action for your test runner's IP, and in staging use Turnstile's test sitekeys: 1x00000000000000000000AA always passes, 2x00000000000000000000AB always fails, 3x00000000000000000000FF forces an interactive challenge. Cloudflare's testing page says automated suites such as Playwright "are detected as bots by Turnstile", which is why the test keys exist. What a challenge is, in Cloudflare's words: security mechanisms "to verify whether a visitor to your site is a real human" (Cloudflare challenges).

Step-by-step checks for the error page: Cloudflare 403 Forbidden. Why it happens: why Cloudflare thinks you're a bot.

11. Troubleshooting

SymptomLikely causeFix
net::ERR_PROXY_CONNECTION_FAILEDWrong host or port, or a firewall blocks port 7000, or the port you set up in the dashboard for the allowlistUse http://gate.proxyfield.io:7000 with your username and password (with the allowlist, the port you set up in the dashboard) and run the cURL check from section 1.
Every page fails or times out right after launch, while the cURL check also failsWrong or missing username or password, or your current IP is not on the allowlistCopy the credentials from the dashboard again, or add your IP to the allowlist.
net::ERR_TUNNEL_CONNECTION_FAILEDThe proxy could not open a tunnel to the site: the site is down or refused the connectionCheck the site without the proxy. Some site categories are restricted to protect the network, including financial and government services.
Browser does not support socks5 proxy authenticationusername and password set with a socks5:// server in ChromiumUse the allowlist without credentials, or switch to http://.
Wrong countryA misspelled username parameter, or a reused keep-alive connectionCheck the username against the table in section 5, and open a new context.
Your own IP shows upThe page runs in a context without a proxy, or the host is on the bypass listSet proxy on the browser or on that context, and check bypass.
The sticky IP changed mid-sessionttl ran out, 120 s passed without traffic, or the exit node droppedRaise ttl, keep the session busy, and reconnect after a broken connection.
Timeouts on heavy pagesLarge pages load slower through a remote IPBlock images, fonts and media (section 8) and raise timeout in page.goto().
Challenge pagesThe site reads the browser's fingerprint and behavior, not only the IPSee section 10. Challenge pages still use traffic, so stop the run rather than retrying.

Gateway responses for specific failures: 407 Proxy Authentication Required for a wrong login or password, an IP not on the allowlist or a malformed location, 402 Payment Required when no traffic is left and 502 Bad Gateway when no exit could be connected; a restricted site gets no separate response, and a 403 comes from the site itself. More: proxy errors. Our 24/7 live chat also helps with setup and integration.

12. Playwright Test (playwright.config)

Set proxy under use in playwright.config.ts, and every test in the project runs through it.

TypeScript
// playwright.config.ts
import { defineConfig } from '@playwright/test';

export default defineConfig({
  use: {
    proxy: {
      server: 'http://gate.proxyfield.io:7000',
      username: process.env.PF_USER, // e.g. <login>-country-us
      password: process.env.PF_PASS,
    },
  },
});

Run it with PF_USER=<login>-country-us PF_PASS=<password> npx playwright test. To use another proxy for one file, call test.use({ proxy: { ... } }) at the top of that file; for a proxy per test, create a context from the browser fixture with browser.newContext({ proxy }).

Get started

Start with the Easy Trial: 1 GB for $2.95, no minimum purchase, no subscription, and the traffic never expires. Pay in USDT, BTC, ETH and 10 other coins; the smallest payment for traffic is $2.95. All purchases are final. See pricing per GB.

Playwright Proxy FAQ

How do I use an authenticated proxy in Playwright, with a different proxy per browser context?

ProxyField works in Playwright with one setting, browser.newContext({ proxy: { server: 'http://gate.proxyfield.io:7000', username, password } }), from $1.95/GB. Each context gets its own proxy, cookies and storage, so give each its own username, such as <login>-country-us and <login>-country-de-session-he9f2qga-ttl-600; credentials go in proxy.username and proxy.password, never in httpCredentials. A context's proxy is fixed at creation: to change it, close the context and open a new one, and the browser keeps running.

What are the best proxies to use with Playwright on a budget?

ProxyField rotating datacenter proxies cost $0.29/GB down to $0.22/GB for sites that don't block server IPs, and residential proxies cost $2.95/GB for 1 GB down to $1.95/GB from 1,000 GB for most scraping: pick the lowest-cost type your target accepts. Blocking images, fonts and media cut our example 10,000-page job from about 20 GB ($55.80 residential) to about 5 GB ($14.75, or $1.45 on datacenter). There is no minimum purchase: start with 1 GB for $2.95, with no subscription and traffic that never expires.

Playwright vs Puppeteer: which is better for scraping with proxies?

Both use the same gateway. Playwright takes the username and password in its proxy option and sets a proxy per context in one line; Puppeteer needs page.authenticate() on every page. Playwright also drives Firefox and WebKit and has Python, Java and .NET APIs; see the Puppeteer proxy setup for the other side.

How do I get past Cloudflare when scraping with Playwright and residential proxies?

A residential proxy fixes only the IP signal; Cloudflare also reads the browser fingerprint, TLS signature and behavior, and no proxy solves a challenge. Check that the pages are public and the site's terms allow collection, name what fired (a plain 403 or 429, a "Just a moment..." page or a Turnstile widget), keep one context on one sticky IP per visit, slow down, and stop when the challenge repeats, because challenge pages still use traffic. If you own the site, skip your test runner's IP with a WAF custom rule and use Turnstile's test sitekeys in staging (section 10).

Do proxy credentials go in httpCredentials in Playwright?

No. Proxy credentials go in proxy.username and proxy.password; httpCredentials answers an HTTP authentication prompt from the website itself. Mixing them up makes every request fail at the proxy.

Does Playwright support proxy authentication?

Yes, for HTTP proxies. Pass username and password in the proxy option of launch() or newContext(). For SOCKS5, Chromium sends no credentials, so use an IP allowlist instead.

How do I set a proxy in Playwright Python?

Pass a dict to launch or new_context: {"server": "http://gate.proxyfield.io:7000", "username": "<login>-country-us", "password": "<password>"}. The sync and async APIs take the same dict (section 3).

How do I rotate proxies in Playwright?

Let the gateway rotate: ProxyField gives a new IP on every request by default, or a sticky session from 30 s to 36 h, chosen in the username. Open one browser context per session or per job.

Should I use a rotating or sticky residential proxy with Playwright?

Sticky for logged-in flows, multi-step forms and anything that must come from one IP; rotating for independent page fetches. A sticky session holds one IP from 30 s to 36 h (20 min if you set no ttl), and an IP idle for 120 s is replaced.

Can Playwright use a different proxy per page or context?

Per context, not per page: every page in a context shares that context's proxy. When each page needs its own IP, open one context per page; contexts are cheap compared with launching a new browser.

Show 11 more questionsShow fewer questions

Can Playwright change the proxy without restarting the browser?

Yes. Close the context and open a new one with another proxy setting; the browser keeps running. Changing only the username, for example from <login>-country-us to <login>-country-de, switches the country.

Does Playwright support SOCKS5 proxies?

Yes, with a socks5:// server, but Chromium sends no credentials to a SOCKS5 proxy and stops with Browser does not support socks5 proxy authentication. Allowlist your IP and connect to gate.proxyfield.io on the port you set up in the dashboard, or stay on HTTP, which also carries HTTPS sites.

Can an HTTP proxy open HTTPS websites in Playwright?

Yes. For an HTTPS site the browser opens a CONNECT tunnel through the HTTP proxy, and TLS runs between the browser and the site; the ProxyField gateway does not decrypt it. Use http://gate.proxyfield.io:7000 for both kinds of site.

Does Playwright use the HTTP_PROXY and HTTPS_PROXY environment variables?

Don't rely on them for page traffic: set proxy in launch(), newContext() or playwright.config so every run uses the gateway on purpose. The variables do matter when npx playwright install downloads browsers behind a corporate proxy.

Where do I put the proxy in a Playwright Test config?

Under use.proxy in playwright.config.ts, with the username and password from environment variables (section 12). test.use({ proxy: { ... } }) at the top of a file gives that file its own proxy.

Can I target specific countries or cities with Playwright?

Yes, in the username: <login>-country-us for the United States, <login>-country-us-city-new_york for New York. ProxyField targets country, region (state) and city, with all 50 US states at the same price per GB, and each context can use a different location.

How do I verify that Playwright is using the proxy?

Open https://api.ipify.org?format=json in the page and compare the IP with your own; https://ipinfo.io/json also shows its country. Run the cURL check from section 1 first if the page doesn't load.

Which proxy type works best with Playwright?

Residential proxies suit most public-data scraping. Mobile 5G/4G proxies fit targets that treat carrier IPs differently, and residential and mobile share one balance. For targets that don't block datacenter IPs, rotating datacenter proxies cost less per GB.

What is playwright-extra?

playwright-extra is a Node.js wrapper that brings puppeteer-extra plugins, including stealth, to Playwright. Its last release, 4.3.6, dates from March 2023, and it uses Playwright's own proxy settings.

What is playwright-stealth?

playwright-stealth is a Python port of the stealth evasions that hides some automation signals. Version 2.0.3 came out in April 2026; the proxy still goes in Playwright's proxy option.

What proxy format does Playwright use?

A server URL with scheme, host and port, such as http://gate.proxyfield.io:7000, plus separate username and password fields. Don't put user:pass@ inside server; a server without a scheme is read as HTTP.

Easy Trial: 1 GB for $2.95.

Try for the price of 1 GB, no subscription, traffic never expires.