结论先说: 让 curl 走代理,加上 -x 指定代理地址、-U 填账号密码即可:curl -x http://HOST:PORT -U "USERNAME:PASSWORD" https://example.com。地址开头的协议决定用哪种代理:http:// 或 https:// 是 HTTP 代理,socks5h:// 是由代理负责解析域名的 SOCKS5 代理。curl 也能从环境变量和配置文件读取代理,加 -v 可以看到 curl 和代理之间每一步发生了什么。

基本命令
curl -x http://HOST:PORT -U "USERNAME:PASSWORD" https://example.com-x(完整写法--proxy)是代理地址。-U(完整写法--proxy-user)是代理的账号密码。密码里有 shell 会特殊处理的字符时,记得加引号。
想知道网站看到的是哪个 IP,就请求 IP 查询服务。https://ipinfo.io/ip 只返回出口 IP,https://ipinfo.io/json 还会返回国家、城市和网络:
curl -x http://HOST:PORT -U "USERNAME:PASSWORD" https://ipinfo.io/json账号写在地址里,还是用 -U
账号密码也可以写进代理地址:-x http://USERNAME:PASSWORD@HOST:PORT。但只要密码里有 @、:、/ 或 #,地址就会被拆错,需要转义(@ 写成 %40,: 写成 %3A)。我们用密码 p@ss:word 测试:写在地址里要写成 p%40ss%3Aword,用 -U 则原样填写即可:
curl -x "http://user:p%40ss%3Aword@127.0.0.1:28181" https://example.com
curl -x http://127.0.0.1:28181 -U "user:p@ss:word" https://example.com用 -U 传账号密码就不用考虑转义,所以本文后面都用这种写法。
HTTP、HTTPS 和 SOCKS5 代理
| 协议 | 代理类型 | curl 怎么做 |
|---|---|---|
http:// | HTTP 代理 | 访问 HTTPS 网站时发 CONNECT 建隧道,访问 http:// 网站时把整个请求发给代理 |
https:// | 通过 TLS 连接的 HTTP 代理 | 同上,但先加密到代理的连接 |
socks5:// | SOCKS5 | 先自己解析网站地址,再让代理连接这个 IP |
socks5h:// | SOCKS5 | 把域名发给代理,由代理解析 |
--socks5 和 --socks5-hostname 参数的作用,分别等同于 socks5:// 和 socks5h://。协议和代理实际支持的不一致时,报错往往看不出原因:我们测试时,用 http:// 连 SOCKS5 端口报 Recv failure: Connection reset by peer;用 socks5h:// 或 https:// 连普通 HTTP 代理,则一直卡到 curl 超时。
两种协议各自适合什么,见 SOCKS5和HTTP代理的区别。
socks5 还是 socks5h

没有特别理由的话,用 socks5h://。我们的测试代理记录了同一个请求在两种写法下收到的内容:
socks5:// → the proxy received an IP address (curl had looked it up locally)
socks5h:// → the proxy received "example.com" (the proxy looked it up)本地解析由你自己的 DNS 服务器回答,返回的可能是为你所在地优化的服务器,而不是代理所在地的,同时还会让本地 DNS 服务器看到你访问了哪些网站。用 socks5h://,解析就发生在代理那一端。
不用 -x 时怎么设置代理
环境变量
没有 -x 时,curl 会读取这些环境变量:
| 变量 | 用于 | 实测说明 |
|---|---|---|
http_proxy | http:// 网址 | 只认小写:大写的 HTTP_PROXY 被 curl 忽略,直接连接了 |
https_proxy 或 HTTPS_PROXY | https:// 网址 | 大小写都可以 |
ALL_PROXY | 没有更具体变量的所有网址 | 配合 socks5h:// 代理可以使用 |
NO_PROXY | 不走代理的地址 | 逗号分隔,* 表示全部 |
export https_proxy="http://USERNAME:PASSWORD@HOST:PORT"
curl https://example.com这里账号密码只能写在地址里,特殊字符要转义。其他程序也会读这些变量,export 会影响这个终端里运行的所有程序;只想对一条命令生效,就写在命令前面(https_proxy=… curl …)。
配置文件
curl 启动时会读取 ~/.curlrc(Windows 在应用数据目录下的 _curlrc),-K 文件 可以指定其他文件。写法和命令行参数相同,只是去掉横杠:
proxy = "http://HOST:PORT"
proxy-user = "USERNAME:PASSWORD"哪个设置优先

