curl HTTP 客户端完整指南

curl 学习笔记 -- 命令行 HTTP 全能工具

分类:网络工具

核心主题:curl -- 命令行 HTTP 客户端完整学习笔记

主要内容:全面系统地讲解 curl HTTP 客户端工具,涵盖安装配置、各种 HTTP 请求方法、请求头设置、Cookie 管理、文件上传下载、认证安全、代理设置、脚本化自动化及与 Claude Code 结合使用。

关键词:curl, HTTP, 命令行, REST API, HTTP请求, Web开发, API测试, 文件传输, Claude Code

目录

  1. curl 概述与基本概念
  2. 安装与配置
  3. 基本 HTTP 请求(GET、POST、PUT、DELETE)
  4. 请求头与参数设置
  5. Cookie 管理与会话
  6. 文件上传与下载
  7. 认证与安全(Basic Auth、Bearer Token、SSL/TLS)
  8. 代理与网络设置
  9. 输出处理与格式化
  10. 脚本化与自动化
  11. 与 Claude Code 结合使用(API 测试、调试等)
  12. 常见问题与排错
  13. 核心总结

一、curl 概述与基本概念

1.1 什么是 curl

curl(全称 Client for URLs)是一个开源的、跨平台的命令行工具和库(libcurl),用于使用各种网络协议传输数据。它由瑞典开发者 Daniel Stenberg 于 1997 年创建,如今已成为互联网基础设施的一部分,几乎所有的操作系统、服务器和开发环境都预装了 curl。

核心事实:curl 是互联网上使用最广泛的数据传输工具之一。截至 2026 年,curl 已被集成到超过 100 亿个设备中,包括 Linux、macOS、Windows、嵌入式系统、路由器、智能电视等。它支持 20+ 种网络协议,最常用的是 HTTP/HTTPS。

1.2 curl 的发展历史

年份版本里程碑
1997curl 1.0Daniel Stenberg 首次发布,仅支持 FTP 和 GOPHER
1998curl 4.0引入 HTTP 支持,更名为 curl(原为 httpget)
2000curl 7.0重大重构,引入 libcurl 库
2003curl 7.10支持 SSL/TLS(HTTPS),引入 Cookie 引擎
2009curl 7.20支持 SMTP、POP3、IMAP 邮件协议
2015curl 7.44支持 HTTP/2
2020curl 7.71支持 HTTP/3(基于 QUIC)
2022curl 7.86TLS 1.3 成为默认,改进 --json 选项
2024curl 8.x持续优化性能、安全性和协议支持

1.3 curl 的工作原理

curl 的工作流程可以概括为四个阶段:解析 URL、建立连接、发送请求、接收响应。当用户输入一条 curl 命令时,curl 内部会执行以下步骤:

解析 URL DNS 解析 TCP 握手 SSL/TLS 握手 发送 HTTP 请求 接收响应

每个阶段都支持丰富的可配置选项,这也是 curl 如此强大的原因。用户可以通过各种命令行选项干预每个阶段的行为。

curl 的协议支持范围

curl 支持的协议远超 HTTP 范畴。以下是最常用的协议列表:

  • HTTP/HTTPS -- 网页和 REST API 请求(最常用)
  • FTP/SFTP -- 文件上传和下载
  • SMTP/SMTPS -- 发送电子邮件
  • POP3/POP3S -- 接收电子邮件
  • IMAP/IMAPS -- 邮件管理
  • SCP/SFTP -- 基于 SSH 的文件传输
  • LDAP/LDAPS -- 目录服务
  • MQTT -- IoT 消息协议
  • GOPHER -- 早期的互联网协议(历史意义)
  • DICT -- 字典查询协议
  • TELNET -- 远程登录
  • FILE -- 本地文件访问

1.4 curl 与 libcurl

了解 curl 和 libcurl 的区别很重要:

特性curl(命令行工具)libcurl(库)
用途直接在终端中使用嵌入到其他程序中使用
用户开发者、运维工程师编程语言绑定(PHP cURL、Python pycurl 等)
调用方式通过 Shell 执行通过 API 调用(C、C++、PHP、Python、Ruby 等)
配置命令行参数函数参数和回调
应用场景快速调试、脚本编写应用程序内置传输功能

学习提示

本笔记专注于 curl 命令行工具。libcurl 涉及大量编程接口,超出了本文范围。但掌握 curl 命令行的所有选项后,理解 libcurl 的概念会轻松很多 -- 因为命令行选项和 libcurl 的选项之间有一一对应关系。

二、安装与配置

2.1 检查是否已安装 curl

大多数操作系统都预装了 curl。可以通过以下命令检查:

# 检查 curl 是否安装及版本 curl --version # 简写方式 curl -V
$ curl --version curl 8.4.0 (x86_64-pc-linux-gnu) libcurl/8.4.0 OpenSSL/3.2.0 zlib/1.3 Release-Date: 2023-11-06 Protocols: dict file ftp ftps gopher gophers http https imap imaps ldap ldaps mqtt pop3 pop3s rtmp rtsp scp sftp smb smbs smtp smtps telnet tftp Features: alt-svc AsynchDNS GSS-API HSTS HTTP2 HTTP3 HTTPS-proxy IPv6 Kerberos Largefile libz NTLM SPNEGO SSL TLS-SRP UnixSockets

输出中的 Protocols 列出了当前 curl 支持的所有协议,Features 列出了编译时启用的特性。不同的系统可能显示不同的协议和特性列表,这取决于编译时使用的依赖库。

2.2 在主流操作系统上安装 curl

操作系统安装命令说明
Ubuntu/Debiansudo apt install curl官方仓库
CentOS/RHEL 8+sudo dnf install curl默认已预装
CentOS 7sudo yum install curl版本可能较旧
Fedorasudo dnf install curl较新版本
Arch Linuxsudo pacman -S curl社区维护
macOS (Homebrew)brew install curl系统自带旧版,brew 安装新版
macOS (MacPorts)sudo port install curl备选方案
Windows (winget)winget install curlWindows 10/11 内置
Windows (choco)choco install curlChocolatey 包管理器
Windows (scoop)scoop install curlScoop 包管理器

Windows 特殊说明

从 Windows 10 1803 版本开始,Windows 已经内置了 curl.exe。但 Windows 内置版本可能功能有限(不支持 HTTP/2、HTTP/3)。建议通过 WSL(Windows Subsystem for Linux)使用 Linux 版 curl,或者使用 winget/choco 安装最新版。在 WSL 中,curl 的表现完全等同于 Linux 环境。

2.3 从源码编译 curl

如果需要最新特性或自定义编译选项,可以从源码编译:

# 下载最新源码 git clone https://github.com/curl/curl.git cd curl # 使用 autoconf 构建 autoreconf -fi ./configure --with-openssl --enable-http2 --enable-http3 --enable-unicode make -j$(nproc) sudo make install # 验证安装 /usr/local/bin/curl --version # 常用 configure 选项 # --with-openssl 启用 SSL/TLS 支持 # --enable-http2 启用 HTTP/2 支持 # --enable-http3 启用 HTTP/3 支持 # --with-zlib 启用压缩支持 # --enable-unicode 启用 Unicode 支持(Windows) # --without-ssl 禁用 SSL(不推荐,但可用于轻量环境)

2.4 curl 的配置文件

curl 支持通过配置文件设置默认选项,这在团队协作和 CI/CD 环境中非常有用:

curlrc 配置文件

curl 会按以下顺序查找配置文件:

  • ~/.curlrc(类 Unix 系统)
  • %USERPROFILE%\.curlrc(Windows 系统)
  • 通过 --config 参数指定的自定义路径

配置文件中每行一个选项,与命令行参数对应但不带前面的 --

# ~/.curlrc 示例 # 默认超时时间(秒) connect-timeout = 30 # 默认使用 HTTP/2 http2 # 显示请求头(方便调试) include # 静默模式(去掉进度条) silent # 允许自动跳转 location # 设置 User-Agent user-agent = "curl/8.4 MyCustomUA" # 默认代理(企业环境常用) # proxy = http://proxy.company.com:8080 # 自动处理压缩 compressed

