
A Playwright residential proxy is a Playwright browser context whose every request — document, XHR, WebSocket upgrade — leaves through an IP that an ISP assigned to a household, not through the machine that launched Chromium. You configure it with a proxy object: server, username, password. You do not embed user:pass@host in the server string. Chromium strips that userinfo and answers 407, which looks like a network failure and wastes a morning.
This is the long guide. The copy-paste card lives at /integrations/playwright. If the page loaded and the scraper still “succeeded” with empty HTML, that is a different bug: Playwright silent 403.
Why Playwright needs a residential exit
Playwright already looks more like a browser than requests does. That does not make the exit IP look like a household. Launching Chromium on a GitHub runner, an AWS box, or a Hetzner VPS still presents a datacenter ASN. CDNs classify that ASN in the handshake. A stealth plugin will not rewrite the autonomous system. Pairing Playwright with a datacenter proxy is the most common expensive mistake in 2026: you pay for a full browser and then donate the session to a range that Cloudflare already scored as automation.
A residential exit changes the trust class. Aethyn Premium (proxy.aethyn.io:2099) is the volume pool with country targeting. Elite (:5499) adds city and ISP when the target is hard. Both are residential; Aethyn does not sell a datacenter SKU to “try first.” If the page is unprotected, you may not need a browser at all — see residential vs datacenter. If you are already in Playwright, put a residential IP on the context.

Credentials go in fields, never in the URL

Python:
Code Snippetfrom playwright.sync_api import sync_playwright with sync_playwright() as p: browser = p.chromium.launch(proxy={"server": "per-context"}) context = browser.new_context( proxy={ "server": "http://proxy.aethyn.io:2099", "username": "aethyn-XXXXX-country-us", "password": "PASSWORD", } ) page = context.new_page() page.goto("https://httpbin.org/ip") print(page.content()) context.close() browser.close()
Node.js:
Code Snippetimport { chromium } from "playwright"; const browser = await chromium.launch({ proxy: { server: "per-context" } }); const context = await browser.newContext({ proxy: { server: "http://proxy.aethyn.io:2099", username: "aethyn-XXXXX-country-us", password: "PASSWORD", }, }); const page = await context.newPage(); await page.goto("https://httpbin.org/ip"); console.log(await page.content()); await context.close(); await browser.close();
Replace aethyn-XXXXX and PASSWORD from the dashboard. Elite HTTP is port 5499; Premium SOCKS5 is socks5://proxy.aethyn.io:1099. Targeting suffixes live on the username: country, optional city/ISP (Elite), optional -session-ID-lifetime-N.
The short integration card at /integrations/playwright launches with the proxy on chromium.launch() — that is correct when every context shares one exit. The placeholder pattern above is what you need for many identities in one process.
Rotate by creating a new context

Playwright reads proxy when the context is created. There is no context.setProxy() that you call mid-job. Per-request rotation on a rotating residential gateway happens because each new TCP connection can draw a new IP — but a browser context reuses connections, cookies, and service workers. If you need a fresh identity, close the context and open another with a new -session- token (or omit session for a random exit). If you need the same identity across pagination, put -session-job42-lifetime-30 on the username and keep that context alive for the job.
Sticky lifetime on Aethyn is 1–1440 minutes. Default is 30 if you omit -lifetime-N. That is a gateway hold, not a Playwright setting. When the TTL expires, the next request on that session id may land on a new household. Build a retry that opens a fresh context rather than assuming the IP is nailed to the wall for 24 hours.
Match locale, timezone, and geolocation to the exit

A US Elite exit with locale: "ja-JP" and a Tokyo timezone is a gift to bot management. Set locale, timezoneId, and geolocation (plus permissions) to the country you encoded in the username. Keep the User-Agent and viewport stable for the life of that context. Switching UA on a sticky IP is a louder tell than rotating the IP under a stable UA.
Python sketch:
Code Snippetcontext = browser.new_context( proxy={ "server": "http://proxy.aethyn.io:5499", "username": "aethyn-XXXXX-country-us-city-newyork-session-nyc1-lifetime-30", "password": "PASSWORD", }, locale="en-US", timezone_id="America/New_York", geolocation={"longitude": -74.006, "latitude": 40.7128}, permissions=["geolocation"], )
City and ISP suffixes require Elite. Premium is country-only. If the city does not resolve, the tunnel falls back to the country — see targeting docs.
Save gigabytes (you pay for them)
Playwright will happily download every image, font, and tracker. On residential, that is the bill. Abort what the parser does not need:
Code Snippetcontext.route("**/*.{png,jpg,jpeg,gif,webp,svg,woff,woff2}", lambda route: route.abort())
Then measure cost per successful request on a sample. A headed run that loads a 4 MB homepage to extract one JSON blob is how teams “prove” residential is expensive.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| 407 | Credentials in the URL, or username/password swapped | Fields only; rebuild from the dashboard |
| Context proxy ignored | Launched Chromium with no proxy | launch({ proxy: { server: "per-context" } }) |
net::ERR_TUNNEL_CONNECTION_FAILED | Wrong port or scheme | HTTP 2099/5499; SOCKS5 1099/3499 |
| Page 200, empty/challenge body | Soft block | Assert selectors; see silent 403 |
| Works once, then 403 | Sticky reused too hard, or datacenter leftover | New context; Elite if Premium is scored |
Do not throw both IP tier and fingerprint stack in one panic change. Change one, measure, then the other. Public-data collection only — this page does not teach CAPTCHA solving.
Common questions about this article
How do I set a proxy in Playwright?
Why is my Playwright per-context proxy ignored?
Should I rotate IPs inside one Playwright context?
How long can a Playwright sticky session last on Aethyn?
Does Playwright work with SOCKS5 residential proxies?
Guides, integrations & docs
Continue reading

Playwright Silent 403: Your Scraper Was Blocked Quietly
Playwright page.goto returns status 403 and raises nothing; Selenium is quieter still. Build an explicit classify step so anti-bot pages stop looking like missing selectors.

Residential vs Datacenter Proxies: Which One Should You Use?
A residential proxy is an ISP-assigned household IP; a datacenter proxy is a cloud-hosted server IP. Compare trust, speed, cost, and when to switch — Aethyn sells residential only.

Residential Proxy Pricing in 2026: What You Actually Pay per GB
Residential proxy pricing is the published euros or dollars you pay per gigabyte of household-ISP traffic. Here is a dated 10 / 50 / 100 GB sticker table — then why sticker is not the bill.
Run Playwright through real household IPs
Premium HTTP 2099 for volume. Elite 5499 when the target scores the exit. Sticky 1–1440 minutes in the username. Free trial, no card.