接入指南
Node.js 代理:undici 与 https-proxy-agent
Node 的 fetch 没有接收代理 URL 的选项,所以要从 undici 传入一个 dispatcher。基于 https 模块的代码则改用 https-proxy-agent 提供的 agent。两种写法都在下面。
开始之前
- Node.js 22 或更新版本,并保持更新:当前的 undici 版本不支持更旧的 Node。
- fetch 示例需要 npm i undici,https 示例需要 npm i https-proxy-agent。
- 服务页面上的 HOST、PORT、USERNAME 和 PASSWORD。
你的连接信息
登录控制台,打开你购买的服务。服务页面上会显示该服务的主机、端口、用户名和密码。ProxyPanda 没有一个统一的固定地址,所以每次都请从那里复制。指南中的代码使用下面这些占位符,请逐一替换成你自己的值。
- HOST
- 该服务的代理地址,按服务页面上显示的原样填写。
- PORT
- 要连接的端口。请和主机一起复制,因为不同服务的端口可能不同。
- USERNAME
- 你的代理登录名。它与你登录控制台所用的邮箱是分开的。
- PASSWORD
- 请完整复制。住宅代理在控制台中选择的选项会附加在密码末尾,凭记忆手动输入的密码会丢失这些选项。
把你用来连接的 IP 地址加入服务的白名单,就可以不用用户名和密码。这时代码里只需要 HOST 和 PORT。
示例都使用 HTTP,它可以通过加密隧道访问 https 网站。SOCKS5 同样可用:住宅代理的端口两种都接受,ISP 和数据中心代理在控制台里切换协议。
步骤
通过 undici 的 ProxyAgent 使用 fetch
从同一个包里导入 fetch 和 ProxyAgent,把 agent 作为 dispatcher 传入。登录信息写在 URL 里。
fetch.mjs import { fetch, ProxyAgent } from 'undici'; const dispatcher = new ProxyAgent('http://USERNAME:PASSWORD@HOST:PORT'); const response = await fetch('https://api.ipify.org?format=json', { dispatcher }); console.log(await response.json());用 https-proxy-agent 配合 https 模块
HttpsProxyAgent 会为 https 请求经代理建立 CONNECT 隧道。任何接受 Node agent 的库都可以直接使用这个对象。
https.mjs import https from 'node:https'; import { HttpsProxyAgent } from 'https-proxy-agent'; const agent = new HttpsProxyAgent('http://USERNAME:PASSWORD@HOST:PORT'); https.get('https://api.ipify.org?format=json', { agent }, (res) => { let body = ''; res.on('data', (chunk) => (body += chunk)); res.on('end', () => console.log(body)); });运行两次并对比
两个脚本都会打印 api.ipify.org 看到的地址。每次运行都是新进程、新连接,所以住宅代理选“随机 IP”时,运行两次应当打印两个不同的地址。
轮换 IP 与粘性 IP
两种 agent 都会保持连接并复用。共用同一条隧道的请求从同一个地址发出,所以长时间运行的进程在“随机 IP”模式下,未必每次调用都换出口。确定需要新地址时,请新建一个 agent。
在“粘性 IP”模式下,或者使用 ISP、数据中心 IP 时,复用连接没有影响:地址本来就应该保持不变。
常见错误与解决办法
TypeError: fetch failed,原因是 invalid onRequestStart method
Node 内置的 fetch 拿到了 undici 包里的 ProxyAgent,两者版本不匹配。像示例那样,fetch 也从 undici 导入。
RequestAbortedError: Proxy response (407) !== 200 when HTTP Tunneling
代理拒绝了登录。重新复制用户名和密码;如果其中含有 @、: 或 /,用 encodeURIComponent 处理。
ECONNREFUSED 或 ETIMEDOUT
HOST 或 PORT 填错了,或者服务已经到期。在服务页面上核对两者,并确认服务仍显示为有效。
脚本打印的是你自己的 IP
agent 没有传到请求上。使用 https.get 时,它应作为 agent 放在选项对象里;使用 fetch 时,它作为 dispatcher 传入。
其他接入指南
有不明白的词? 术语表用大白话解释。
卡在某一步了?
把命令和报错贴到 Discord,记得先删掉密码。那里的人大多遇到过这些错误。