> ## Content Index
> Fetch the complete content index at: https://semaphoreproxies.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Setting up authenticated proxies in Playwright and Puppeteer
- URL: https://semaphoreproxies.com/journal/authenticated-proxies-playwright-puppeteer/
- Published: 2026-10-09T12:00:00.000Z
- Updated: 2026-11-03T00:42:16.000Z
- Description: Launch options, per-page credentials and the one setting that quietly breaks authentication in headless mode.
- Author: Arthur Embry
- Tags: Engineering

Both libraries support authenticated proxies, but they handle the credentials differently, and the difference is where most setups go wrong.

## Playwright

Playwright takes the credentials at launch and handles the `407` challenge for you:

```
const browser = await chromium.launch({
  proxy: { server: "http://ADDRESS:PORT", username: "USERNAME", password: "PASSWORD" },
});
```

You can also pass `proxy` to `browser.newContext()` to give each context its own IP, which is the cleanest way to run one session per proxy.

## Puppeteer

Puppeteer passes the proxy to Chrome as a flag and leaves authentication to you. Chrome has no flag for credentials, so you answer the challenge per page:

```
const browser = await puppeteer.launch({ args: ["--proxy-server=ADDRESS:PORT"] });
const page = await browser.newPage();
await page.authenticate({ username: "USERNAME", password: "PASSWORD" });
```

Call `page.authenticate()` before the first navigation on every new page, including pages opened by the site itself.

## The setting that breaks it

Headless Chrome ignores proxy settings for `localhost` and, by default, bypasses the proxy for anything in `--proxy-bypass-list`. If your code sets a bypass list for development and forgets to clear it, requests silently go direct. Log the exit IP from a known endpoint at startup and assert it is not your own.

## Avoiding the challenge entirely

If you control the machine’s public IP, switch the plan to IP allowlist. Chrome then needs only `--proxy-server`, and there is no per-page authentication to forget.