简短的回答只需一个标志:curl -x "http://host:port" "https://example.com" 将请求通过代理路由,目标看到的是代理的 IP 而非你的。-x(或 --proxy)标志就是全部功能。本文的其余内容都是变体:如何添加凭据、如何切换协议、如何为整个 shell 会话设置代理,以及如何确认代理真正生效。

如果你已经了解什么是代理服务器,只需要正确可直接粘贴使用的命令,请直接跳到下面的语法表格。示例使用 127.0.0.1 和清晰的占位符,以便你可以直接替换自己的主机、端口和凭据,无需猜测哪个字段是哪个。

唯一需要的标志:-x

cURL 在你传入 -x(短格式)或 --proxy(长格式)时通过代理路由请求。两者完全相同,选择在脚本中读起来更顺畅的那个。其值是一个 URL:协议、可选凭据、主机和端口。

bash
# Route one request through an HTTP proxy
curl -x "http://127.0.0.1:8080" "https://example.com"

# Same request, long-form flag
curl --proxy "http://127.0.0.1:8080" "https://example.com"

代理主机前面的协议(http://https://socks5://)告诉 cURL 如何与代理通信,而非它要获取的内容。普通的 http:// 代理仍然可以获取 https:// URL:cURL 通过它打开 CONNECT 隧道,并进行端到端的 TLS,因此代理永远看不到你的加密字节。这个区别容易让人困惑,如果还不清楚,建议阅读HTTP 代理与 HTTPS 代理的对比

添加代理认证

大多数付费代理需要凭据。有两种方式提供,行为略有不同。

第一种是将用户名和密码直接放在代理 URL 中,位于主机之前,用冒号分隔并以 @ 结尾:

bash
# Credentials inline in the proxy URL
curl -x "http://user:[email protected]:8080" "https://example.com"

# Credentials in a separate flag (keeps them out of the URL)
curl -x "http://127.0.0.1:8080" -U "user:pass" "https://example.com"

-U(或 --proxy-user)形式值得养成习惯:它将密码排除在 URL 之外,而 URL 往往会泄漏到 shell 历史和日志中。如果你的用户名或密码包含特殊字符(@:/),请对其进行 URL 编码,否则 cURL 会误读主机的起始位置。例如密码中的字符 @ 要变成 %40

HTTP、HTTPS 和 SOCKS 一览

SOCKS 代理的用法相同,只需更改协议。SOCKS 工作在 HTTP 之下一层,转发原始 TCP,因此它能承载任何协议,但无法读取或重写你的请求。当你希望代理负责解析 DNS 时(这样你的机器就不会泄露它要查询的主机名),使用 socks5h:// 而非 socks5://h 代表"在代理上解析主机名"。关于更深层的权衡,参阅什么是 SOCKS5 代理

目标 标志和值
HTTP 代理 -x "http://host:port"
HTTPS 代理 -x "https://host:port"
SOCKS5 代理 -x "socks5://host:port"
SOCKS5,DNS 由代理解析 -x "socks5h://host:port"
代理认证,内联 -x "http://user:pass@host:port"
代理认证,独立标志 -U "user:pass"
绕过某主机的代理 --noproxy "example.com"

还有一个专用的 --socks5 标志(以及 --socks4),接受不带协议的 host:port。它等效于 -x "socks5://...",主要是当脚本中同时使用多种代理类型时提高可读性。

http_proxy 与 HTTP_PROXY 不是拼写错误

cURL 同时读取环境变量的小写和大写形式,但有一个历史遗留的注意事项:它遵守小写的 http_proxy,但出于安全考虑,在 CGI 环境中只接受大写的 HTTPS_PROXY 等。原因是 HTTP_PROXY 在某些服务器环境中与 CGI 请求头(Proxy: 变成 HTTP_PROXY)冲突,因此 cURL 在 CGI 上下文中刻意忽略大写的 HTTP 形式。如有疑虑,对 HTTP 使用小写形式,可以避免整类意外情况。

通过环境变量为整个 shell 会话设置代理

在每条命令上都传 -x 会很烦人。导出一次代理,该 shell 会话中的每次 cURL 调用都会使用它,连同大多数其他遵守这些变量的命令行工具(wgetgit、包管理器等)。

bash
# Apply to every request in this shell session
export http_proxy="http://user:[email protected]:8080"
export https_proxy="http://user:[email protected]:8080"

# Skip the proxy for these hosts, comma-separated
export NO_PROXY="localhost,127.0.0.1,.internal.example.com"

# Stop using the proxy
unset http_proxy https_proxy

http_proxyhttps_proxy 接受相同的值:协议是 cURL 连接到代理所使用的协议,而变量名决定它应用于哪些目标 URL。NO_PROXY 是逃生出口:列表中匹配的任何主机都会直接连接。前缀点(.internal.example.com)匹配所有子域,NO_PROXY="*" 完全禁用代理而无需取消设置其他变量。

通过 .curlrc 永久设置代理

环境变量随 shell 消失。要让 cURL 始终使用代理,将其写入 cURL 的配置文件。在 Linux 和 macOS 上是 ~/.curlrc;在 Windows 上是 %APPDATA% 目录中的 _curlrc

bash
# ~/.curlrc  (Linux / macOS)
proxy = "http://user:[email protected]:8080"
proxy-user = "user:pass"

现在每条 cURL 命令都会通过代理路由,无需任何标志。这种便利有其两面性:很容易忘记该文件的存在,然后花一个小时纳闷为什么一台机器的行为与另一台不同。如果请求行为异常,尽早检查 ~/.curlrc。要对单次调用绕过它,传入 --noproxy "*",或使用 -q 运行,这会告诉 cURL 完全忽略配置文件。

为特定请求绕过代理

当代理被全局设置(环境变量或 .curlrc)时,有时你会希望某个请求直接连接,比如内部健康检查或本地服务。--noproxy 可以按命令处理:

bash
# Ignore the proxy entirely for this one request
curl --noproxy "*" "http://localhost:3000/health"

# Bypass only for one domain, proxy stays on for the rest
curl --noproxy "internal.example.com" "http://internal.example.com/api"

验证代理是否真正生效

永远不要假设路由已生效:请加以确认。最快的检查方法是请求一个回声服务报告它看到的 IP,并与你的真实 IP 对比。如果返回的地址是代理的,说明路由成功。

bash
# Your real IP, no proxy
curl "https://httpbin.org/ip"

# The IP seen through the proxy: should differ
curl -x "http://user:[email protected]:8080" "https://httpbin.org/ip"

# Add -v to watch the CONNECT handshake and headers
curl -v -x "http://user:[email protected]:8080" "https://httpbin.org/ip"

详细标志(-v)才是真正的诊断工具。它打印与代理的连接、HTTPS 目标的 CONNECT 行、代理的响应,以及最终发出的请求,告诉你出问题时确切的断点在哪里。

常见的 cURL 代理错误及其读法

大多数代理失败都属于少数几种可识别的形态。读懂错误信息而非盲目重试能节省大量时间。

你看到的内容 通常意味着
Failed to connect to ... port ... 主机或端口错误,或代理已宕机。确认地址并检查端口是否开放。
Proxy CONNECT aborted / 407 需要认证或认证被拒绝。检查凭据并对特殊字符进行 URL 编码。
SSL certificate problem 目标的 TLS 验证失败,非代理问题。修复信任库而非在生产环境中禁用检查。
Could not resolve proxy 代理主机名本身有误或 DNS 在任何请求发出之前就失败了。
Received HTTP code 403 / 429 代理连接正常;目标封锁或限速了出口 IP。更换 IP 或使用轮换 IP 池才是解决之道。

最后一行对爬取最为重要。403429 意味着你的 cURL 命令完全正确:只是目标不信任你来自的 IP。任何标志都无法解决这个问题,你需要更好的或轮换的 IP。如果持续遇到这种情况,如何在不被封锁的情况下爬取代理状态错误码的深度解析比单条命令能提供更多帮助。

关于 SSL 那一行:cURL 有 -k--insecure)标志可以跳过证书验证。用于测试本地环境是没问题的,但对任何你在意的环境来说则是真实的风险,因为它禁用了专门用于捕获中间人攻击的检查。将其视为调试工具,而非默认选项。

