Credentials do not go in the launch flag
Writing user and password into the proxy server argument is the natural thing to try and it silently does nothing. Chrome accepts the host and port from that flag and discards everything else, which is why the failure looks like a broken proxy rather than a rejected login.
// This looks correct and does not work.
const browser = await puppeteer.launch({
args: ['--proxy-server=http://USERNAME:[email protected]:80'],
})The setup that works
Host and port in the launch argument, credentials through page.authenticate. Call authenticate before the first navigation, and call it on every page you open, because it applies per page rather than per browser.
import puppeteer from 'puppeteer'
const browser = await puppeteer.launch({
args: ['--proxy-server=gate-eu.proxies.nullvault.shop:80'],
})
const page = await browser.newPage()
await page.authenticate({ username: 'USERNAME', password: 'PASSWORD' })
await page.goto('https://api.ipify.org?format=json')
console.log(await page.content())
await browser.close()One address for the whole browser session
A browser is a session by nature. Cookies, storage and fingerprint all persist across navigations, so the exit address should persist too. Use a sticky session rather than a rotating one, otherwise the site sees one visitor whose country changes between clicks, which is a stronger signal than any single request would be.
// Sticky, so the address survives the whole browser session.
// Residential holds up to six hours, mobile up to 120 minutes.
args: ['--proxy-server=gate-eu.proxies.nullvault.shop:80']Skip images if you are paying by the gigabyte
A browser downloads everything a browser downloads, and on a metered plan the images and fonts are billed exactly like the HTML you actually wanted. Blocking the request types you do not need often cuts traffic by most of the page weight and costs nothing in accuracy for scraping work.
await page.setRequestInterception(true)
page.on('request', (req) => {
const type = req.resourceType()
if (type === 'image' || type === 'font' || type === 'media') return req.abort()
req.continue()
})What to buy
Residential sticky for anything that has to look like a person using a browser. If you are only rendering pages nobody is guarding, datacenter is a great deal cheaper and works fine.
Common questions
Why is my proxy ignored in Puppeteer?
Because credentials in the proxy server flag are discarded by Chrome. The host and port take effect, so the browser is genuinely using the proxy, it just never authenticates and every request is refused. Move the credentials into page.authenticate and it works.
Do I need to authenticate on every page?
Yes. It applies per page, not per browser, so a page opened later in the run needs its own call. A common bug is authenticating the first page and then having every popup or new tab fail.
Can I use a different proxy per page?
Not in one browser instance, because the proxy is set when Chrome launches. Launch a browser per proxy, or use a rotating gateway if what you actually want is a fresh address per session rather than per page.