Puppeteer with an authenticated proxy: launch flag plus login
Updated:
Puppeteer proxy authentication happens in two places: the proxy address goes into the --proxy-server=http://ip:port launch flag, and the username and password go into await page.authenticate({ username, password }). Chrome answers the proxy's 407 challenge with those credentials over the DevTools Protocol, so your Node.js script can use a ProxyV4 IP without a browser extension.
--proxy-server=http://ip:port + page.authenticate({ username, password })Why the login is not part of the flag
Chrome does not accept credentials inside --proxy-server. If you write --proxy-server=http://user:pass@ip:port, the browser cannot use the value and requests fail, typically with ERR_NO_SUPPORTED_PROXIES. Keep the flag to address and port, and hand the login to the page.
| Order | Call | What it does |
|---|---|---|
| 1 | puppeteer.launch({ args: ['--proxy-server=http://ip:port'] }) | Tells Chrome which proxy every request should use |
| 2 | await page.authenticate({ username, password }) | Supplies the credentials when the proxy replies 407 |
| 3 | await page.goto(url, { waitUntil: 'domcontentloaded' }) | Loads the target through the authenticated proxy |
Tabs, contexts and more than one IP
page.authenticate()is set per page: every tab frombrowser.newPage()needs its own call before the firstgoto()- The launch flag fixes one proxy for the whole browser. For a different IP per context in one Chrome process, run each
http://user:pass@ip:portthroughanonymizeProxy()from theproxy-chainpackage and pass the result asproxyServertobrowser.createBrowserContext({ proxyServer }) - The setup works the same with
puppeteer-extraandpuppeteer-extra-plugin-stealth - Always end with
browser.close(), including in error paths, or headless Chrome processes pile up on the server
Choosing IPs for a Puppeteer fleet
Headless Chrome downloads full pages, scripts and images, so metered traffic adds up quickly. ProxyV4 private IPv4 and static ISP proxies have no bandwidth metering, each IP serves one customer only, and renewing keeps the same address, which matters when a session or allow-list is tied to it. Compare the private IPv4 product with the static ISP product if the target site treats datacenter ranges differently.
Step by step
- 1
Launch Chrome with the proxy address
Start the browser with
const browser = await puppeteer.launch({ args: ['--proxy-server=http://ip:port'] });, using the IP and port from your ProxyV4 order. - 2
Authenticate the tab
Open a page with
const page = await browser.newPage();and callawait page.authenticate({ username: 'USER', password: 'PASS' });before any navigation. - 3
Read the exit IP
Navigate with
await page.goto('https://proxyv4.com/api/my-ip');and check that the response shows the proxy address. - 4
Shut the browser down
Finish with
await browser.close();so no Chrome process is left running.
Frequently asked questions
What causes `ERR_NO_SUPPORTED_PROXIES` in Puppeteer?
Credentials inside the flag, as in --proxy-server=http://user:pass@ip:port. Use --proxy-server=http://ip:port and pass the username and password through page.authenticate().
My first tab works but a new tab gets HTTP 407. Why?
Authentication is stored per page. Call await newTab.authenticate({ username, password }) on each page you open before it navigates.
Can one Puppeteer browser use several proxies at once?
Not through the launch flag alone. Use proxy-chain to turn each authenticated proxy into a local address and give each browser context its own proxyServer, or start one browser per proxy.
How do I test many proxies before giving them to Puppeteer?
Paste them into the proxy checker; it handles up to 100 at a time and does not store passwords.
Unmetered IPs for headless Chrome
Private IPv4 in 7 countries plus static ISP in the US and Vietnam, issued automatically after payment, one customer per IP.
Check live US prices