我们测试时,-x 和配置文件都会覆盖错误的 https_proxy。-x 和 -K 同时出现时,命令行里写在后面的生效,所以 curl 最先读取的 ~/.curlrc 不会覆盖你的 -x。某个请求不想走代理,用 --noproxy '*';想忽略 ~/.curlrc,把 -q 放在命令最前面。
排查代理连接
用 -v 查看通信过程
-v 会打印每一步。下面是通过测试代理的一次正常请求的开头:
* Connected to 127.0.0.1 (127.0.0.1) port 28181
* Proxy auth using Basic with user 'user'
* Establish HTTP proxy tunnel to example.com:443
> CONNECT example.com:443 HTTP/1.1
> Proxy-Authorization: Basic dXNlcjpwQHNzOndvcmQ=
< HTTP/1.1 200 Connection established
* CONNECT tunnel established, response 200> 开头的是 curl 发给代理的,< 开头的是代理的回复。隧道没有建立,说明问题出在 curl 和代理之间,和网站无关。注意 Proxy-Authorization 只是 Base64 编码,并没有加密:带真实账号的 -v 输出不要贴到工单或聊天里。
通过代理用 -I(只看响应头)时,第一行是代理的 HTTP/1.1 200 Connection established,后面才是网站自己的响应头,所以看到的第一个状态行并不是网站的。
用 -w 给每一步计时
curl -x http://HOST:PORT -U "USERNAME:PASSWORD" -o /dev/null -s \
-w 'connect: %{time_connect}s tls: %{time_appconnect}s total: %{time_total}s\n' \
https://example.comtime_connect 是连接代理的耗时;它和 time_appconnect 之间的差,是建隧道加上和网站 TLS 握手的耗时。连接慢,问题在你到代理的线路;连接快但总耗时长,问题在出口或网站。
常见报错
退出码 7、56、97、28 的报错信息来自我们的实测;退出码 5 的说明来自 curl 文档。
| 退出码 | 报错信息 | 常见原因 |
|---|---|---|
| 7 | Failed to connect to 127.0.0.1 port 1 after 0 ms: Couldn't connect to server | 端口错误,或你的网络连不上代理 |
| 56 | CONNECT tunnel failed, response 407 | 没有填或填错了代理账号密码,见代理 407 错误 |
| 56 | Recv failure: Connection reset by peer | 协议写错,比如用 http:// 连 SOCKS5 端口 |
| 97 | User was rejected by the SOCKS5 server (1 1). | SOCKS5 的用户名或密码错误 |
| 28 | Connection timed out after 8006 milliseconds | 连不上代理,或用了代理不支持的协议 |
| 5 | Could not resolve proxy | 代理主机名写错了 |
在 NanoIP 代理上使用 curl
动态住宅和移动代理通过 HTTPS 网关连接,账号密码用 Dynamic Routes 里生成的路由:
curl -x https://gateway.nanoip.net:1111 -U "USERNAME:PASSWORD" https://ipinfo.io/json每个静态 ISP 代理都有自己的主机和端口,同一组账号同时支持 HTTP 和 SOCKS5:
curl -x http://HOST:PORT -U "USERNAME:PASSWORD" https://ipinfo.io/json
curl -x socks5h://HOST:PORT -U "USERNAME:PASSWORD" https://ipinfo.io/json在轮换路由上多运行几次住宅代理的命令,每次 IP 都会变;粘性路由或静态 ISP 的 IP 则保持不变。NanoIP 只用用户名密码认证,在任何网络下命令都一样。各项信息在哪里看,见新手入门;会话类型的区别,见轮换会话和粘性会话的区别。
常见问题
curl 会使用系统代理设置吗?
不会。curl 不读取 macOS 和 Windows 网络设置里的代理,只认 -x、配置文件和上面这些环境变量。
怎么让某些地址不走代理?
加 --noproxy,后面跟逗号分隔的地址,比如 --noproxy localhost,example.com;也可以设置 NO_PROXY。--noproxy '*' 表示所有地址都不走代理。
为什么浏览器能用,curl 不行?
浏览器可能用的是另一个代理,或者根本没用代理。先用 env | grep -i proxy 看看设置了哪些变量,再用 -x 和 -U 明确指定代理,查看 -v 的输出。