Before you start

  • Node.js 20 or newer, which https-proxy-agent 9 requires. Save scripts with an .mjs extension so top-level await works.
  • npm i axios https-proxy-agent. The steps were tested with axios 1.20 and https-proxy-agent 9.1.
  • HOST, PORT, USERNAME and PASSWORD from the service page in the dashboard.

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. Install axios and the agent

    npm ls shows which versions landed in node_modules. Note the axios number: it decides whether the built-in option in step 4 is safe to use for https.

    terminal
    npm i axios https-proxy-agent
    npm ls axios https-proxy-agent
  2. Pass the agent as httpsAgent, with proxy: false

    HttpsProxyAgent sends a CONNECT to the proxy with your login and runs TLS to the site inside that tunnel, so the proxy passes the page along without reading it. proxy: false tells axios to leave routing to the agent. Leave it out and an HTTPS_PROXY variable in your shell wins over the agent, which happened on both axios versions tested.

    check-ip.mjs
    import axios from 'axios';
    import { HttpsProxyAgent } from 'https-proxy-agent';
    
    const client = axios.create({
      httpsAgent: new HttpsProxyAgent('http://USERNAME:PASSWORD@HOST:PORT'),
      proxy: false,
      timeout: 30000,
    });
    
    const { data } = await client.get('https://api.ipify.org?format=json');
    console.log(data.ip);
  3. Run the script and read the address

    node check-ip.mjs prints the ip field from api.ipify.org. It should match a proxy exit and differ from the address your own connection shows.

  4. Use the built-in proxy option on axios 1.16.1 or newer

    Since 1.16.1, axios opens a CONNECT tunnel for https URLs by itself, with the login in auth. Up to 1.16.0 it sent the https request to the proxy as a plain GET carrying the full URL, which the proxy could read and which works only if the proxy agrees to fetch it. With an older axios, stay with the agent from step 2.

    builtin-proxy.mjs
    import axios from 'axios';
    
    const { data } = await axios.get('https://api.ipify.org?format=json', {
      proxy: {
        protocol: 'http',
        host: 'HOST',
        port: PORT,
        auth: { username: 'USERNAME', password: 'PASSWORD' },
      },
      timeout: 30000,
    });
    console.log(data.ip);
  5. Rotate over your static IPs, with a timeout that holds

    Save one proxy URL per line in proxies.txt, each built as http://USERNAME:PASSWORD@HOST:PORT for one of your IPs, and every request goes to the next client in turn. The axios timeout starts once the tunnel is up. When a proxy accepted the connection and then never answered the CONNECT, it did not fire in testing, so AbortSignal.timeout puts a ceiling on the whole request.

    rotate.mjs
    import { readFileSync } from 'node:fs';
    import axios from 'axios';
    import { HttpsProxyAgent } from 'https-proxy-agent';
    
    const clients = readFileSync('proxies.txt', 'utf8')
      .split('\n')
      .map((line) => line.trim())
      .filter(Boolean)
      .map((proxy) =>
        axios.create({ httpsAgent: new HttpsProxyAgent(proxy), proxy: false, timeout: 30000 }),
      );
    
    const urls = Array(6).fill('https://api.ipify.org');
    
    for (const [i, url] of urls.entries()) {
      const client = clients[i % clients.length];
      try {
        const { data } = await client.get(url, { signal: AbortSignal.timeout(45000) });
        console.log(i, data);
      } catch (err) {
        console.log(i, err.code ?? err.message);
      }
    }

Rotating and sticky IPs

Each run of check-ip.mjs is a new process with a new tunnel. On residential with Randomize IP, two runs should print two addresses; with Sticky IP, the same one for as long as the network can hold it.

In testing, https-proxy-agent opened a fresh CONNECT tunnel for every request, even from the same client. That suits Randomize IP, where each call may get a new exit. It also means a rotating residential client cannot pin an address by reusing a connection: choose Sticky IP for that.

Rotating through proxies.txt makes sense on ISP and datacenter, since each line there is a separate fixed IP. On residential the proxy already changes the exit for you when Randomize IP is on, so a list with one line is enough.

Common errors and fixes

AxiosError: Request failed with status code 407

The proxy turned the login down. With https-proxy-agent the refusal comes back as a normal 407 response instead of a socket error. Copy USERNAME and PASSWORD from the service page again, in full.

Invalid URL (ERR_INVALID_URL) as the agent is created

A character such as @, : or / in the password split the proxy URL in the wrong place. Run the username and password through encodeURIComponent before building the URL.

The IP printed is not from the proxy in your code

An HTTP_PROXY or HTTPS_PROXY variable is set and axios followed it. Add proxy: false next to httpsAgent, as in step 2, or unset the variable.

AxiosError: connect ECONNREFUSED

Nothing answered at HOST:PORT. Check both against the service page and confirm the service is still active.

A request that never ends although timeout is set

The proxy took the connection and went quiet before the tunnel opened, and timeout only counts from after that point. Pass signal: AbortSignal.timeout(...), as in step 5; the call then fails with ERR_CANCELED.

Which line to pick

Axios jobs that call APIs or read pages from sites that accept server traffic run cheapest on datacenter IPs, and the rotation loop shares the load across every IP you rent. When a site starts refusing data-centre ranges, move that job to residential. If a script signs in to the same account day after day, give it an ISP IP.

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