从单一代理到轮换 IP 池

以上所有内容都适用于单一代理。一旦你大规模爬取,单一 IP 就会成为瓶颈:目标会对其限速,然后封锁,你又回到手动更换地址的起点。通常的下一步是维护一个自己轮换的代理列表,这意味着要手动编写轮换、重试和健康检查逻辑。参阅如何使用轮换代理了解这种方法。

另一种选择是在整个 IP 池前放一个端点,让它替你轮换。你的 cURL 命令完全不变,只是将 -x 指向网关而非单个主机,每次请求在后台选择一个新的出口 IP。

Crawlbase Smart AI Proxy

Smart AI Proxy 是一个你将 cURL 指向的端点:它在大型住宅、数据中心和移动 IP 池中按请求轮换,并在封锁时重试,因此同样的 -x 标志让你每次调用都获得新鲜可信的 IP,而不是一个被封禁的。先在免费套餐上针对你的真实目标运行一下。

bash
# Same -x flag, pointed at a rotating gateway.
# Your token is the proxy username; password is empty.
curl -x "http://_USER_TOKEN_:@smartproxy.crawlbase.com:8012" -k \
     "https://httpbin.org/ip"

这是你工作流程中唯一的变化:网关在后台轮换出口 IP,而你的命令仍是普通的 cURL 调用。如果目标还需要真实浏览器或服务端重试,托管获取服务(如 Crawling API)接受一个 URL 并返回渲染后的结果,而不仅仅是提供干净的 IP。接入任何一种服务,只需阅读 API 文档

