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
npm install puppeteerBasic setup
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:
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:
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:
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
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
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
| Error | Cause |
|---|---|
net::ERR_NO_SUPPORTED_PROXIES | Credentials inside --proxy-server. Use page.authenticate. |
net::ERR_PROXY_CONNECTION_FAILED | Wrong host or port, or a firewall. |
net::ERR_INVALID_AUTH_CREDENTIALS | No credentials were sent. Call page.authenticate before goto. |
A response with status 407 | Wrong username or password. |
net::ERR_SOCKS_CONNECTION_FAILED | A 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.