OP-Proxy
PricingBlogResellerAPI
Dashboard
← Blog
Setup·August 9, 2026·4 min read

Proxies in Playwright and Puppeteer: setup, authentication and per-context IPs

Browser automation has two quirks everyone trips over: Chromium will not take a password from the launch argument, and a proxy can be set per context rather than per browser. The second lets one process work with several addresses at once.

In this article

  • The two levels a proxy can be set at
  • Playwright: credentials right in the option
  • Puppeteer: the password goes in a separate call
  • Why IP authentication is easier here
  • How many contexts to open
  • When you do not need a browser
  • What to disable so the browser stops eating your limit

The two levels a proxy can be set at

A proxy can be given at browser launch, applying to everything, or when creating a context. A context in these libraries is an isolated session with its own cookies and storage, and each one can have its own address. For data collection that beats a single shared proxy: profiles overlap neither in state nor in address.

Playwright: credentials right in the option

Here it is straightforward: username and password go in the same setting as the address, and this works both at launch and per context.

javascript
import { chromium } from 'playwright'

// Playwright takes the username and password in the same option as the address,
// both at launch and per browser context.
const browser = await chromium.launch({
  proxy: { server: 'http://GATEWAY:PORT', username: 'LOGIN', password: 'PASSWORD' },
})

// A separate address per context: one browser then works
// through several IPs at the same time.
const ctx = await browser.newContext({
  proxy: { server: 'http://GATEWAY:PORT', username: 'LOGIN', password: 'PASSWORD' },
})
const page = await ctx.newPage()
await page.goto('https://example.com')
A caveat about SOCKS5: login authentication for it is unreliable in the browser — the documentation promises it only for HTTP proxies. If you need SOCKS5 in a browser, plan on IP authentication.

Puppeteer: the password goes in a separate call

Chromium ignores credentials passed in the launch argument and shows a native authentication dialog instead — the driver will not fill it in, and the page simply never loads. So credentials go in a separate call, and it must happen before navigating.

javascript
import puppeteer from 'puppeteer'

// Chromium ignores credentials passed in --proxy-server: it shows a native auth
// dialog that the driver will not fill in. Credentials go in a separate call.
const browser = await puppeteer.launch({
  args: ['--proxy-server=http://GATEWAY:PORT'],
})
const page = await browser.newPage()
await page.authenticate({ username: 'LOGIN', password: 'PASSWORD' })  // before goto
await page.goto('https://example.com')

// A separate context with its own proxy; credentials still via page.authenticate
const ctx = await browser.createBrowserContext({
  proxyServer: 'http://GATEWAY:PORT',
  proxyBypassList: ['127.0.0.1'],
})

Why IP authentication is easier here

Both frameworks need extra steps to pass a password, and with SOCKS5 it may not work at all. Whitelist authentication removes the question entirely: the machine's address is added once and the browser connects with no credentials, regardless of framework or protocol.

Both schemes are active at once here, so this is not a trade-off: browser jobs on a server go by whitelist while scripts from other machines keep using the login.

How many contexts to open

It is easy to overestimate here. One context with an open page holds not one connection but several: the document itself, images, scripts, API calls. So context count does not equal your plan's thread count — it is considerably lower.

  • Reckon on 5–10 concurrent connections per active context loading a full page.
  • A 50-thread plan comfortably holds 5–8 contexts, not fifty.
  • Blocking unneeded resources — images, fonts, analytics — cuts connection use several times over.

That last point is worth doing first: for collecting prices or text you do not need images or fonts, and they account for most of the connections and traffic.

When you do not need a browser

Before launching Chromium, check whether you need it: a browser consumes several times more connections and memory than a plain request. For pages where the data arrives in a separate JSON response, a browser is not needed at all.

javascript
// Proxy from environment variables, no libraries needed.
// The flag and the variable arrived in recent Node versions and are marked as
// actively developing — check that your version supports them.
//   node --use-env-proxy script.js
//   NODE_USE_ENV_PROXY=1 node script.js
// Applies to fetch(), http.request() and https.request().

// An explicit address in code requires installing undici:
import { fetch, ProxyAgent } from 'undici'
const agent = new ProxyAgent({ uri: 'http://GATEWAY:PORT' })
await fetch('https://example.com', { dispatcher: agent })

// axios: the proxy option works in Node ONLY, and a custom httpAgent or
// httpsAgent overrides it — set an agent and the option is ignored.
// proxy: false disables the proxy and also ignores environment variables.

Two traps in that snippet deserve attention. The proxy option in axios works server-side only — in a browser build it silently does nothing. And it stops applying if you set your own agent: the agent overrides the option, without warning.

What to disable so the browser stops eating your limit

This is the single most effective change available: for collecting prices or text you do not need images, fonts or analytics, and those account for most of the connections and traffic. Blocking unneeded resource types cuts usage several times over, not by a few percent.

  • Images and fonts — almost always surplus for data collection.
  • Analytics and advertising scripts — they open connections to third-party hosts absent from your arithmetic.
  • Media and font downloads — the heaviest class by traffic.
Measure usage empirically rather than by context count: open one context on a typical target page and look at the network request list. The real number of connections is almost always higher than expected, and that is the number to plan from.

A pool for browser automation

HTTP and SOCKS5, whitelist authentication for headless browsers. IPv6 from 650 ₽ for 50 threads.

View pricing

Proxies for this job

  • For parsing and scraping

Check it with our tools

  • Anonymity check
  • DNS leak test

Read next

  • Automating proxies over the API: whitelist, purchase and renewal from a scriptA PUT to the whitelist replaces the whole list rather than adding to it — that is how people lock themselves out. A walkthrough of our API: the key and its limits, updating an address from cron, purchase and renewal, error codes.
  • Authenticated proxies in Selenium: why every old recipe brokeAcross 2025 Chrome removed four separate things, and each one breaks a different line of the decade-old tutorial. What actually broke, what MV3 did not lose, and four routes that work today.
  • Proxies in Key Collector: why account modules need static addresses, not rotationThe program splits into modules, and the right proxy differs per module. An account pins one address until restart, Google.Ads rejects IPv6 and SOCKS, and the browser handler drops SOCKS entirely.
OP-Proxy
Plans & Information
PricingBlogReseller programAPITerms of ServicePrivacy Policy
Proxies by use case
For parsing and scrapingFor multi-threaded softwareFor marketplacesFor antidetect browsersFor captcha softwareFor SEO and SERP checksRotating IPv6 and IPv4IPv6 proxiesStatic datacenter IPv4
Tools
My IP AddressSpeed TestAnonymity CheckWHOIS LookupDNS Leak TestWebsite Check
ИП Артамонов Анатолий Михайлович ОГРНИП 324700000026212 ИНН 701755408691