配置文件的最佳实践

配置文件非常适合设置全局默认值,但在脚本中建议使用显式参数而非依赖配置文件,以确保脚本在不同环境中行为一致。可以在脚本开头使用 --config /dev/null 来忽略配置文件。

2.5 升级 curl 到最新版

旧版 curl 可能缺少新特性或存在安全漏洞。以下是在各平台上更新 curl 的方法:

# Ubuntu/Debian 更新 sudo apt update && sudo apt upgrade curl # macOS Homebrew 更新 brew upgrade curl # 确保新版优先于系统版 echo 'export PATH="/usr/local/opt/curl/bin:$PATH"' >> ~/.zshrc # Windows WSL 更新(与 Linux 相同) sudo apt update && sudo apt upgrade curl # 使用官方安装脚本 # 访问 https://curl.se/download.html 获取最新版

三、基本 HTTP 请求(GET、POST、PUT、DELETE)

3.1 curl 命令的基础语法

curl 的命令行语法非常直观,基本格式为:

基本语法:curl [options] URL
  • options -- 控制 curl 行为的各种选项
  • URL -- 请求的目标地址

最简单的 curl 命令几乎不需要任何选项:

curl https://example.com

这个命令会发送一个 HTTP GET 请求,将返回的 HTML 内容直接输出到终端。

3.2 GET 请求

GET 是最常用的 HTTP 方法,用于从服务器获取资源。curl 默认使用 GET 方法:

# 基本 GET 请求(默认方法) curl https://api.github.com/users/octocat # 带查询参数的 GET 请求 curl "https://api.example.com/users?page=1&limit=20" # 更清晰的写法:URL 编码 curl "https://api.example.com/search?q=curl+http+client&lang=zh" # 显示响应头(-i 或 --include) curl -i https://api.github.com/users/octocat # 仅显示响应头(-I 或 --head,使用 HEAD 方法) curl -I https://github.com # 获取 HTTP 状态码 curl -o /dev/null -s -w "%{http_code}\n" https://example.com # 带条件请求(If-Modified-Since) curl -H "If-Modified-Since: Tue, 15 Nov 2024 12:45:00 GMT" https://example.com
$ curl -I https://github.com HTTP/2 200 server: GitHub.com content-type: text/html; charset=utf-8 strict-transport-security: max-age=31536000; includeSubdomains; preload

URL 编码注意事项

在 Shell 中,URL 中的特殊字符(如 &?=、空格等)需要用引号括起来,否则 Shell 会尝试解释它们。推荐始终对 URL 使用双引号,这是最安全的做法。

如果 URL 包含空格,应使用 %20+ 替代。curl 的 --data-urlencode 选项可以自动对数据进行 URL 编码。

3.3 POST 请求

POST 方法用于向服务器提交数据,如表单数据、JSON 负载等。curl 通过 -d--data 系列选项发送 POST 请求:

# 发送表单数据(Content-Type: application/x-www-form-urlencoded) curl -d "username=johndoe&password=secret123" https://api.example.com/login # 发送 JSON 数据(需手动指定 Content-Type) curl -d '{"username":"johndoe","password":"secret123"}' \ -H "Content-Type: application/json" \ https://api.example.com/login # curl 7.82+ 的 --json 快捷方式(自动设置 Content-Type: application/json) curl --json '{"username":"johndoe","password":"secret123"}' \ https://api.example.com/login # 从文件读取数据 curl -d @data.json -H "Content-Type: application/json" \ https://api.example.com/submit # 从 stdin 读取数据 echo '{"key":"value"}' | curl -d @- -H "Content-Type: application/json" \ https://api.example.com/submit # 发送空的 POST 请求(仅触发动作) curl -X POST https://api.example.com/actions/refresh # URL 编码的 data(自动编码特殊字符) curl --data-urlencode "comment=hello world & goodbye" \ https://api.example.com/comment

3.4 PUT 请求

PUT 方法用于更新或替换服务器上的资源。使用 -X PUT--request PUT

# PUT 更新资源 curl -X PUT -d '{"name":"Updated Name","email":"new@example.com"}' \ -H "Content-Type: application/json" \ https://api.example.com/users/123 # PUT 上传文件(替换已有资源) curl -X PUT -T localfile.txt https://api.example.com/files/remotefile.txt # 使用 -T (--upload-file) 时,-X PUT 可以省略,curl 自动推断 curl -T image.jpg https://api.example.com/uploads/avatar.jpg # 带条件 PUT(只在实际数据变化时才更新) curl -X PUT -d @updated.json \ -H "Content-Type: application/json" \ -H "If-Match: \"abc123\"" \ https://api.example.com/resources/42

3.5 DELETE 请求

DELETE 方法用于删除服务器上的资源:

# 基本 DELETE 请求 curl -X DELETE https://api.example.com/users/123 # DELETE 带请求体(某些 API 需要) curl -X DELETE -d '{"reason":"user requested removal"}' \ -H "Content-Type: application/json" \ https://api.example.com/users/123 # 验证删除结果(检查状态码) curl -s -o /dev/null -w "%{http_code}" -X DELETE \ https://api.example.com/users/123 # 200 = 删除成功,204 = 无内容(成功),404 = 资源不存在

3.6 PATCH 请求

PATCH 方法用于部分更新资源(不像 PUT 那样替换整个资源):

# PATCH 部分更新(仅发送要修改的字段) curl -X PATCH -d '{"email":"newemail@example.com"}' \ -H "Content-Type: application/json" \ https://api.example.com/users/123 # REST API 中 PATCH 与 PUT 的区别 # PUT /users/123 -- 替换整个用户记录 # PATCH /users/123 -- 仅更新指定字段

3.7 请求方法速查表

HTTP 方法curl 选项用途是否有请求体
GET默认,无需选项获取资源
POST-d / --data / --json创建资源,提交数据
PUT-X PUT + -d-T替换资源,上传文件
PATCH-X PATCH + -d部分更新资源
DELETE-X DELETE删除资源通常没有
HEAD-I只获取响应头
OPTIONS-X OPTIONS查询服务器支持的 HTTP 方法

关于 -X 与 -d 的自动推断

curl 有一个重要行为:当使用 -d(或 --data)选项时,curl 会自动将请求方法从 GET 改为 POST。当使用 -T(或 --upload-file)选项时,curl 会自动使用 PUT。只有在需要覆盖默认行为时才需要显式使用 -X。这是最佳实践,因为手动指定 -X POST 加上 -d 在某些情况下可能会导致意外行为(如重定向时方法保持为 POST)。

四、请求头与参数设置

4.1 自定义请求头

HTTP 请求头包含了请求的元数据信息。curl 使用 -H--header 选项来自定义请求头:

# 设置单个请求头 curl -H "Authorization: Bearer your-token-here" \ https://api.example.com/protected # 设置多个请求头(每个 -H 一个) curl -H "Content-Type: application/json" \ -H "Accept: application/vnd.github.v3+json" \ -H "User-Agent: MyApp/1.0" \ https://api.github.com/repos/curl/curl # 覆盖默认请求头 curl -H "Host: mysite.example.com" https://example.com # 删除默认请求头(设置空值即可删除) curl -H "User-Agent:" https://example.com # 设置 Accept-Encoding curl -H "Accept-Encoding: gzip, deflate" --compressed https://example.com # 自定义 Referer curl -H "Referer: https://google.com" https://example.com # 模拟移动端访问 curl -H "User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X)" \ https://m.example.com

