Playwright Proxy Integration
Configure Databay residential and datacenter proxies in Playwright using the built-in proxy option with username and password authentication. Covers per-context proxies for rotation, country targeting, sticky sessions, and fixes for 407 errors, tunnel failures, TLS pitfalls and timeouts in Node.js and Python.
Playwright
Browser automation
Browser process
chromium.launch()
Context US
newContext()
Exit session
countryCode-us
Context DE
newContext()
Exit session
countryCode-de
Treat each authorized browser context as an isolated test workspace with its own proxy configuration, cookies and storage.
Operating principle
Treat each authorized browser context as an isolated test workspace with its own proxy configuration, cookies and storage.
What Is Playwright
Playwright is Microsoft's browser automation framework, driving Chromium, Firefox and WebKit from a single API with bindings for Node.js, Python, Java and .NET. It has become the default for new automation projects largely because of its ergonomics: auto-waiting, isolated browser contexts, and network interception are first-class. For proxy users it has a decisive advantage over both Puppeteer and Selenium: the proxy option accepts a username and password directly, so authenticated proxies work out of the box with no extensions, no auth-popup workarounds and no third-party wrappers. It is the easiest of the major browser tools to pair with a proxy network.
Connecting Playwright to Databay Proxies
Databay exposes one gateway, gw.databay.co:8888, and selects the pool, requested country, and session behavior with documented username flags. Playwright accepts the proxy object at browser launch or per context. A separate context isolates its cookies and storage; a proxy supplies a network route, not a separate person or device identity.
Residential Proxy Setup
The launch-level setup in Node.js routes the entire browser through the residential pool:
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch({
proxy: {
server: 'http://gw.databay.co:8888',
username: 'USER-zone-residential',
password: 'PASS'
}
});
const page = await browser.newPage();
await page.goto('https://httpbin.org/ip');
console.log(await page.textContent('body'));
await browser.close();
})();Keep the credentials in the username and password fields rather than embedding them in the server URL: Chromium strips credentials from proxy URLs, and the dedicated fields are how Playwright answers the gateway's authentication challenge for all three browser engines consistently.
Datacenter Proxy Setup
The API is identical in every language binding; here is the datacenter pool in Python:
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(proxy={
'server': 'http://gw.databay.co:8888',
'username': 'USER-zone-datacenter',
'password': 'PASS'
})
page = browser.new_page()
page.goto('https://httpbin.org/ip')
print(page.text_content('body'))
browser.close()Datacenter IPs are faster and cheaper per gigabyte; residential IPs come from real consumer connections and are the better fit where IP reputation is scored. A pragmatic split: datacenter for permissive, high-volume targets, residential for reputation-sensitive or geo-specific ones. Since the pool is a username flag, switching is a one-word change.
Per-Context Proxies
The current Playwright network documentation shows that browser.newContext() accepts a proxy option. Separate contexts isolate cookies and storage and can use separate documented proxy configurations; they are not separate people or device identities:
const browser = await chromium.launch();
const usContext = await browser.newContext({
proxy: {
server: 'http://gw.databay.co:8888',
username: 'USER-zone-residential-countryCode-us',
password: 'PASS'
}
});
const deContext = await browser.newContext({
proxy: {
server: 'http://gw.databay.co:8888',
username: 'USER-zone-residential-countryCode-de',
password: 'PASS'
}
});Pin Playwright and its bundled browsers together, then verify the observed exit on a non-sensitive endpoint you control. Older or vendor-patched releases may behave differently; consult the documentation for the exact pinned version instead of relying on an undocumented placeholder workaround.
Country Targeting and Sticky Sessions
Both behaviors use documented username flags. -countryCode-us requests a US-geolocated exit and -sessionId-abc123 requests short-term continuity, subject to live availability:
const context = await browser.newContext({
proxy: {
server: 'http://gw.databay.co:8888',
username: 'USER-zone-residential-countryCode-us-sessionId-abc123',
password: 'PASS'
}
});Use stickiness only when an authorized test needs continuity. It is not a dedicated device and must not be used to cross an authentication, CAPTCHA, block, or other access boundary.
Proxy Rotation Patterns
A Playwright context can carry its own proxy, cookies, and storage. Create a separate sticky session only when an authorized workflow requires that continuity, and do not rotate mid-page:
function sessionProxy() {
const id = Math.random().toString(36).slice(2, 10);
return {
server: 'http://gw.databay.co:8888',
username: `USER-zone-residential-sessionId-${id}`,
password: 'PASS'
};
}
const browser = await chromium.launch();
for (const url of approvedUrls) {
const context = await browser.newContext({ proxy: sessionProxy() });
const page = await context.newPage();
try {
await page.goto(url, { waitUntil: 'domcontentloaded' });
// ... authorized work ...
} finally {
await context.close();
}
}For parallel work, apply one source-level concurrency and request budget across the entire context pool. Stop or back off on 403, 429, or CAPTCHA responses; do not replace a context to bypass the response. The strategy behind sticky-versus-rotating choices is covered in static vs rotating proxies.
Common Errors and Fixes
Playwright surfaces proxy failures with engine-specific error strings. The four families below account for nearly all of them.
HTTP 407 Proxy Authentication Required
A 407 means the gateway rejected or never received credentials. In Playwright the common causes are credentials embedded in the server URL instead of the username/password fields, a typo in the zone or flag spelling (use the exact forms countryCode and sessionId), or stale credentials. Validate outside the browser first:
curl -x http://USER-zone-residential:PASS@gw.databay.co:8888 https://httpbin.org/ipIf curl succeeds, recheck the proxy object: server carries only scheme, host and port; everything else belongs in the dedicated fields.
ERR_TUNNEL_CONNECTION_FAILED
Chromium reports net::ERR_TUNNEL_CONNECTION_FAILED when the HTTPS CONNECT tunnel fails; Firefox may surface NS_ERROR_PROXY_CONNECTION_REFUSED. Check the endpoint spelling (gw.databay.co:8888) and username flags. If an approved health-check host works but one destination refuses the request, stop and review that destination's access rules instead of changing session identity. If the error appears only under load, reduce parallel contexts and check local sockets or file-descriptor limits.
TLS and Certificate Errors
HTTPS traffic through the gateway is tunneled end-to-end; the proxy does not re-sign certificates. Certificate errors in Playwright therefore usually trace to corporate TLS interception on your own network, a misconfigured target, or an outdated browser bundle (keep Playwright and its bundled browsers updated together). The escape hatch is ignoreHTTPSErrors: true on the context, appropriate for staging servers with self-signed certificates, but unwise as a permanent default: it silences exactly the warning that detects interception. Also remember that IP rotation does not change your TLS fingerprint; how fingerprinting interacts with proxies is explained in TLS fingerprinting and proxy detection.
Timeouts and Slow Pages
Proxy routing adds variable per-connection latency. Choose the timeout from measurements, wait for the event the authorized workflow actually needs, and omit only resources outside its scope:
context.setDefaultNavigationTimeout(60000);
await context.route('**/*', (route) => {
const type = route.request().resourceType();
return ['image', 'media', 'font'].includes(type)
? route.abort()
: route.continue();
});
await page.goto(url, { waitUntil: 'domcontentloaded' });Waiting for domcontentloaded can avoid stalling on long-lived connections. If a destination times out repeatedly, reduce concurrency and diagnose the source response; do not replace identities to route around a control.
Best Practices for Playwright with Proxies
- Treat each authorized context as one short-lived session when cookie and IP continuity are required; do not reuse a session ID concurrently.
- Stop or back off after blocks or CAPTCHAs. Do not replace the context merely to bypass the source's control.
- A
context.route()rule may omit images, media, and fonts when those assets are outside the approved scope, reducing source load and bandwidth. - Parallel country samples can support permitted localization QA, but IP country is only one location signal.
- Use accurate client settings rather than trying to conceal automation.
- A
page.goto('https://httpbin.org/ip')health check can confirm wiring and log the test exit.
Use official APIs or licensed feeds first, and apply the source's terms, robots controls, and rate guidance to the whole pool.
Questions specific to Playwright
Do per-context proxies work in all three Playwright browsers?
Can I rotate proxies without restarting the browser?
Should proxy credentials go in the server URL or the username and password fields?
Does Playwright support SOCKS5 proxies?
Should I use residential or datacenter proxies with Playwright?
Same gateway, different control surface
Choose the exit pool after the control path works. Use residential for reputation-sensitive targets or datacenter for throughput.
Ship Playwright to production
Create an account, drop in your gateway credentials, and route your first Playwright request in minutes.
Pricing, order minimums, and traffic validity vary by product.