回顾

核心要点

  • 一个标志搞定一切。 curl -x "scheme://host:port" URL 通过代理路由;--proxy 是同一标志的完整写法。
  • 协议选择的是到代理的通信方式,而非目标。 http:// 代理仍通过 CONNECT 隧道获取 HTTPS;socks5h:// 在代理上解析 DNS。
  • 将凭据排除在 URL 之外。 优先使用 -U "user:pass" 而非内联凭据,并对特殊字符进行 URL 编码。
  • 通过环境变量或 .curlrc 一次性设置。 http_proxy/https_proxy 覆盖一次会话;~/.curlrc 使其永久生效;NO_PROXY--noproxy 是逃生出口。
  • 先验证,再读错误信息。 通过代理查询你的 IP 并使用 -v403/429 是被封锁的 IP,不是损坏的命令,这正是轮换 IP 池发挥价值的地方。

常见问题

如何在 cURL 中使用代理?

传入 -x(或 --proxy)标志加上代理 URL:curl -x "http://host:port" "https://example.com"。以 http://user:pass@host:port 的形式内联添加凭据,或者更好的方式是使用独立的 -U "user:pass" 标志。代理 URL 中的协议(httphttpssocks5)是 cURL 与代理通信的方式,而非它要获取的内容。

如何为 cURL 代理添加用户名和密码?

要么将其嵌入代理 URL 的主机之前(-x "http://user:pass@host:port"),要么用 -U "user:pass" 单独提供。独立的标志能防止密码出现在 shell 历史中。对凭据中的特殊字符进行 URL 编码,例如字符 @ 变成 %40,以便 cURL 正确解析主机地址。

如何通过环境变量设置代理?

导出 http_proxyhttps_proxy 并赋予代理 URL,cURL(以及大多数其他命令行工具)会将其用于该 shell 中的每次请求。使用 NO_PROXY 列出应直接连接的主机,用 unset http_proxy https_proxy 关闭代理。优先使用小写的 http_proxy 以避免与大写形式的 CGI 相关冲突。

cURL 可以使用 SOCKS5 代理吗?

可以。使用 -x "socks5://host:port",或专用的 --socks5 "host:port" 标志。要让代理解析 DNS(这样你的机器就不会泄露主机名),使用 socks5h://。SOCKS 转发原始 TCP,因此它能承载任何协议,但无法像 HTTP 代理那样读取或重写你的请求。

如何让 cURL 始终使用代理?

在 cURL 的配置文件中添加一行 proxy = "http://host:port":Linux 和 macOS 上是 ~/.curlrc,Windows 上是 %APPDATA% 中的 _curlrc。此后每条 cURL 命令都会通过它路由,无需任何标志。要为一次调用跳过配置,传入 -q,或使用 --noproxy "*" 仅对该请求绕过代理。

为什么我的代理返回 403 或 429 错误?

这些状态码来自目标网站,而非 cURL 或代理,这意味着连接成功,但出口 IP 被封锁或限速了。单个代理 IP 在负载下很快就会被标记。解决方法是更换或轮换 IP,要么自己管理一个池,要么将 cURL 指向按请求轮换出口 IP 的轮换网关。

开始构建

大规模爬取任何站点,无需与基础设施对抗。

Crawlbase 负责处理代理、指纹和 CAPTCHA,让你的团队专注于交付数据流水线,而非维护爬取管道。1,000 次请求免费,无需信用卡。

自助开通 · 无需销售通话 · 提供企业级爬取量