Puppeteer

Use NyxonProxies with Puppeteer: --proxy-server with page.authenticate, a proxy per browser context, sticky sessions, SOCKS5 via a local forwarder and errors.

Puppeteer passes the proxy address to Chrome as a launch flag and the credentials through page.authenticate. Chrome does not accept credentials inside the flag, so you always need both parts.

Install

bash
npm install puppeteer

Basic setup

javascript
import puppeteer from "puppeteer";

const browser = await puppeteer.launch({
  args: ["--proxy-server=http://geo.gw.nyxon.sh:8080"],
});
const page = await browser.newPage();
await page.authenticate({ username: "USERNAME-country-us", password: "PASSWORD" });

const res = await page.goto("https://api.ipify.org?format=json");
console.log(res.status(), await page.evaluate(() => document.body.innerText));
await browser.close();

Call page.authenticate on every new page, before its first goto.

Check the status

A wrong password does not always throw. Check the response, so a 407 page does not pass as content:

javascript
const res = await page.goto(url);
if (!res.ok()) throw new Error(`HTTP ${res.status()} for ${url}`);

A proxy per browser context

A browser context is an isolated session with its own cookies and storage. Each context can use its own proxy server, and each page its own username, so one browser can hold several sessions in different countries:

javascript
import puppeteer from "puppeteer";
import { randomBytes } from "node:crypto";

const browser = await puppeteer.launch();

async function openSession(country) {
  const context = await browser.createBrowserContext({ proxyServer: "http://geo.gw.nyxon.sh:8080" });
  const page = await context.newPage();
  const sid = randomBytes(4).toString("hex");
  await page.authenticate({ username: `USERNAME-country-${country}-session-${sid}-time-20`, password: "PASSWORD" });
  return { context, page };
}

for (const country of ["us", "de", "gb"]) {
  const { context, page } = await openSession(country);
  await page.goto("https://ipinfo.io/json");
  console.log(country, await page.evaluate(() => document.body.innerText));
  await context.close();
}
await browser.close();

Rotating or sticky

A page load opens several connections, and on a rotating username each one can leave from a different IP. For anything with a login or a cart, use a session ID per context, as above. For a new IP, open a new context with a new session ID. See Rotating and sticky sessions.

SOCKS5

Chrome cannot send a password to a SOCKS5 proxy. The HTTP port is the simple answer. If you need the SOCKS5 port, the proxy-chain package runs a local forwarder without a password that logs in to the gateway for Chrome:

javascript
import puppeteer from "puppeteer";
import { anonymizeProxy, closeAnonymizedProxy } from "proxy-chain";

const local = await anonymizeProxy("socks5://USERNAME:[email protected]:1080");
const browser = await puppeteer.launch({ args: [`--proxy-server=${local}`] });

const page = await browser.newPage();
await page.goto("https://api.ipify.org?format=json");
console.log(await page.evaluate(() => document.body.innerText));

await browser.close();
await closeAnonymizedProxy(local, true);

Skip the proxy for some hosts

javascript
const browser = await puppeteer.launch({
  args: [
    "--proxy-server=http://geo.gw.nyxon.sh:8080",
    "--proxy-bypass-list=*.internal.example;status.example.com",
  ],
});

Separate hosts with semicolons. A leading *. matches subdomains.

Save traffic: block heavy files

javascript
await page.setRequestInterception(true);
page.on("request", req => {
  if (["image", "media", "font"].includes(req.resourceType())) req.abort();
  else req.continue();
});

Aborted requests never reach the proxy, so they use no traffic.

Errors

ErrorCause
net::ERR_NO_SUPPORTED_PROXIESCredentials inside --proxy-server. Use page.authenticate.
net::ERR_PROXY_CONNECTION_FAILEDWrong host or port, or a firewall.
net::ERR_INVALID_AUTH_CREDENTIALSNo credentials were sent. Call page.authenticate before goto.
A response with status 407Wrong username or password.
net::ERR_SOCKS_CONNECTION_FAILEDA SOCKS5 address without a forwarder. Use the HTTP port.

Last updated

Still stuck?

People answer the live chat around the clock. Send the proxy line you used (without the password) and the error you see.