接入指南
Axios 代理设置:Node.js 账号密码认证
axios 自带 proxy 选项,但它如何处理 https 网站,取决于你装的版本。把 https-proxy-agent 的 agent 作为 httpsAgent 传入,并把 proxy 设为 false,在测试过的 axios 1.7 和 1.20 上表现一致,所以本指南从这种写法讲起。如果不用 axios,只用 fetch 或 https 模块,请看 Node.js 指南,那里讲了 undici 和单独使用 agent 的写法。
开始之前
- 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 和数据中心代理在控制台里切换协议。
步骤
安装 axios 和 agent
npm ls 会显示 node_modules 里实际装上的版本。记下 axios 的版本号:第 4 步的内置选项能否安全用于 https,取决于它。
terminal npm i axios https-proxy-agent npm ls axios https-proxy-agent把 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);运行脚本,查看地址
node check-ip.mjs 会打印 api.ipify.org 返回的 ip 字段。它应该是代理的出口地址,与你自己网络的地址不同。
在 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);在静态 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 失败。
其他接入指南
有不明白的词? 术语表用大白话解释。
卡在某一步了?
把命令和报错贴到 Discord,记得先删掉密码。那里的人大多遇到过这些错误。