Setup guide
Puppeteer proxy with username and password
Chrome takes the proxy address as a launch flag and asks for the login separately. Puppeteer answers that login through page.authenticate, which has to run before the first navigation.
Before you start
- Node.js with Puppeteer installed: npm i puppeteer, which also downloads a matching Chrome.
- The HOST, PORT, USERNAME and PASSWORD from the service page.
Your connection details
Sign in to the dashboard and open the service you bought. Its page shows the host, port, username and password for that service. There is no single ProxyPanda address to remember, so copy them from there each time. The code in these guides uses the placeholders below; replace each one with your own value.
- HOST
- The proxy address for this service, exactly as the service page shows it.
- PORT
- The port to connect to. Copy it with the host, since it can differ from one service to the next.
- USERNAME
- Your proxy login. It is separate from the email you use for the dashboard.
- PASSWORD
- Copy it in full. On residential, the options you choose in the dashboard are added to the end of the password, so a password typed from memory loses them.
You can skip the username and password by adding the IP address you connect from to the service’s allowlist. Then only HOST and PORT go into your code.
The examples use HTTP, which reaches https sites through an encrypted tunnel. SOCKS5 works too: residential ports accept both, and ISP and datacenter proxies switch protocol in the dashboard.
Steps
Launch Chrome with --proxy-server
Only the scheme, host and port go into the flag. Chrome refuses a username or password inside it.
Call page.authenticate before page.goto
Chrome then answers the proxy’s 407 challenge with your credentials. The script prints what api.ipify.org saw, which should be the proxy’s address.
check-ip.mjs import puppeteer from 'puppeteer'; const browser = await puppeteer.launch({ args: ['--proxy-server=http://HOST:PORT'], }); 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.evaluate(() => document.body.innerText)); await browser.close();Trim what the page downloads
Request interception lets you abort images, media and fonts before they load. It works alongside page.authenticate, and it keeps residential traffic, which is billed by the gigabyte, to the parts you use.
block-media.mjs await page.setRequestInterception(true); page.on('request', (request) => { if (['image', 'media', 'font'].includes(request.resourceType())) request.abort(); else request.continue(); });
Rotating and sticky IPs
Credentials given to page.authenticate apply to that page. Call it again on every new page you open, or that page’s requests reach the proxy without a login.
With Randomize IP on residential, the connections behind one page can leave from different addresses. For a flow that must look like one visitor, use Sticky IP, or an ISP or datacenter IP that does not change.
Common errors and fixes
net::ERR_NO_SUPPORTED_PROXIES
The --proxy-server flag contains a username and password. Keep only http://HOST:PORT there and pass the login to page.authenticate.
An empty page, and the response status is 407
page.authenticate was not called, or it ran after page.goto. Move it to straight after browser.newPage().
net::ERR_PROXY_CONNECTION_FAILED
Chrome could not reach HOST:PORT. Compare both with the service page and check that the service has not expired.
Navigation timeout exceeded
Slow exits happen, most often on residential. Pass a larger timeout to page.goto and retry once before giving up on that URL.
Which line to pick
For screenshots, PDFs and tests against sites that do not block servers, datacenter IPs are fast and cheap. Residential suits sites that turn away server ranges; you pay for its traffic by the gigabyte, which is why the interception step is worth keeping.
Other setup guides
Not sure what a word means? The glossary explains it in plain English.
Stuck on a step?
Paste the command and the error into Discord, with your password taken out. People there have met most of these errors before.