No KYC — no ID, no selfie, no documents. Pay in crypto: BTC, USDT, USDC, ETH, SOL, LTC
Language: English
Get started

Docs · Puppeteer · Chrome for Testing

Puppeteer proxy authentication with residential and mobile IPs

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.

Last updated: · 4 min read

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

Proxy address--proxy-server=http://gw.crawlrelay.com:7777 in args, or proxyServer on a browser context
Credentialsawait page.authenticate({ username, password }) before navigating
Separate sessionsbrowser.createBrowserContext({ proxyServer }): one context per session
SOCKS5Not with authentication in Chrome: use the HTTP port
Saving trafficpage.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
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
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.

If curl succeeds with the same username and password and Puppeteer still fails, read 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 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 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.

From $0.50/GB · no KYC

Get started