开始之前

  • Node.js 20 或更新版本,这是 https-proxy-agent 9 的要求。脚本保存为 .mjs 扩展名,顶层 await 才能使用。
  • 执行 npm i axios https-proxy-agent。以下步骤在 axios 1.20 和 https-proxy-agent 9.1 上测试过。
  • 控制台服务页面上的 HOST、PORT、USERNAME 和 PASSWORD。

你的连接信息

登录控制台,打开你购买的服务。服务页面上会显示该服务的主机、端口、用户名和密码。ProxyPanda 没有一个统一的固定地址,所以每次都请从那里复制。指南中的代码使用下面这些占位符,请逐一替换成你自己的值。

HOST
该服务的代理地址,按服务页面上显示的原样填写。
PORT
要连接的端口。请和主机一起复制,因为不同服务的端口可能不同。
USERNAME
你的代理登录名。它与你登录控制台所用的邮箱是分开的。
PASSWORD
请完整复制。住宅代理在控制台中选择的选项会附加在密码末尾,凭记忆手动输入的密码会丢失这些选项。

把你用来连接的 IP 地址加入服务的白名单,就可以不用用户名和密码。这时代码里只需要 HOST 和 PORT。

示例都使用 HTTP,它可以通过加密隧道访问 https 网站。SOCKS5 同样可用:住宅代理的端口两种都接受,ISP 和数据中心代理在控制台里切换协议。

步骤

  1. 安装 axios 和 agent

    npm ls 会显示 node_modules 里实际装上的版本。记下 axios 的版本号:第 4 步的内置选项能否安全用于 https,取决于它。

    terminal
    npm i axios https-proxy-agent
    npm ls axios https-proxy-agent
  2. 把 agent 作为 httpsAgent 传入,并设 proxy: false

    HttpsProxyAgent 带着你的登录信息向代理发送 CONNECT,再在这条隧道里与网站建立 TLS,代理只负责转发,读不到页面内容。proxy: false 让 axios 把路由完全交给 agent。去掉这一项时,shell 里的 HTTPS_PROXY 变量会盖过你的 agent,测试的两个 axios 版本都是如此。

    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. 运行脚本,查看地址

    node check-ip.mjs 会打印 api.ipify.org 返回的 ip 字段。它应该是代理的出口地址,与你自己网络的地址不同。

  4. 在 axios 1.16.1 及以上使用内置 proxy 选项

    从 1.16.1 起,axios 会自己为 https 网址建立 CONNECT 隧道,登录信息写在 auth 里。1.16.0 及更早的版本会把 https 请求当作带完整网址的普通 GET 发给代理,代理能读到请求内容,能否成功也要看代理愿不愿意代为获取。axios 版本较旧时,请继续用第 2 步的 agent。

    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. 在静态 IP 之间轮换,并设置可靠的超时

    在 proxies.txt 里每行写一个代理 URL,格式为 http://USERNAME:PASSWORD@HOST:PORT,每行对应你的一个 IP,请求会依次交给下一个客户端。axios 的 timeout 从隧道建立之后才开始计时。测试中,代理接受了连接却一直不回应 CONNECT 时,timeout 没有触发,所以再用 AbortSignal.timeout 给整个请求设一个上限。

    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);
      }
    }

轮换 IP 与粘性 IP

每次运行 check-ip.mjs 都是新进程、新隧道。住宅代理选“随机 IP”时,运行两次应当打印两个地址;选“粘性 IP”时,在网络允许的范围内一直是同一个地址。

测试中,https-proxy-agent 每个请求都会新开一条 CONNECT 隧道,即使来自同一个客户端也是如此。这正适合“随机 IP”,每次调用都可能换一个出口;但也意味着无法靠复用连接固定住宅地址,需要固定时请选“粘性 IP”。

按 proxies.txt 轮换适合 ISP 和数据中心,那里的每一行都是一个独立的固定 IP。住宅代理打开“随机 IP”后,代理端就会替你更换出口,列表里写一行就够了。

常见错误与解决办法

AxiosError: Request failed with status code 407

代理拒绝了登录。使用 https-proxy-agent 时,拒绝会以普通的 407 响应返回,而不是连接错误。从服务页面重新完整复制 USERNAME 和 PASSWORD。

创建 agent 时报 Invalid URL(ERR_INVALID_URL)

密码里的 @、: 或 / 等字符把代理 URL 从错误的位置切开了。拼 URL 之前,先用 encodeURIComponent 处理用户名和密码。

打印出的 IP 不属于代码里的那个代理

环境里设置了 HTTP_PROXY 或 HTTPS_PROXY,axios 用了它。像第 2 步那样在 httpsAgent 旁加上 proxy: false,或者取消这个变量。

AxiosError: connect ECONNREFUSED

HOST:PORT 上没有任何响应。与服务页面核对两者,并确认服务仍然有效。

设置了 timeout,请求却一直不结束

代理接受了连接,却在隧道建立之前不再回应,而 timeout 要从那之后才开始计时。像第 5 步那样传入 signal: AbortSignal.timeout(...),调用就会以 ERR_CANCELED 失败。

选择哪条产品线

用 axios 调用 API、或读取接受服务器流量的网站时,数据中心 IP 最省钱,轮换循环会把负载分摊到你租的每个 IP 上。网站开始拒绝数据中心 IP 段时,把这个任务换到住宅代理。脚本每天都要登录同一个账号时,给它一个 ISP IP。

卡在某一步了?

把命令和报错贴到 Discord,记得先删掉密码。那里的人大多遇到过这些错误。

加入 Discorddiscord.gg/proxypanda
$5 起步去 Discord 问