重要的 HTTP 请求头

  • Authorization -- 认证凭据(Bearer Token、Basic Auth 等)
  • Content-Type -- 请求体的 MIME 类型(application/jsonapplication/x-www-form-urlencoded
  • Accept -- 客户端期望的响应格式
  • User-Agent -- 客户端标识
  • Referer -- 请求来源页面
  • Cookie -- 会话 Cookie(通常由 -b 管理)
  • Cache-Control -- 缓存控制策略
  • If-Modified-Since / If-None-Match -- 条件请求

4.2 User-Agent 设置

User-Agent 头标识发出请求的客户端类型。某些网站会检查 User-Agent 来返回不同的内容或阻止非浏览器访问:

# curl 的默认 User-Agent curl -I https://httpbin.org/user-agent # 输出: User-Agent: curl/8.4.0 # 伪装为浏览器 curl -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" \ https://www.example.com # 常用浏览器 User-Agent # Chrome 120 on Windows # -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" # Safari on macOS # -A "Mozilla/5.0 (Macintosh; Intel Mac OS X 14_2) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2 Safari/605.1.15" # Firefox on Linux # -A "Mozilla/5.0 (X11; Linux x86_64; rv:121.0) Gecko/20100101 Firefox/121.0"

4.3 查询参数处理

对于 GET 请求,查询参数可以直接拼接到 URL 中。curl 也提供了 -G 选项配合 --data-urlencode 来构建带参数的 GET 请求:

# 方式 1:直接拼接到 URL curl "https://api.example.com/search?q=hello&page=1&sort=desc" # 方式 2:使用 -G 和 --data-urlencode 自动拼接 curl -G https://api.example.com/search \ --data-urlencode "q=curl tutorial" \ --data-urlencode "page=1" \ --data-urlencode "lang=zh-CN" # 这等效于请求: # https://api.example.com/search?q=curl%20tutorial&page=1&lang=zh-CN # --data-urlencode 自动处理特殊字符的编码 curl -G https://api.example.com/filter \ --data-urlencode "tags=web,api,dev" \ --data-urlencode "q=foo & bar" # 输出中的 & 会被编码为 %26,保留为字符串的一部分

4.4 超时设置

curl 提供了两种超时控制:连接超时和总超时。在脚本中使用 curl 时,超时设置至关重要:

# 连接超时:建立 TCP 连接的最大等待时间 curl --connect-timeout 10 https://api.example.com # 总超时:整个请求的最大允许时间(含数据传输) curl --max-time 30 https://api.example.com # 同时设置连接超时和总超时 curl --connect-timeout 5 --max-time 60 \ https://slow-api.example.com # 超时单位都是秒,不支持毫秒 # --connect-timeout 0.5 虽然会被接受但会被取整为 0(不超时) # 要用毫秒级别的超时,可以配合 timeout 命令 timeout 3s curl https://api.example.com

超时设置的常见陷阱

不设置超时的危险:如果服务器无响应,curl 会一直等待(默认不超时),这在脚本中会导致脚本永久挂起。在 CI/CD 或自动化脚本中,总是设置 --max-time
连接超时和总超时的区别:连接超时只覆盖建立 TCP 连接阶段,对于需要长时间传输大文件的场景,应该设置合理的 --max-time 而非 --connect-timeout

4.5 自动跟随重定向

许多 URL 会返回 3xx 重定向响应。默认情况下,curl 不会自动跟随重定向:

# 默认不跟随重定向(会显示重定向页面内容或空内容) curl http://httpbin.org/redirect/3 # 跟随重定向 curl -L http://httpbin.org/redirect/3 # -L 或 --location 让 curl 自动跟随所有重定向直到最终页面 # 限制重定向次数(防止无限重定向循环) curl -L --max-redirs 5 http://example.com # 查看重定向路径(详细模式) curl -L -v http://httpbin.org/redirect/3 # POST 请求的重定向处理(默认 POST 会被改为 GET) curl -L -d "data=value" --post301 --post302 --post303 \ https://example.com/submit
$ curl -L -v http://httpbin.org/redirect/3 2>&1 | grep -E "^> |^< " > GET /redirect/3 HTTP/1.1 < HTTP/1.1 302 FOUND < Location: /relative-redirect/1 > GET /relative-redirect/1 HTTP/1.1 < HTTP/1.1 302 FOUND < Location: /get > GET /get HTTP/1.1 < HTTP/1.1 200 OK

五、Cookie 管理与会话

5.1 Cookie 基础

Cookie 是 Web 服务器发送到客户端并保存在本地的小块数据,用于维持会话状态。curl 提供了完整的 Cookie 管理机制:

Cookie 的作用:
  • 会话管理 -- 维持登录状态、购物车内容等
  • 个性化 -- 保存用户偏好设置
  • 追踪 -- 记录用户行为(通常用于分析)

在 API 测试和网页抓取中,Cookie 管理是必不可少的技能。

5.2 查看和发送 Cookie

# 发送自定义 Cookie curl -b "sessionid=abc123; user_pref=dark_mode" \ https://example.com/dashboard # 从文件读取 Cookie curl -b cookies.txt https://example.com # 同时发送多个 Cookie(-b 可以接受 name=value 字符串或文件) curl -b "token=xyz; lang=zh-CN; theme=dark" \ -H "Cookie: extra=value" \ https://example.com

5.3 存储服务器返回的 Cookie

curl 使用 -c--cookie-jar 将服务器返回的 Set-Cookie 头保存到文件中:

# 访问网站并保存 Cookie 到文件 curl -c cookies.txt https://example.com # 登录并保存 Cookie(典型登录流程) curl -c session.txt \ -d "username=user&password=pass" \ https://example.com/login # 使用保存的 Cookie 访问需要登录的页面 curl -b session.txt https://example.com/dashboard # Cookie 文件格式示例(Netscape Cookie 格式) # .example.com TRUE / FALSE 1735689600 sessionid abc123 # 域名 标志 路径 安全标志 过期时间 名称 值

5.4 Cookie 管理与会话保持

处理需要登录的网站或 API 时,完整的会话流程通常包括三个步骤:

# 完整会话示例:登录 + 操作 + 登出 # 步骤 1:登录并保存 Cookie curl -c session.txt \ -d "username=admin&password=secret123" \ https://api.example.com/auth/login # 响应中应包含成功信息和 Set-Cookie 头 # 步骤 2:使用 Cookie 访问受保护资源 curl -b session.txt \ -H "X-CSRF-Token: abc123" \ https://api.example.com/dashboard # 步骤 3:再访问另一个页面(Cookie 自动维持) curl -b session.txt \ -H "Accept: application/json" \ https://api.example.com/profile # 步骤 4:登出(清理 Cookie) curl -b session.txt -c session.txt \ -X POST https://api.example.com/auth/logout # --cookie 选项可以同时指定发送和保存的 Cookie 文件 # 即 -b 和 -c 指向同一个文件 curl -b session.txt -c session.txt \ https://api.example.com/some-action

Netscape Cookie 文件格式

curl 使用标准的 Netscape Cookie 格式存储 Cookie。每行代表一个 Cookie:

# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
.example.com	TRUE	/	FALSE	1767225600	sessionid	abc123
.example.com	TRUE	/	FALSE	0	csrf_token	xyz789

各字段:域名是否对所有子域生效路径是否仅 HTTPS过期时间戳名称

5.5 处理 Cookie 的高级场景

# 禁用 Cookie 引擎(不发送、不接收任何 Cookie) curl -b "" https://example.com # 忽略服务器返回的 Cookie 丢弃任何新的 Cookie curl -c /dev/null https://example.com # 使用多个 Cookie 来源 curl -b auth.txt -b "tracking=disabled" https://example.com # 查看所有请求/响应 Cookie(使用 -v 或 --trace) curl -v -b session.txt https://example.com # 在输出中搜索 "Cookie" 或 "Set-Cookie" # 模拟浏览器 Cookie 行为 curl -L -b session.txt -c session.txt \ -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" \ -H "Accept-Language: zh-CN,zh;q=0.9" \ https://example.com

Cookie 管理技巧

  • 在测试 API 时,使用 -c cookie.txt-b cookie.txt 模拟完整的用户会话
  • 使用 -v 查看原始 Cookie 头,有助于调试认证问题
  • 多步骤流程建议在脚本中维护独立的 Cookie 文件
  • 临时 Cookie 可以用 -c /tmp/cookies_$$.txt 存放($$ 是 PID,避免冲突)

六、文件上传与下载

6.1 文件下载

文件下载是 curl 最常见的用途之一。curl 提供了多种下载控制选项:

# 最基础的下载:输出到终端 curl https://example.com/file.zip # 保存到指定文件名(-o 或 --output) curl -o myfile.zip https://example.com/file.zip # 使用 URL 中的文件名保存(-O 或 --remote-name) curl -O https://example.com/file.zip # 这会保存为 file.zip(从 URL 推断文件名) # 断点续传(-C 或 --continue-at) curl -C - -O https://example.com/largefile.zip # 如果之前下载了一部分,-C - 会自动从断点处继续 # 限速下载(--limit-rate) curl --limit-rate 500K -O https://example.com/largefile.zip # 显示进度条 curl -# -O https://example.com/largefile.zip # -# 或 --progress-bar 显示 # 字符进度条 # 静默下载(无进度条、无错误消息) curl -s -o file.zip https://example.com/file.zip # 下载并重命名 curl -o "document-v2.pdf" -L https://example.com/download?file=doc.pdf # 多文件下载(多个 -O) curl -O https://example.com/file1.zip \ -O https://example.com/file2.zip \ -O https://example.com/file3.zip # 按时间戳条件下载(只下载更新的文件) curl -z 2026-01-01 -o data.csv https://example.com/data.csv # -z 或 --time-cond 只在文件比指定时间新时才下载

6.2 文件上传(POST 方式)

curl 使用 -F--form 选项通过 multipart/form-data 格式上传文件:

# 上传单个文件(模拟表单的 <input type="file">) curl -F "file=@/path/to/local/file.txt" \ https://api.example.com/upload # 上传并指定文件名(覆盖本地文件名) curl -F "file=@/path/to/photo.jpg;filename=avatar.jpg" \ https://api.example.com/upload/avatar # 上传多个文件 curl -F "image1=@photo1.jpg" \ -F "image2=@photo2.jpg" \ https://api.example.com/upload/multiple # 同时上传文件和普通表单字段 curl -F "file=@resume.pdf" \ -F "name=张三" \ -F "email=zhangsan@example.com" \ -F "category=job" \ https://api.example.com/upload # 使用 @- 从 stdin 读取文件内容 cat /etc/hosts | curl -F "file=@-;filename=hosts.txt" \ https://api.example.com/upload

-F 与 -d 的区别

  • -d / --data:发送 application/x-www-form-urlencoded 格式的数据。适合键值对数据,不适合文件上传。
  • -F / --form:发送 multipart/form-data 格式的数据。支持文件上传(@filename 语法),也支持普通字段。

选择哪种取决于服务器期望的格式。大多数文件上传 API 要求使用 -F

6.3 文件上传(PUT 方式)

-T--upload-file 使用 PUT 方法上传文件内容:

# PUT 上传文件 curl -T localfile.txt https://example.com/remote/path/localfile.txt # PUT 上传到指定远程路径 curl -T backup.sql https://example.com/db/backup/2026-05-01.sql # 从 stdin 上传 echo "data content" | curl -T - https://example.com/upload/data.txt # FTP 上传 curl -T myfile.txt ftp://ftp.example.com/upload/ --user user:pass # PUT 上传并显示进度 curl -T largefile.iso -# https://example.com/files/largefile.iso # PUT 上传带认证 curl -T package.tar.gz \ -u "username:password" \ https://private.example.com/packages/v1.2.3.tar.gz

6.4 批量下载与通配符

curl 内置了简单的通配符支持,可以批量下载多个文件(称为"URL 通配符"或"globbing"):

# 下载编号序列文件 curl -O "https://example.com/images/photo_[1-10].jpg" # 下载 photo_1.jpg 到 photo_10.jpg # 步进通配符 curl -O "https://example.com/images/photo_[1-10:2].jpg" # 下载 photo_1.jpg, photo_3.jpg, photo_5.jpg, photo_7.jpg, photo_9.jpg # 字母序列 curl -O "https://example.com/files/[a-f].txt" # 下载 a.txt 到 f.txt # 枚举通配符 curl -O "https://example.com/{foo,bar,baz}.html" # 下载 foo.html, bar.html, baz.html # 组合使用 curl -O "https://example.com/{img,css}/[1-9].{jpg,css}" # 禁用通配符(如果 URL 本身包含 [] 或 {} 字符) curl --globoff "https://example.com/api/[object Object]" # 或使用短选项 -g

通配符使用注意事项

  • 通配符是 curl 自身的功能,不是 Shell 的功能,所以 URL 需要用引号括起来
  • 如果 URL 本身包含 []{} 字符(如某些 API 路径),需要使用 -g 禁用通配符
  • 通配符不支持递归目录结构
  • 批量下载大量文件时,注意频率可能触发服务器的限流机制

七、认证与安全(Basic Auth、Bearer Token、SSL/TLS)

7.1 基本认证(Basic Auth)

HTTP Basic Auth 是最简单的认证方式,通过在请求头中发送 Base64 编码的用户名和密码:

# 使用 -u 选项(最常用) curl -u "username:password" https://api.example.com/protected # 只提供用户名,curl 会交互式提示密码输入 curl -u "username" https://api.example.com/protected # 输出: Enter host password for user 'username': # 直接在 URL 中包含凭据(不推荐,会出现在进程列表中) curl https://username:password@api.example.com/protected # 手动设置 Authorization 头(等效于 -u) curl -H "Authorization: Basic $(echo -n 'user:pass' | base64)" \ https://api.example.com/protected # 在脚本中安全使用(从环境变量读取密码) curl -u "admin:${API_PASSWORD}" https://api.example.com/admin

Basic Auth 安全提示

Basic Auth 的 Base64 编码不是加密,只是编码。任何人都可以轻松解码。仅在与 HTTPS 配合使用时才算安全。绝不要在 HTTP 连接上使用 Basic Auth,凭据会在网络中明文传输。
此外,在命令行参数中直接包含密码(-u user:pass)可能会被其他用户通过 ps aux 看到。在共享环境中,建议从文件或环境变量读取凭据。

7.2 Bearer Token 认证

Bearer Token 是现代 REST API 最常用的认证方式(尤其是 JWT):

# 使用 -H 设置 Authorization: Bearer curl -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \ https://api.example.com/protected # 从文件读取 Token TOKEN=$(cat /path/to/token.txt) curl -H "Authorization: Bearer ${TOKEN}" \ https://api.example.com/data # 从环境变量读取 Token curl -H "Authorization: Bearer ${GITHUB_TOKEN}" \ https://api.github.com/user # 使用 OAuth 2.0 客户端凭据流程获取 Token TOKEN=$(curl -s -X POST \ -d "grant_type=client_credentials&client_id=${ID}&client_secret=${SECRET}" \ https://auth.example.com/oauth/token | jq -r '.access_token') # 使用获取到的 Token 访问 API curl -H "Authorization: Bearer ${TOKEN}" \ https://api.example.com/secure/resource

7.3 API Key 认证

许多 API 使用 API Key 进行认证。API Key 可以放在请求头或查询参数中:

# API Key 在请求头中 curl -H "X-API-Key: your-api-key-here" \ https://api.example.com/v1/data # API Key 在查询参数中 curl "https://api.example.com/v1/data?api_key=your-api-key-here" # API Key 作为子域名 curl "https://your-api-key-here@api.example.com/v1/data" # 从变量读取 API Key curl -H "X-API-Key: ${API_KEY}" \ https://api.example.com/v1/users

7.4 SSL/TLS 配置

HTTPS 是 HTTP 的安全版本,使用 SSL/TLS 加密。curl 默认验证服务器证书,但提供了多种控制选项:

SSL/TLS 相关选项速览:
  • -k / --insecure -- 跳过证书验证(仅测试用)
  • --cacert -- 指定 CA 证书文件
  • --cert -- 指定客户端证书
  • --key -- 指定客户端证书私钥
  • --tlsv1.2 / --tlsv1.3 -- 指定 TLS 版本
  • --ciphers -- 指定密码套件
# 跳过证书验证(仅用于开发和测试!) curl -k https://self-signed.example.com # 指定自定义 CA 证书 curl --cacert /path/to/ca-bundle.crt \ https://internal.company.com # 客户端证书认证(双向 TLS / mTLS) curl --cert /path/to/client.crt \ --key /path/to/client.key \ https://secure-api.example.com # 带密码的客户端证书 curl --cert /path/to/client.p12:mypassword \ --cert-type p12 \ https://secure-api.example.com # 强制 TLS 1.2 curl --tlsv1.2 https://api.example.com # 强制 TLS 1.3 curl --tlsv1.3 https://api.example.com # 查看 SSL/TLS 连接详情 curl -v https://example.com 2>&1 | grep -E "SSL|TLS|certificate" # 检查 SSL 证书信息 curl --trace-ascii /dev/stdout https://example.com 2>&1 | grep -A 20 "SSL connection"
$ curl -v https://curl.se 2>&1 | grep -E "SSL|TLS|handshake" * SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 * Server certificate: * subject: CN=curl.se * start date: Jan 30 00:00:00 2024 GMT * expire date: Feb 27 23:59:59 2025 GMT * issuer: C=US; O=Let's Encrypt; CN=R3

7.5 处理 SSL 证书错误

SSL 证书错误是使用 curl 时常见的问题。理解这些错误至关重要:

错误说明解决方案
SSL certificate problem: self-signed certificate使用自签名证书使用 --cacert 指定 CA 证书,或 -k 跳过验证
SSL certificate problem: unable to get local issuer certificateCA 证书缺失更新 CA 证书包:sudo apt install ca-certificates
SSL certificate problem: certificate has expired证书已过期提醒服务器管理员更新证书。临时绕过用 -k
hostname mismatch证书中的域名与请求域名不匹配检查 URL 是否正确,或使用 -k 临时绕过
SSL: no alternative certificate subject name matches证书 SAN 字段不含请求的域名检查服务器配置,确保证书包含正确的域名

生产环境安全建议

永远不要在脚本中使用 -k(跳过证书验证),这会让你的请求容易受到中间人攻击。如果出现 SSL 错误,应该:

  • 确认系统时间为当前时间(错误的时间会导致证书被认为"已过期")
  • 更新 CA 证书包:sudo apt install ca-certificates
  • 对于内部服务,使用 --cacert 指定内部 CA
  • 确保客户端系统时间同步:sudo ntpdate pool.ntp.org

八、代理与网络设置

8.1 HTTP 代理

在企业网络或受限环境中,需要通过代理服务器访问外部资源:

# 使用 HTTP 代理(-x 或 --proxy) curl -x http://proxy.company.com:8080 https://api.example.com # 需要认证的代理 curl -x http://proxy.company.com:8080 -U "username:password" \ https://api.example.com # 设置环境变量自动使用代理 export http_proxy=http://proxy.company.com:8080 export https_proxy=http://proxy.company.com:8080 curl https://api.example.com # 自动使用代理 # NO_PROXY:针对某些域名不使用代理 export NO_PROXY=localhost,127.0.0.1,.internal.company.com # 使用 SOCKS5 代理 curl -x socks5://127.0.0.1:1080 https://example.com # 使用 SOCKS5 代理(带用户名密码) curl -x socks5://user:pass@127.0.0.1:1080 https://example.com # SOCKS5h:让代理解析 DNS(而非本地解析) curl --socks5-hostname 127.0.0.1:1080 https://example.com # 绕过代理(--noproxy) curl --noproxy ".local,.internal" https://internal-api.local/data

代理环境变量详解

curl 支持以下环境变量来自动配置代理:

  • http_proxy -- HTTP 请求的代理(小写)
  • https_proxy -- HTTPS 请求的代理(小写)
  • all_proxy -- 所有请求的代理
  • no_proxy -- 不需要代理的域名列表(逗号分隔)
  • HTTP_PROXY -- 同上,但某些情况下会被忽略(安全原因)

注意:大多数 Unix 系统只识别小写版本(http_proxy),curl 两者都支持。在 CGI 环境下,大写版本可能被忽略以防止 HTTP 头注入攻击。

8.2 网络接口绑定

# 绑定到特定网络接口 curl --interface eth0 https://example.com # 绑定到特定 IP 地址 curl --interface 192.168.1.100 https://example.com # 绑定到本地主机 curl --interface lo https://localhost:8080 # 指定本地端口范围 curl --local-port 10000-60000 https://example.com

8.3 DNS 设置

# 使用特定 DNS 服务器 curl --dns-servers 8.8.8.8,1.1.1.1 https://example.com # 自定义 DNS 解析(--resolve 别名) curl --resolve "api.example.com:443:127.0.0.1" \ https://api.example.com/health # 绕过 DNS 解析,直接连接到指定 IP curl --connect-to "::example.com:" https://example.com # 这将连接 example.com 的默认 IP,但通过 Host 头发送 Host: example.com # 多个自定义解析 curl --resolve "service1.example.com:443:10.0.0.1" \ --resolve "service2.example.com:443:10.0.0.2" \ https://service1.example.com/data

8.4 网络速度与延迟控制

# 限速下载 curl --limit-rate 1M -O https://example.com/largefile.zip # 设置接收速度下限(低于此速度持续一段时间则退出) curl --speed-limit 1000 --speed-time 30 \ -O https://example.com/largefile.zip # 如果连续 30 秒速度低于 1000 字节/秒,则中止传输 # 禁用 keepalive(每次请求后关闭连接) curl --no-keepalive https://example.com # 设置 keepalive 时间 curl --keepalive-time 30 https://example.com # 重试设置 curl --retry 3 --retry-delay 5 --retry-max-time 60 \ https://unstable-api.example.com # --retry 3 最多重试 3 次 # --retry-delay 5 重试前等待 5 秒 # --retry-max-time 60 重试总时间不超过 60 秒

重试策略最佳实践

在自动化脚本中,始终使用 --retry 来处理瞬态网络问题。curl 默认只在以下情况重试:

  • 可重试的传输错误(连接超时、连接被拒绝等)
  • HTTP 响应 408(请求超时)
  • HTTP 响应 429(请求过多)
  • HTTP 响应 5xx(服务器错误,不包括 500 和 501)

使用 --retry-connrefused 也会在被拒绝连接时重试。

九、输出处理与格式化

9.1 控制输出内容

curl 提供了丰富的选项来控制输出哪些信息以及如何格式化:

# 静默模式:不显示进度条和错误信息 curl -s https://api.example.com/data # 显示响应头(-i 或 --include) curl -i https://example.com # 仅显示响应头(-I 或 --head,发送 HEAD 请求) curl -I https://example.com # 详细模式:显示请求和响应的完整细节 curl -v https://example.com # 更详细的追踪输出 curl --trace trace.txt https://example.com # 追踪输出到 stdout curl --trace-ascii - https://example.com # 只输出 HTTP 响应体(默认行为) curl -s https://api.example.com/data # 输出到文件而非 stdout curl -o output.json https://api.example.com/data

9.2 使用 -w 自定义输出格式

-w--write-out 是 curl 最强大的特性之一,允许在请求完成后输出自定义格式的信息:

# 输出 HTTP 状态码 curl -s -o /dev/null -w "%{http_code}\n" https://example.com # 输出: 200 # 输出时间统计 curl -s -o /dev/null -w "\ time_namelookup: %{time_namelookup}s\n\ time_connect: %{time_connect}s\n\ time_appconnect: %{time_appconnect}s\n\ time_starttransfer: %{time_starttransfer}s\n\ time_total: %{time_total}s\n\ speed_download: %{speed_download} B/s\n" \ https://example.com
time_namelookup: 0.021s time_connect: 0.045s time_appconnect: 0.089s time_starttransfer: 0.178s time_total: 0.378s speed_download: 18523.000 B/s

curl 时间指标详解

变量名含义说明
time_namelookupDNS 解析时间域名解析为 IP 地址的耗时
time_connectTCP 连接时间TCP 三次握手耗时(含 DNS 解析)
time_appconnectSSL/TLS 握手时间TLS 加密协商耗时
time_pretransfer开始传输前总时间从开始到数据开始发送的耗时
time_starttransfer收到首个字节时间(TTFB)从开始到收到第一个响应字节
time_total总耗时整个请求的完整体耗时
# 可以配合 JSON 输出,方便脚本解析 curl -s -o /dev/null -w '{"http_code":%{http_code},"time_total":%{time_total},"size_download":%{size_download}}' \ https://example.com # 输出 HTTP 头中特定字段 curl -s -I -w "%{header_content_type}\n" -o /dev/null https://example.com # 输出 SSL 证书信息 curl -s -o /dev/null -w "%{ssl_verify_result}\n" https://example.com # 0 = 验证通过,其他值 = 验证失败 # 输出多种统计信息 curl -s -o /dev/null -w "\ status: %{http_code}\n\ size: %{size_download} bytes\n\ speed: %{speed_download} B/s\n\ time: %{time_total}s\n\ redirects: %{num_redirects}\n" \ https://example.com

9.3 处理 JSON 输出

curl 经常与 jq 命令配合使用来处理 JSON 响应:

# 基本组合:curl 获取 JSON,jq 格式化 curl -s https://api.github.com/repos/curl/curl | jq '.' # 提取特定字段 curl -s https://api.github.com/repos/curl/curl | jq '.name, .description, .stargazers_count' # 格式化输出 curl -s https://api.github.com/repos/curl/curl | jq '{name, stars: .stargazers_count, forks: .forks_count}' # 数据过滤 curl -s "https://api.github.com/search/repositories?q=curl+language:c" | \ jq '.items[] | {name, stars: .stargazers_count, url: .html_url}' # 转换为 CSV curl -s "https://api.github.com/search/repositories?q=curl" | \ jq -r '.items[] | [.name, .stargazers_count, .language] | @csv'
$ curl -s https://api.github.com/repos/curl/curl | jq '{name, stars: .stargazers_count}' { "name": "curl", "stars": 35334 }

9.4 输出重定向与组合

# 将响应头和响应体输出到不同的文件 curl -s -D headers.txt -o body.json https://api.example.com/data # 查看 headers.txt # cat headers.txt # HTTP/2 200 # content-type: application/json; charset=utf-8 # 丢弃所有输出 curl -s -o /dev/null https://example.com curl -s -o /dev/null -w "%{http_code}" https://example.com # 将输出通过管道传递给其他命令 curl -s https://api.example.com/data | jq '.results[]' | head -5 # 保存到文件并同时查看 curl -s https://api.example.com/data | tee response.json | jq '.' # 格式化 XML 输出 curl -s https://example.com/sitemap.xml | xmllint --format -

十、脚本化与自动化

10.1 Shell 脚本中的 curl

在 Shell 脚本中使用 curl 是自动化基础设施的核心能力。以下是一些常见的脚本模式:

#!/usr/bin/env bash # 健康检查脚本 set -euo pipefail URL="https://api.example.com/health" EXPECTED_CODE="200" status_code=$(curl -s -o /dev/null -w "%{http_code}" "${URL}") if [ "${status_code}" = "${EXPECTED_CODE}" ]; then echo "健康检查通过 (${status_code})" exit 0 else echo "健康检查失败 (${status_code})" exit 1 fi
# 带错误处理的 API 调用函数 call_api() { local method="$1" local url="$2" local data="${3:-}" local response local http_code if [ -n "$data" ]; then response=$(curl -s -w "\n%{http_code}" \ -X "${method}" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ${API_TOKEN}" \ -d "${data}" \ "${url}") else response=$(curl -s -w "\n%{http_code}" \ -X "${method}" \ -H "Authorization: Bearer ${API_TOKEN}" \ "${url}") fi local http_code=$(echo "$response" | tail -1) local body=$(echo "$response" | sed 's/\n[0-9]*$//') if [ "$http_code" -ge 200" ] && [ "$http_code" -lt 300" ]; then echo "$body" return 0 else echo "API Error (${http_code}): ${body}" >&2 return 1 fi } # 使用示例 call_api GET "https://api.example.com/users" call_api POST "https://api.example.com/users" '{"name":"张三"}'

10.2 循环与批量操作

# 批量检查多个 URL urls=("https://example.com" "https://google.com" "https://github.com") for url in "${urls[@]}"; do code=$(curl -s -o /dev/null -w "%{http_code}" "${url}") echo "${url}: ${code}" done # 批量 API 请求(并发版本) for id in {1..10}; do curl -s "https://api.example.com/users/${id}" & done wait echo "所有请求已完成" # 基于文件列表的批量操作 while IFS= read -r url; do echo "下载: ${url}" curl -s -O "${url}" || echo "下载失败: ${url}" done < url_list.txt # 使用 xargs 并行下载 cat urls.txt | xargs -P 4 -I {} curl -s -O {} && echo "{}" # 指数退避重试模式 retry_curl() { local max_attempts=5 local attempt=0 local delay=1 while [ "$attempt" -lt "$max_attempts" ]; do attempt=$((attempt + 1)) if curl -s -f "$@"; then return 0 fi echo "尝试 ${attempt}/${max_attempts} 失败,${delay} 秒后重试..." sleep "$delay" delay=$((delay * 2)) # 指数退避 done return 1 } retry_curl https://unstable-api.example.com/data

10.3 CI/CD 中的 curl

在 GitHub Actions、GitLab CI 等 CI/CD 系统中,curl 是部署和测试的关键工具:

# GitHub Actions 中的 curl 使用示例 # .github/workflows/deploy.yml # # - name: 触发部署 # run: | # curl -X POST \ # -H "Authorization: Bearer ${{ secrets.DEPLOY_TOKEN }}" \ # -H "Content-Type: application/json" \ # -d '{"ref":"main"}' \ # https://api.vercel.com/v1/integrations/deploy/xxx # 部署健康检查(等待服务就绪) echo "等待部署完成..." for i in $(seq 1 30); do code=$(curl -s -o /dev/null -w "%{http_code}" https://app.example.com/health 2>/dev/null || echo "000") if [ "$code" = "200" ]; then echo "部署成功!" exit 0 fi sleep 10 done echo "部署超时" exit 1 # Slack 通知 curl -s -X POST \ -H "Content-Type: application/json" \ -d '{"text":"部署完成: v1.2.3 已上线"}' \ https://hooks.slack.com/services/T00000000/B00000000/xxxxxxxxxxxx

10.4 性能测试脚本

#!/usr/bin/env bash # 简单性能测试 # 用法: ./benchmark.sh https://api.example.com 10 URL="${1:?需要提供 URL}" COUNT=${2:-5} echo "测试 URL: ${URL}" echo "请求次数: ${COUNT}" echo "---" total_time=0 for i in $(seq 1 "$COUNT"); do result=$(curl -s -o /dev/null -w "%{http_code} %{time_total}" "${URL}") code=$(echo "$result" | cut -d' ' -f1) time=$(echo "$result" | cut -d' ' -f2) total_time=$(echo "$total_time + $time" | bc) echo "请求 #${i}: 状态=${code}, 耗时=${time}s" done echo "---" echo "平均耗时: $(echo "scale=3; $total_time / $COUNT" | bc)s"
脚本化最佳实践:
  • 始终设置超时:在脚本中使用 --connect-timeout--max-time
  • 检查返回码:使用 -f(失败时返回非零退出码)或自己检查 HTTP 状态码
  • 使用 -sS 组合:-s 静默模式(去掉进度条),-S 显示错误(否则错误也被静默了)
  • 重试机制:关键请求要有重试逻辑
  • 日志输出:记录请求 URL、状态码和耗时到日志文件

十一、与 Claude Code 结合使用(API 测试、调试等)

11.1 在 Claude Code 中使用 curl

Claude Code 通过 Bash 工具执行 curl 命令,用于 API 测试、服务调试、数据获取等场景。以下是 Claude Code 中常用的 curl 使用模式:

场景示例命令说明
API 测试curl -s https://api.example.com/health快速检查 API 可用性
数据获取curl -s url | jq '.data'获取并提取 JSON 数据
接口调试curl -v https://api.example.com/endpoint查看请求和响应的完整细节
认证测试curl -H "Authorization: Bearer ..." url测试 API 认证机制
文件下载curl -O https://example.com/file.zip在 Claude Code 中下载文件
健康检查curl -s -o /dev/null -w "%{http_code}" url监控服务状态
# 测试 API 端点是否正常 curl -s -o /dev/null -w "%{http_code}" https://api.example.com/health # 获取天气数据并提取温度 curl -s "https://api.openweathermap.org/data/2.5/weather?q=Shanghai&appid=${API_KEY}&units=metric" \ | jq '{city: .name, temp: .main.temp, weather: .weather[0].description}' # 在 Claude Code 中调试 API 响应 curl -s -i https://api.example.com/users/1 | head -30 # 逐步骤调试(查看每个阶段的耗时) curl -s -o /dev/null -w "\ DNS 解析: %{time_namelookup}s\n\ TCP 连接: %{time_connect}s\n\ TLS 握手: %{time_appconnect}s\n\ TTFB: %{time_starttransfer}s\n\ 总耗时: %{time_total}s\n" \ https://api.example.com

11.2 API 开发辅助

Claude Code 可以帮助生成和完善 curl 命令,用于 API 开发和测试:

Claude Code 中的 curl 工作流:
  1. 开发者描述需要的 API 调用
  2. Claude Code 生成对应的 curl 命令
  3. 通过 Bash 工具执行验证
  4. 根据响应结果调整参数
  5. 最终命令被用于文档、脚本或测试
# 场景 1:从 API 文档到 curl 命令 # Claude Code 根据 API 文档自动生成: # POST /api/v1/orders # 请求体: { "product_id": "123", "quantity": 2, "coupon": "SAVE10" } curl -s -X POST \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ${API_TOKEN}" \ -d '{"product_id":"123","quantity":2,"coupon":"SAVE10"}' \ https://api.example.com/v1/orders | jq '.' # 场景 2:分页 API 数据采集 # 获取所有分页数据 page=1 has_more=true while [ "$has_more" = true ]; do data=$(curl -s "https://api.example.com/v1/items?page=${page}&per_page=100" \ -H "Authorization: Bearer ${API_TOKEN}") echo "${data}" | jq '.items[]' >> all_items.json has_more=$(echo "${data}" | jq '.has_more') page=$((page + 1)) done echo "采集完成,共 $(jq -s '.' < all_items.json | jq 'length') 条记录"

11.3 Webhook 测试

在 Claude Code 中,可以方便地测试和调试 Webhook:

# 模拟发送 Webhook 事件 curl -s -X POST \ -H "Content-Type: application/json" \ -H "X-Webhook-Secret: whsec_abc123" \ -d '{ "event": "order.created", "timestamp": "2026-05-08T11:54:22Z", "data": { "order_id": "ORD-20260508-001", "customer": "张三", "amount": 299.00, "currency": "CNY" } }' \ https://webhook.example.com/hooks/order-events # 使用 webhook.site 或 requestbin 测试 curl -X POST \ -H "Content-Type: application/json" \ -d '{"test": true, "message": "hello from Claude Code"}' \ https://webhook.site/your-unique-id # 测试 Webhook 签名验证 payload='{"event":"ping","data":"test"}' signature=$(echo -n "${payload}" | openssl sha256 -hmac "${WEBHOOK_SECRET}") curl -s -X POST \ -H "Content-Type: application/json" \ -H "X-Signature-256: sha256=${signature}" \ -d "${payload}" \ https://webhook.example.com/hooks

11.4 结合 jq 进行数据提取

在 Claude Code 中,curl 和 jq 的组合是数据处理的标准配置。Claude Code 可以利用这些工具帮助分析 API 数据:

# Claude Code 常用 curl+jq 组合模式 # 模式 1:API 响应分析 curl -s https://api.github.com/repos/curl/curl/commits | \ jq '.[] | {sha: .sha[0:8], author: .commit.author.name, date: .commit.author.date, message: .commit.message | split("\n")[0]}' | \ head -10 # 模式 2:数据汇总 curl -s "https://api.github.com/search/issues?q=repo:curl/curl+is:issue+is:open" | \ jq '{total: .total_count, items: [.items[] | {number, title, state, created_at}]}' # 模式 3:服务健康检查 curl -s https://status.example.com/api/v2 | jq '{ overall: .status.description, services: [.components[] | {name: .name, status: .status}] }'

在 Claude Code 中高效使用 curl 的建议

  • 使用 -sS 而不是 -s:-s 静默进度条,-S 仍然输出错误信息。配合使用 -sS 既整洁又能看到错误。
  • 设置超时:在 Claude Code 中使用 --connect-timeout 10 --max-time 30 避免长时间阻塞。
  • 限制输出大小:使用 jqheadtail 限制输出行数,避免输出过多内容。
  • 与环境变量配合:敏感信息(Token、API Key)通过环境变量传入,不要硬编码。
  • 管道组合:将 curl 的输出通过管道传递给 jq、grep、awk 等工具进行后续处理。

十二、常见问题与排错

12.1 curl 退出码详解

curl 在失败时会返回非零的退出码。理解这些退出码是排查问题的第一步:

退出码含义常见原因
0成功请求成功完成
1不支持的协议URL 使用了 curl 未编译支持的协议
3URL 格式错误URL 语法不正确
5无法解析代理代理主机名无法解析
6无法解析主机域名解析失败(最常见错误之一)
7无法连接目标主机拒绝连接或无法到达
22HTTP 页面未获取HTTP 返回码 >= 400,且使用了 -f
23写入错误无法写入输出文件或管道
26读取错误无法读取本地文件
28操作超时超出 --max-time--connect-timeout 设置的时间
35SSL 连接错误TLS 握手失败,通常与证书相关
47重定向过多超出 --max-redirs 限制
52服务器无响应服务器返回空响应
55网络发送失败Socket 发送数据失败
56网络接收失败Socket 接收数据失败
60SSL 证书问题证书验证失败
92HTTP/2 错误HTTP/2 协议层面的错误
# 检查 curl 退出码 curl -s https://nonexistent.example.com echo "退出码: $?" # 输出: 退出码: 6 # 使用 -f 让 HTTP 错误也产生非零退出码 curl -sf https://httpbin.org/status/404 && echo "成功" || echo "失败" # 输出: 失败(因为 404 触发了 -f 的错误处理)

12.2 常见问题及解决方案

问题可能原因解决方案
curl: (6) Could not resolve host域名无法解析检查 DNS 设置,确认域名拼写正确。尝试使用 IP 地址直接访问。
curl: (7) Failed to connect目标不可达检查网络连接、防火墙规则、目标服务是否运行。
curl: (28) Operation timed out请求超时增加 --connect-timeout--max-time 值,或检查网络速度。
curl: (35) SSL connect errorTLS 握手失败检查系统时间,更新 CA 证书包,确认服务器 SSL 配置。
curl: (56) Recv failure连接被重置可能是服务器主动断开连接,或是防火墙/代理干预。
curl: (60) SSL certificate problem证书不信任对于自签名证书使用 --cacert,或更新系统 CA 证书。
收到的 JSON 数据不完整服务器传输中断或 curl 输出被截断使用 -sS 而不是 -s 来显示错误信息;使用 jq 验证 JSON 完整性。
POST 请求返回 405 Method Not Allowed服务器不允许 POST检查 API 文档确认正确的方法。可能需使用 PUT 或 PATCH。
返回内容乱码字符编码不匹配设置 -H "Accept-Charset: utf-8" 或用 iconv 转换编码。
无法上传大文件服务器限制或超时使用 --limit-rate 降低速度,增加 --max-time,或分块上传。

12.3 调试技巧

# 1. 使用 -v 查看详细请求/响应 curl -v https://example.com # 输出中 > 表示请求头,< 表示响应头,* 表示 curl 内部信息 # 2. 使用 --trace 进行更详细的追踪 curl --trace - https://example.com # 3. 仅查看请求头(--trace-ascii 过滤输出) curl --trace-ascii /dev/stdout https://example.com 2>&1 | grep "^==" # 4. 发送但只检查请求(--dry-run 不实际发送) # 注意:curl 没有内置 --dry-run,但可以用 echo 模拟 echo "curl -X POST -d 'data' -H 'Content-Type: application/json' https://api.example.com" # 5. 使用 --config 调试配置文件问题 curl --config /dev/null -v https://example.com # 明确使用空的配置文件,确保不会意外加载 ~/.curlrc # 6. 检查 SSL 证书链 echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | \ openssl x509 -text -noout | grep -E "Subject:|Issuer:|Not " # 7. 测试特定的 DNS 解析 curl --resolve "example.com:443:93.184.216.34" https://example.com # 8. 模拟慢速网络(排查网络超时问题) curl --limit-rate 10k https://example.com/largefile.zip # 如果限速后能下载,说明正常下载时的超时是网络带宽问题

-v 输出解读

*   Trying 93.184.216.34:443...              # 正在连接目标 IP
* Connected to example.com (93.184.216.34)    # TCP 连接已建立
* SSL connection using TLSv1.3                # TLS 加密套件信息
* Server certificate:                         # 服务器证书信息
*   subject: CN=example.com
*   start date: Jan 29 00:00:00 2024 GMT
*   expire date: Feb 27 23:59:59 2025 GMT
*   issuer: C=US; O=Let's Encrypt; CN=R3
> GET / HTTP/1.1                              # > 表示发送的请求头
> Host: example.com
> User-Agent: curl/8.4.0
>
< HTTP/1.1 200 OK                             # < 表示接收的响应头
< Content-Type: text/html; charset=UTF-8
* Connection #0 to host example.com left intact  # 连接保持

12.4 性能调优

# 启用 HTTP/2(显著提升并发性能) curl --http2 https://api.example.com # 启用 HTTP/3(基于 QUIC,减少握手延迟) curl --http3 https://api.example.com # 连接复用(保持连接存活) curl --keepalive-time 60 \ -O https://example.com/file1.zip \ -O https://example.com/file2.zip # 并行下载(使用 xargs) seq 1 10 | xargs -P 4 -I {} curl -O "https://example.com/files/{}.zip" # DNS 缓存优化 curl --dns-cache-ttl 300 https://example.com # 增加 DNS 缓存时间,减少重复 DNS 查询 # 使用压缩减少传输量 curl --compressed https://example.com # 接受 gzip/deflate/brotli 压缩,CPU 换带宽

性能优化优先级

当需要优化 curl 请求性能时,按以下顺序排查:

  1. 启用压缩--compressed)-- 几乎总是有效,减少传输量 5-10x
  2. 使用 HTTP/2--http2)-- 多路复用,减少连接开销
  3. 连接复用(默认已开启)-- 确保请求共享同一个 base URL
  4. 限制带宽--limit-rate)-- 避免占满上行带宽影响其他服务
  5. DNS 优化--dns-servers)-- 使用更快的 DNS 服务器

