Playwright Proxy Configuration: Browser Contexts and Session Management
Build a repeatable Playwright proxy workflow: configure HTTP authentication, separate browser contexts, validate the exit route and manage state without mixing independent tasks.
KAIROXO

A browser automation task has two kinds of continuity to manage: its browser state and its network route. Cookies may persist while the proxy exit changes, or an exit may remain stable while a new browser context starts with no state. A useful Playwright integration makes both choices explicit. This tutorial builds a small HTTP-proxy workflow for authorized testing, then explains how to extend it without accidentally sharing state or hiding failures.
Start with a documented route and a controlled target
Copy the gateway, protocol and complete proxy credentials generated for the selected KAIROXO product. Do not invent a universal hostname or port. Use the authentication documentation to verify the connection format, and install Playwright with the browser binaries appropriate for your test environment. Begin with one controlled page and one worker. Record which product and route configuration you selected before trying a larger automation suite.
Six steps to a repeatable browser proxy workflow
Choose the task boundary before creating a context
A context is a useful boundary for one independent browser workflow. Decide whether the next page belongs to the same task or should start with separate cookies and local storage. If a multi-step workflow needs a consistent network identity, select the documented static or sticky behavior first and measure its continuity. A browser context does not force a rotating proxy to keep the same exit. See the rotation and sticky-session guide when deciding which mode fits.
Choose a browser-level default for a uniform test suite, or pass proxy settings when creating an individual context. Make that decision visible in your test setup so later workers do not silently inherit an unintended route.
Keep HTTP proxy configuration separate from target authentication
Read the proxy server, username and password from your test environment instead of putting live credentials in source code. The server value should contain the scheme, host and port returned by the console; keep the complete generated username, including any routing parameters. Do not print this object in logs. Proxy authentication is separate from the target website’s login and from Playwright httpCredentials, which handles website HTTP authentication.
The example uses authenticated HTTP proxy settings. Playwright’s proxy documentation also describes SOCKSv5 routing, but its username/password options are documented for HTTP(S) proxies. Check the browser and provider combination rather than treating authenticated SOCKS5 as interchangeable with this example.
Save the configuration block as proxy-config.mjs in the same directory as proxy-smoke.mjs. Supply the proxy settings and TEST_URL through your environment before starting.
proxy-config.mjsjavascript const proxy = { server: process.env.PROXY_SERVER, // http://PROXY_HOST:PROXY_PORT username: process.env.PROXY_USERNAME, password: process.env.PROXY_PASSWORD,};for (const value of Object.values(proxy)) { if (!value) throw new Error("Set the proxy environment variables.");}const testUrl = process.env.TEST_URL; // an authorized test pageif (!testUrl) throw new Error("Set TEST_URL.");export { proxy, testUrl };Create a context and verify one page before adding work
Launch the browser, create a context with the chosen proxy and navigate to an authorized test URL. Check the returned HTTP status and an expected element or response; navigation completion alone is not proof that the intended content loaded. The 30-second timeout below is an example test deadline, not a product guarantee. Keep TLS validation enabled and use a page whose expected result you can recognize.
To verify the exit, visit a controlled IP-check endpoint through the same page or browser context and compare its response with your selected route. Choose the response parser for that endpoint’s documented format. Do not assume the proxy provides an undocumented echo API. Also verify the required location when your task depends on geography.
Save the browser workflow as proxy-smoke.mjs next to proxy-config.mjs, then run node proxy-smoke.mjs. Use a test page you are permitted to access.
proxy-smoke.mjsjavascript import { chromium } from "playwright";import { proxy, testUrl } from "./proxy-config.mjs"; const browser = await chromium.launch();let context;try { context = await browser.newContext({ proxy }); const page = await context.newPage(); const response = await page.goto(testUrl, { waitUntil: "domcontentloaded", timeout: 30000, }); console.log({ status: response?.status() ?? null }); // Assert a stable element or your controlled IP-check response.} finally { await context?.close(); await browser.close();}Reuse browser state deliberately, with the route configured again
For a fresh task, create a fresh context. If an approved continuation needs saved cookies and local storage, obtain storageState from your test context and supply it when creating the next one. Playwright documents storage state separately from proxy configuration. Passing state does not replace the need to configure the intended proxy route again. Do not copy state between unrelated users, sites or concurrent workflows.
Treat captured state as sensitive: it may carry usable session cookies. Keep it in memory when persistence is unnecessary, and keep any saved authentication files out of source control and shared reports. A saved state does not guarantee that the target accepts a changed IP or an expired session. Revalidate the continuation using the account and environment you are authorized to test.
Insert the continuation snippet inside the active try block of proxy-smoke.mjs, before its cleanup. It is a fragment of that workflow, rather than a separate script to run after the original context has closed.
state-continuation.mjsjavascript // Insert inside proxy-smoke.mjs try block, before context cleanup.// Capture only state from a test account you are authorized to use.const state = await context.storageState();const nextContext = await browser.newContext({ proxy, storageState: state,});try { const nextPage = await nextContext.newPage(); await nextPage.goto(testUrl, { timeout: 30000 });} finally { await nextContext.close();}Classify failures and use a bounded recovery path
Keep proxy authentication failures, target rate limits, navigation timeouts and application assertions separate in your results. A 407 response calls for checking proxy credentials; a target 429 calls for respecting its rate policy. A timeout requires evidence about the last completed stage. Follow the proxy error guide instead of changing credentials, concurrency and routes at the same time.
Use a limited retry budget and an overall task deadline. Reopening contexts or rotating exits should not become a way to ignore a target’s access rules. If a sticky route disappears, decide whether the task can safely restart; repeating a state-changing action may create duplicates even when the browser reported a failure.
Close contexts, then increase concurrency from measurements
Close the task context when its work ends and close the browser when the run finishes. A finally block makes cleanup explicit even after failed navigation. Start with a small worker limit and measure memory, usable response rate, transferred data and route continuity. A browser may load scripts, fonts and API requests in addition to the page document, so request count alone is a poor estimate of proxy traffic.
For longer network continuity, evaluate static residential ISP access; for independently routed requests, review dynamic residential access. Choose from measured task requirements and the current console options. Increasing workers should follow a capacity check, not substitute for a failing single-worker baseline.