Browser level, the simple case
Username and password are fields rather than something smuggled into a URL, so there is no authentication step to forget. This is the whole setup for a single session.
import { chromium } from 'playwright'
const browser = await chromium.launch({
proxy: {
server: 'http://gate-eu.proxies.nullvault.shop:80',
username: 'USERNAME',
password: 'PASSWORD',
},
})
const page = await browser.newPage()
await page.goto('https://api.ipify.org?format=json')
console.log(await page.textContent('body'))
await browser.close()Context level, several sessions in one browser
A context is an isolated profile with its own cookies and storage. Giving each context its own proxy means one browser process can run several unrelated sessions in parallel, which is far cheaper than launching a browser per session.
const browser = await chromium.launch()
const first = await browser.newContext({
proxy: { server: 'http://gate-eu.proxies.nullvault.shop:80', username: 'USER_A', password: 'PASS_A' },
})
const second = await browser.newContext({
proxy: { server: 'http://gate-eu.proxies.nullvault.shop:80', username: 'USER_B', password: 'PASS_B' },
})Python is the same shape
The API mirrors the JavaScript one, so the proxy dictionary carries the same three keys and behaves identically.
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(
proxy={
"server": "http://gate-eu.proxies.nullvault.shop:80",
"username": "USERNAME",
"password": "PASSWORD",
}
)
page = browser.new_page()
page.goto("https://api.ipify.org?format=json")
print(page.text_content("body"))
browser.close()Cut the traffic you are not using
On a metered plan a browser is an expensive client, because it faithfully downloads every image, font and tracker on the page. Routing those request types to abort usually removes most of the page weight and changes nothing about the HTML you came for.
await context.route('**/*', (route) => {
const type = route.request().resourceType()
if (type === 'image' || type === 'font' || type === 'media') return route.abort()
route.continue()
})What to buy
Residential sticky per session for work that has to pass as a person. Contexts make it cheap to run several of those at once, so buy on traffic rather than on how many browsers you intend to open.
Common questions
Browser level or context level?
Context level unless you have a reason not to. It gives you the same behaviour with the option of running independent sessions side by side, and it costs nothing extra to set it there instead.
Does Playwright need a separate authentication call?
No. Unlike Puppeteer it takes username and password as fields and handles the rest, which removes the single most common failure in browser proxy setups.
Can I change the proxy without restarting the browser?
Not for an existing context, but you can close it and open a new one, which is cheap. That is the normal way to move to a fresh address partway through a run.