Use a residential proxy in Puppeteer: --proxy-server and page.authenticate

A common Puppeteer pattern is --proxy-server at launch, then page.authenticate on each page. Console credentials; fake placeholders. Not a Playwright or antidetect guide. Not for mainland China.

A common Puppeteer pattern is --proxy-server at launch, then page.authenticate on each page. Console credentials; fake placeholders. Not a Playwright or antidetect guide. Not for mainland China.

Copy protocol, host, port, and auth from the console, then put them in Puppeteer. A common pattern is `--proxy-server` for host and port at launch, then `page.authenticate` on every `page` before `goto`. That is not the same API as Playwright’s `launch({ proxy })`; see Playwright residential proxy. HTTP from Node: Axios setup. Antidetect field mapping: antidetect setup.

ZTProxy sells rotating residential (per GB) and static residential (per IP·month). Examples use fake placeholders—not production hosts. Authorized targets only. Not for mainland China.

What to have ready

Ready itemSource
Protocol, host, port, authConsole values only (not the fake placeholders)
Node.js and `puppeteer`Your local environment
Check URLA page you may access
Rotating or static orderRotating vs static

Placeholders (not production): host `proxy.example.invalid`, port `10000`, user `USER_EXAMPLE`, password `PASS_EXAMPLE_NOT_REAL`. Protocol and strings: HTTP / SOCKS5 setup, proxy format. Commands follow Docs EN quickstart.

Recommended pattern: launch arg plus per-page auth

Do not rely on putting `user:pass` inside the `--proxy-server` URL and hoping Chromium will honor it. Pass credentials with `page.authenticate`, and set them again on every new page, or later pages may hit 407 after the first success. Do not invent country or session fields in the username.

import puppeteer from "puppeteer";

const host = process.env.ZT_PROXY_HOST ?? "proxy.example.invalid";
const port = process.env.ZT_PROXY_PORT ?? "10000";
const username = process.env.ZT_PROXY_USER ?? "USER_EXAMPLE";
const password = process.env.ZT_PROXY_PASS ?? "PASS_EXAMPLE_NOT_REAL";

const browser = await puppeteer.launch({
  args: [`--proxy-server=http://${host}:${port}`],
});

const page = await browser.newPage();
await page.authenticate({ username, password });
await page.goto("https://example.com", { timeout: 30_000 });
console.log(await page.title());
await browser.close();

Switch `--proxy-server` to a SOCKS form only when the console returns SOCKS. Do not assume UDP is available. If the username or password has special characters, follow what the console and `authenticate` require—do not invent an encoding scheme and then hide it in the launch argument.

Sessions and common issues

Multiple pages in one browser can still see rotating exits change. Connection reuse is not a static IP, and it is not automatically sticky. See sticky ≠ static.

SymptomCheck first
407Missing `authenticate`; not called again on a new page; order still valid
Still your machine IP`--proxy-server` actually applied; no env or system proxy taking over
TimeoutsProtocol and port match the console; you did not leave the fake host in place
Want to isolate the libraryRecheck the same credentials with curl

Fuller symptom table: 407 and timeouts.

Compliance and scope

Authorized targets only. This is not a bypass or account-farming tutorial. Prices follow the console and pricing (rotating about $0.40/GB, about $0.20/GB on a 100 TB full bundle; static about $1.50 shared and about $5 dedicated per IP/month). USDT/USDC available; Visa/Mastercard in application. Not for mainland China.

FAQ

How is this different from the Playwright page?

Different library and API. Playwright can set host and auth together in `launch({ proxy })`. Puppeteer more often uses a launch argument plus `page.authenticate`.

Do I have to authenticate every new page?

Yes. Setting it only on the first page is a common cause of later 407s.

Can I use the example host as-is?

No. Replace it with console values.

Can I append a country code to the username myself?

Do not invent syntax. Use only fields the console or docs define.

If I reuse the browser, do I keep the same IP?

Not necessarily. Connection reuse is not static, and it is not automatically sticky.

Can I use this to bypass login limits?

No. Authorized targets only.

Do I need SOCKS5?

Follow the protocol the console returns. Many HTTPS pages work with HTTP `CONNECT`.

Where are prices confirmed?

In the console and on pricing.

Next steps

  1. Copy live fields from the console.
  2. Check an authorized page, and authenticate every new page.
  3. When you need to choose a product, open rotating or static.