# Puppeteer proxy authentication with residential and mobile IPs

> Puppeteer proxy authentication: --proxy-server plus page.authenticate(), one session per browser context, request interception to save traffic.

- URL: https://crawlrelay.com/docs/puppeteer/
- Last updated: 2026-10-13
- Publisher: CrawlRelay (https://crawlrelay.com)

Chrome takes the proxy address from a launch flag and the credentials from page.authenticate(). Use one browser context per session so credentials never leak between jobs.

**Quick answer — How do I use an authenticated proxy in Puppeteer?**

Launch Chrome with `--proxy-server=http://gw.crawlrelay.com:7777`, then call `page.authenticate({ username, password })` before the first `goto`. Chrome ignores credentials written into the flag. **CrawlRelay** residential proxies read the country and the sticky session from the username, so each page or context can have its own exit. Traffic costs $0.50/GB from 50 GB. Paid in crypto, with no KYC.

## Puppeteer setup at a glance

| Attribute | Value |
| --- | --- |
| Proxy address | `--proxy-server=http://gw.crawlrelay.com:7777` in `args`, or `proxyServer` on a browser context |
| Credentials | `await page.authenticate({ username, password })` before navigating |
| Separate sessions | `browser.createBrowserContext({ proxyServer })`: one context per session |
| SOCKS5 | Not with authentication in Chrome: use the HTTP port |
| Saving traffic | `page.setRequestInterception(true)` and abort images, fonts and media |

## How do I set up a single authenticated proxy?

This is the minimal pattern. The `try … finally` block closes Chrome even when a navigation fails, which matters on servers where orphan browsers pile up.

*Node.js (ES module): one browser, one exit*

```javascript
import puppeteer from "puppeteer";

const browser = await puppeteer.launch({
  args: ["--proxy-server=http://gw.crawlrelay.com:7777"],
});
try {
  const page = await browser.newPage();
  await page.authenticate({ username: "USERNAME-country-us", password: "PASSWORD" });
  await page.setRequestInterception(true);
  page.on("request", (req) =>
    ["image", "font", "media"].includes(req.resourceType()) ? req.abort() : req.continue()
  );
  const res = await page.goto("https://example.com/", { waitUntil: "domcontentloaded", timeout: 60000 });
  console.log(res.status(), await page.title());
} finally {
  await browser.close();
}
```

## How do I run several sessions or countries in one browser?

Create one browser context per session. A context is an isolated profile with its own cookies, cache and network state, so the credentials you give one context do not leak into another. Give each context a username with its own country or session ID.

*Node.js: one context per sticky session*

```javascript
import puppeteer from "puppeteer";
import { randomUUID } from "node:crypto";

const GATEWAY = "http://gw.crawlrelay.com:7777";
const browser = await puppeteer.launch();

async function visit(country, url) {
  const session = randomUUID().replaceAll("-", "").slice(0, 10);
  const context = await browser.createBrowserContext({ proxyServer: GATEWAY });
  try {
    const page = await context.newPage();
    await page.authenticate({
      username: `USERNAME-country-${country}-session-${session}-ttl-20`,
      password: "PASSWORD",
    });
    await page.goto(url, { waitUntil: "domcontentloaded", timeout: 60000 });
    return { country, session, ip: await page.evaluate(() => document.body.innerText.trim()) };
  } finally {
    await context.close();
  }
}

try {
  const results = await Promise.all([
    visit("us", "https://api.ipify.org"),
    visit("gb", "https://api.ipify.org"),
  ]);
  console.table(results);
} finally {
  await browser.close();
}
```

## Why does Puppeteer show a 407 or ERR_TUNNEL_CONNECTION_FAILED?

Because Chrome sent no credentials, or the wrong ones. Check three things:

1. `page.authenticate()` runs **before** the first `goto` on that page.
2. The `--proxy-server` flag or `proxyServer` holds only the scheme, host and port, with no `user:pass@` part.
3. The username has no typo in its targeting part: test it with curl first, as shown on the [407 page](https://crawlrelay.com/docs/errors/407-proxy-authentication-required/).

If curl succeeds with the same username and password and Puppeteer still fails, read [ERR_TUNNEL_CONNECTION_FAILED](https://crawlrelay.com/docs/errors/err-tunnel-connection-failed/).

## How much traffic does a Puppeteer page cost?

Everything Chrome downloads is billed: the HTML, scripts, styles, images, fonts and the API calls the page makes. The HTTP Archive Web Almanac 2025 measured a median page weight of 2,164 KB on mobile and 2,412 KB on desktop. Blocking images, fonts and media with request interception usually cuts that to a few hundred kilobytes, and returning cached responses for repeated scripts cuts it further. Use [rotating mobile IPs](https://crawlrelay.com/mobile-proxies/) only for the pages that need them: mobile traffic costs $1.50/GB from 5 GB, residential $0.50/GB from 50 GB.

## Puppeteer and proxies: questions

### Can I put the username and password in --proxy-server?

No. Chrome ignores credentials in the `--proxy-server` flag, and the first HTTPS request then fails with a 407 hidden behind `ERR_TUNNEL_CONNECTION_FAILED`. Put only `http://host:port` in the flag and pass the credentials with `page.authenticate()` on every new page.

### How do I rotate the IP between pages in Puppeteer?

Open each page in a new browser context, or give each page a username without a session ID. A new context opens new connections, and each new connection usually gets a different residential exit. Within one page, Chrome reuses connections, so requests to the same site often share an exit until the connection closes.

### Does page.authenticate() work with request interception?

Yes. Puppeteer handles the proxy's authentication challenge itself, and your interception handler only needs to call `continue()` or `abort()` on each request. Set up `authenticate()` first, then turn interception on, as in the first example.

### Should I use puppeteer-extra stealth plugins with proxies?

We do not document or support tools meant to hide automation or defeat bot detection. Their purpose is to get past a site's decision to filter automated visitors, which our [Acceptable Use Policy](https://crawlrelay.com/acceptable-use/) does not allow. Render public pages at a polite pace and use official APIs where sites provide them.

### Which Chrome does Puppeteer use with the proxy?

Recent Puppeteer versions download a matching Chrome for Testing build and use it by default. The proxy flags and `page.authenticate()` work the same way in it as in regular Chrome. If you point Puppeteer at your own Chrome with `executablePath`, keep that browser up to date.

**Run Puppeteer through residential IPs** $5.94 for 10 GB, $0.50/GB from 50 GB. [See pricing](https://crawlrelay.com/pricing/) · [Node.js guide](https://crawlrelay.com/docs/node/)

---

CrawlRelay: CrawlRelay is a developer-first rotating residential and 4G/5G mobile proxy service for scrapers and AI data pipelines: non-expiring pay-as-you-go traffic from $0.50/GB, paid in crypto, with no ID upload. No KYC — no ID, no selfie, no documents. Pay in crypto.