十三、核心总结

curl 学习路线图

掌握 curl 是一个循序渐进的过程,以下是建议的学习路径:

基础 GET POST 数据 请求头 Cookie 文件传输 认证安全 代理网络 输出处理 脚本自动化

13.1 核心命令速查

用途命令
GET 请求curl https://api.example.com
POST JSONcurl -d '{"key":"val"}' -H "Content-Type: application/json" https://api.example.com
POST 表单curl -d "key=val&key2=val2" https://api.example.com
PUT 更新curl -X PUT -d @data.json -H "Content-Type: application/json" https://api.example.com/resource/1
DELETEcurl -X DELETE https://api.example.com/resource/1
文件下载curl -O https://example.com/file.zip
文件上传curl -F "file=@localfile" https://example.com/upload
Bearer Tokencurl -H "Authorization: Bearer TOKEN" https://api.example.com
Basic Authcurl -u "user:pass" https://api.example.com
自定义请求头curl -H "X-Custom: value" -H "Accept: application/json" https://api.example.com
Cookie 管理curl -b cookies.txt -c cookies.txt https://example.com
使用代理curl -x http://proxy:8080 -U "user:pass" https://example.com
超时设置curl --connect-timeout 10 --max-time 30 https://example.com
跟随重定向curl -L --max-redirs 5 https://example.com
状态码查询curl -s -o /dev/null -w "%{http_code}" https://example.com
详细调试curl -v https://example.com
性能测试curl -s -o /dev/null -w "TTFB: %{time_starttransfer}s\nTotal: %{time_total}s\n" https://example.com
跳过 SSL 验证curl -k https://self-signed.example.com(仅测试用)
JSON 格式化curl -s https://api.example.com | jq '.'

