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

  1. Launch Chrome with --proxy-server

    Only the scheme, host and port go into the flag. Chrome refuses a username or password inside it.

  2. 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();
  3. 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.

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.

Join the Discorddiscord.gg/proxypanda
Start with $5Ask in Discord