13.2 curl 三大黄金原则

原则一:默认使用 -sS

在脚本和自动化中,使用 -sS 组合:-s 静默进度条,-S 仍然显示错误。这确保输出整洁的同时不会错过关键错误信息。再配合 -o /dev/null -w "%{http_code}" 可以精确控制输出。

原则二:始终设置超时和错误处理

在脚本中使用 curl 时,应始终设置 --connect-timeout--max-time,防止脚本因网络问题永久挂起。结合 -f 选项让 HTTP 错误码触发非零退出码,便于脚本的错误处理。对关键请求添加重试机制。

原则三:先 -v 调试,再 -s 部署

在开发阶段使用 -v 查看完整的请求和响应细节,确认一切正常后,再改为 -s 模式用于生产环境或自动化脚本。使用 --trace 可以获得更详细的调试信息,适合排查棘手的网络问题。

13.3 常用组合模式

# 模式 1:健康检查 curl -sf -o /dev/null https://example.com/health && echo "服务正常" || echo "服务异常" # 模式 2:API 认证 + 数据提取 curl -s -H "Authorization: Bearer ${TOKEN}" https://api.example.com/data | jq '.items[].name' # 模式 3:下载 + 完整性校验 curl -s -O https://example.com/file.zip && sha256sum file.zip # 模式 4:登录 + 操作 + 登出 curl -c sess.txt -d "user=admin&pass=secret" https://example.com/login curl -b sess.txt https://example.com/dashboard curl -b sess.txt -X POST https://example.com/logout # 模式 5:持续监控 while true; do clear curl -s -o /dev/null -w "状态: %{http_code} 耗时: %{time_total}s\n" https://api.example.com/health sleep 2 done # 模式 6:API 响应缓存 cache_file="/tmp/api_cache.json" cache_ttl=300 # 5 分钟 if [ -f "$cache_file" ] && [ $(( $(date +%s) - $(stat -c %Y "$cache_file") )) -lt "$cache_ttl" ]; then cat "$cache_file" else curl -s https://api.example.com/data > "$cache_file" cat "$cache_file" fi

13.4 推荐学习资源

资源类型说明
curl 官方手册官方文档curl 所有选项的完整参考
Everything curl在线书籍Daniel Stenberg 编写的 curl 完整指南(免费)
curl FAQ常见问题curl 的常见问题和解答
httpbin.org测试服务HTTP 请求/响应测试服务,适合练习 curl
ReqBin在线工具在线 curl 调试工具,可生成 curl 命令
curlconverter转换工具将 curl 命令转换为 Python、JavaScript、Go 等代码
curl 源码GitHub 仓库curl 的源代码和 issue 跟踪

最终寄语

curl 是开发者工具箱中最基础也最重要的工具之一。它简单到可以用一行命令下载文件,又强大到可以模拟完整的 HTTP 会话、测试 REST API、调试 SSL 配置、批量处理请求。掌握 curl 就等于掌握了一种通用的"与互联网对话"的能力。

正如 curl 的创建者 Daniel Stenberg 所说:"curl 是那些你每天都用但很少会想起的工具之一。" 它的价值不在于多么花哨,而在于它在数十亿设备上可靠地工作了几十年。花时间真正掌握 curl,是值得的。

记住:在互联网的世界里,curl 是你万能的 HTTP 瑞士军刀。从简单的 GET 请求到复杂的 API 自动化,curl 始终在那里,随时待命。

10002