curl 命令速查表 - curl HTTP 调试常用命令大全
面向需要通过命令行调接口、复现线上问题、看清一次 HTTP 往返的开发者。浏览器无法表达自定义 Header、POST body、证书校验关闭等诉求,curl 是把"请求长什么样"完全掌握的入口。读完能声明式地构造带 body/header/cookie 的请求,用 -w 拆分 DNS/连接/TTFB 各阶段耗时定位慢在哪里,配合 -v 看清 TLS 握手与重定向链路。
典型使用场景
排障"看一次真实请求"是最典型场景。前端报 400,先用 curl -v 原样重放前端那份请求,看服务端返回与请求头,确认是缺 Content-Type 还是带了多余 Cookie;接口偶发超时,用 curl -w 拆出 time_namelookup/time_connect/time_appconnect/time_starttransfer,定位是 DNS、TCP 连接还是服务端响应慢;需要复现带登录态的线上问题,用 curl -b cookies.txt 带上 cookie,配合 -L 跟完重定向链路拿到真实落地页。写完请求先 -I 只取响应头验证路径,再 -d 提交数据,降低误操作。
基础请求 6
curl https://example.comcurl -X POST https://api.example.comcurl -H "Content-Type: application/json" -H "Authorization: Bearer xxx" https://api.example.comcurl -d '{"k":"v"}' https://api.example.comcurl -d @file.json https://api.example.comcurl -G https://api.example.com --data-urlencode "q=hello world"调试与详情 6
curl -v https://example.comcurl -I https://example.comcurl -L https://example.comcurl -w "%{http_code} %{time_total}\n" -o /dev/null -s https://example.comcurl -s https://example.comcurl --resolve example.com:443:1.2.3.4 https://example.com代理与超时 5
curl -x http://proxy:8080 https://example.comcurl -x socks5h://127.0.0.1:1080 https://example.comcurl --connect-timeout 5 https://example.comcurl --max-time 30 https://example.comcurl --retry 3 https://example.com认证与上传 5
curl -u user:pass https://example.comcurl -F "file=@photo.jpg" https://example.com/uploadcurl -F "file=@photo.jpg" -F "name=tom" https://example.com/uploadcurl -o photo.jpg https://example.com/photo.jpgcurl --cookie "session=abc" https://example.com参数矩阵
| 参数 | 作用 | 示例 |
|---|---|---|
-X | 显式指定请求方法,覆盖 curl 由 -d 推断出的默认值 | curl -X POST https://api.example.com |
-H | 追加单个请求头,可多次叠加,是设置 Content-Type 与 Authorization 的唯一手段 | curl -H "Content-Type: application/json" -H "Authorization: Bearer ***" https://api.example.com |
-d | 发送请求体并把方法推断为 POST,默认按表单格式编码 | curl -d '{"k":"v"}' https://api.example.com |
-d @file | 从文件读取 body 内容,避免长 JSON 全部挤在命令行上 | curl -d @file.json https://api.example.com |
-G + --data-urlencode | 把参数改拼到 URL 查询串并做 URL 编码,含空格的值无需手工转义 | curl -G https://api.example.com --data-urlencode "q=hello world" |
-v | 打印完整请求行、请求头、响应头与握手过程,排障第一选择 | curl -v https://example.com |
-I | 只取响应头,快速确认状态码与缓存头而不下载响应体 | curl -I https://example.com |
-L | 自动跟随 301 / 302 跳转到最终资源,可配合 --max-redirs 限制跳数 | curl -L https://example.com |
-w | 按模板输出自定义指标(状态码、耗时等),监控探测的输出格式靠它 | curl -w "%{http_code} %{time_total}\n" -o /dev/null -s https://example.com |
-s | 静默模式,关掉进度条与错误输出,配合 -o 落盘时保持终端干净 | curl -s https://example.com |
-o | 把响应体写入指定文件,下载二进制内容时替代终端输出 | curl -o photo.jpg https://example.com/photo.jpg |
--resolve | 把域名钉到指定 IP,绕过 DNS 缓存排查负载均衡与证书归属 | curl --resolve example.com:443:1.2.3.4 https://example.com |
-x | 经指定 HTTP 代理出网,排查「本机能通、经代理不通」类问题 | curl -x http://proxy:8080 https://example.com |
socks5h:// | 走 SOCKS5 代理且把 DNS 解析也交给代理,避免本地 DNS 泄露或污染 | curl -x socks5h://127.0.0.1:1080 https://example.com |
--connect-timeout | 只限制建立连接阶段的耗时,防止连接握手阶段无限期挂起 | curl --connect-timeout 5 https://example.com |
--max-time | 限制整个请求(含连接与传输)的总耗时,是脚本防卡死的兜底 | curl --max-time 30 https://example.com |
--retry | 失败后自动重试指定次数,应对瞬时网络抖动 | curl --retry 3 https://example.com |
-u | 发送 HTTP Basic 认证头,省去手写 Authorization 头 | curl -u user:pass https://example.com |
--cookie | 携带 Cookie 复现登录态请求,等价于读浏览器带来的会话 | curl --cookie "session=abc" https://example.com |
-F | 构造 multipart/form-data,可一次带上文件与普通字段 | curl -F "file=@photo.jpg" -F "name=tom" https://example.com/upload |
易错点与避坑指南
现象脚本里的 curl 长时间占着 CPU 不返回,监控任务被拖死。
原因curl 默认没有超时,连接建立或传输阶段只要对端不回应就会一直等下去,调用方也无从察觉。
处置显式加超时上限,用 --connect-timeout 5 卡住连接阶段,用 --max-time 30 卡住整体耗时。
现象-s 之后脚本不报错,但写进日志的状态码始终是同一个失败值。
原因静默模式只关掉了终端输出,不会把 HTTP 错误变成非零退出码,所以 shell 的失败判定完全没有被触发。
处置把判断落到响应本身:用 -w "%{http_code} %{time_total}\n" -o /dev/null -s 显式取出状态码再自行判定。
现象以为在验证某个域名,实际打到的是另一台机器。
原因--resolve 覆盖的是本地解析结果,若同时存在别的解析路径或代理,请求未必走钉住的 IP,排查结论会建立在错误的后端上。
处置配 -v 观察实际连接到的地址,确认连接目标与 --resolve 里写的 IP 一致再下结论。
现象上传接口返回 4xx,服务端说没收到文件。
原因同一请求里既用 -F 走 multipart 又用 -H 手动写 Content-Type,请求头与 curl 自动生成的 multipart 边界冲突,报文结构被打乱。
处置二选一:用 -F "file=@photo.jpg" -F "name=tom" 让 curl 自己生成 multipart 头,就不要再手动覆盖 Content-Type。
现象上传大文件时服务端不收,说请求体格式不对。
原因上传走 -F 时由 curl 负责分块,若同时用 -d 追加了一段正文,两种内容会拼进同一个 body,接收端无法解析。
处置把普通字段一并放进 -F(如 -F "file=@photo.jpg" -F "name=tom"),不要与 -d 混用。
现象带认证请求返回 401,但密码确认没输错。
原因认证信息若与 -H 或 -d 混用,curl 生成的请求头顺序与内容可能与服务端期望不一致;Basic 认证也未必是这套接口的认证方式。
处置改用 curl -u user:pass 让 curl 单独负责认证头,或用 curl -H "Authorization: Bearer ***" 明确指定该接口要求的认证形式。
现象查询参数里的空格和特殊符号被服务端读成乱码或截断。
原因值直接手写进 URL 时空格与 & 、# 等字符没有编码,服务器在解析查询串时就把它们当成了分隔符。
处置改用 curl -G https://api.example.com --data-urlencode "q=hello world",由 curl 负责编码。
现象同一个接口手动执行成功,放进定时任务就变成空响应。
原因命令行里依赖交互终端或当前目录的东西在定时任务中不存在,加上缺少 -s -o 落盘,结果被丢弃或写到了别处。
处置按 curl -s https://example.com 加 -o 明确落盘、-w "%{http_code} %{time_total}\n" -o /dev/null -s 校验状态码的方式重写,并使用绝对路径。
现象写好 -d 就以为请求是 POST,实际发出去的方法不对。
原因-X 会覆盖 curl 由 -d 推断的方法,一旦手写了与 body 语义不符的方法,服务端按方法分支处理就直接报错。
处置用 -v 查看实际发出的请求行;不需要重定向等特殊场景时,让 curl 依据 -d 自己推断方法而不是硬写 -X。
现象重定向后拿到的仍是中转页,不是目标资源。
原因不跟随时 curl 会把 3xx 响应头和正文原样交出,其中往往只是一段指向下一跳的 HTML。
处置用 curl -L https://example.com 跟完跳转;需要限制跳数防环时再加 --max-redirs。
排障路径
1先用只取响应头的请求确认状态码与缓存头
curl -I https://example.com输出的第一行即状态码;此步不下载响应体,适合写接口前先探路径是否通。
2需要看完整请求与响应头、握手细节时打开详细输出
curl -v https://example.com输出里能确认实际发出的请求方法、请求头与状态行,用来判断服务端到底收到了什么。
3把请求与响应体一起落到文件再慢慢看
curl -s https://example.com -o resp.json-s 保持终端干净,-o 让响应体进入 resp.json;文件为空说明该 URL 没有返回正文。
4做监控探测时只输出状态码与总耗时
curl -w "%{http_code} %{time_total}\n" -o /dev/null -s https://example.com终端只留一行数字;时间单位是秒,可以直接拿来做超时与延迟告警的判据。
5带登录态复现问题时补上 Cookie
curl --cookie "session=abc" https://example.com带上会话后返回 200 就说明问题在认证;仍然 401 或 403 则说明是权限或令牌本身的问题。
6怀疑 DNS 或负载均衡有问题时把域名钉到指定 IP
curl --resolve example.com:443:1.2.3.4 https://example.com请求会直连该 IP 但仍使用原域名做 TLS 与 Host;状态码正常即可判定问题出在解析或调度层。
7给探测请求兜底超时,避免任务被卡死
curl --connect-timeout 5 --max-time 30 --retry 3 https://example.com连接 5 秒、总耗时 30 秒、失败重试 3 次,三个上限叠加后任务不会再无限等待。
命令示例
拆解一次请求的各阶段耗时
curl -o /dev/null -s -w "DNS: %{time_namelookup}s\nCONNECT: %{time_connect}s\nTTFB: %{time_starttransfer}s\nTOTAL: %{time_total}s\n" https://example.com/api-o /dev/null 丢弃响应体避免刷屏,-w 输出各阶段耗时。慢在 time_namelookup 是 DNS 解析问题,慢在 time_connect 是网络连通性,慢在 time_starttransfer 说明服务端处理或首字节返回慢。
输出
DNS: 0.012s CONNECT: 0.047s TTFB: 0.213s TOTAL: 0.220s
带 JSON body、自定义 Header 与 Cookie 的 POST
curl -X POST 'https://api.example.com/login' -H 'Content-Type: application/json' -H 'X-Api-Key: abc123' -b 'session=xyz' -d '{"username":"test"}'注意 -d 不会自动设置 Content-Type,需手动加 -H;-b 传入 cookie,-H 可叠加多个自定义头。
本地自签发证书的服务跳过校验
curl -k https://localhost:8443/health-k 只用于本地联调或内网自签证书,生产环境绝不能跳过校验,否则中间人可解读全部流量。
常见坑与注意事项
- -d 默认发送表单格式,POST JSON 必须手动加 -H "Content-Type: application/json",否则服务端可能按表单解析导致 400 或空数据。
- -k 跳过 TLS 校验只适用于本地/内网自签证书;一旦用于生产,HTTPS 形同虚设。
- -X POST 与 -d 组合时,-X 可能覆盖默认的 method 推断;加 -v 确认实际发出的请求方法是否符合预期。
- 监控脚本里 -w time_total 是秒,且 curl 默认无超时,务必配 --max-time 防止进程永久挂起。
- 跟随重定向时用 -L 而非手动改 URL,否则 301/302 落到中转页而非最终资源。
提示
- -d 发 JSON 时记得手动加 -H "Content-Type: application/json",否则服务端可能解析失败。
- 调试 HTTPS 证书问题加 -v 看握手;临时跳过证书校验用 -k,生产环境不要用。
- -w 的 time_total 单位是秒,监控脚本常用 --max-time 兜底防卡死。
常见问题
带 Cookie 或登录态请求怎么用 curl?
一次性带 Cookie 用 curl -b "name=value; token=xxx",只保存服务端返回的 Cookie 用 -c cookies.txt,之后用 -b cookies.txt 复用会话。需要先登录的场景,先跑带 -c 的登录请求,再用 -b 发后续请求即可维持登录态。
需要登录的接口怎么通过浏览器拿到 curl 命令?
按 F12 打开开发者工具 → 切到 Network 面板 → 完成一次需要登录态的请求 → 右键该请求选 Copy as cURL,即可复现所有 Header/Cookie/请求体。把复制的命令里泄露的 Cookie/Token 脱敏后再使用或分享。
POST 提交 JSON 和表单数据分别怎么写?
JSON 用 curl -X POST -d '{"a":1}' -H "Content-Type: application/json",或更简洁的 curl -X POST http://... -d '[{"a":1}]'。表单用 -d "key=value&k2=v2"(Content-Type 自动为 x-www-form-urlencoded)或 -F "file=@a.png"(multipart,支持文件上传)。
curl 访问 HTTPS 报证书错误怎么办?
自签名或内网证书可用 -k(--insecure)跳过校验来排查;但线上请优先修正 CA 或补证书,不要长期用 -k。要指定自定义 CA 用 --cacert path.pem;想忽略代理可加 --noproxy "*"。
怎么判断接口到底慢在网络还是服务端?
用 curl -w "\ntime_namelookup:%{time_namelookup}\ntime_connect:%{time_connect}\ntime_starttransfer:%{time_starttransfer}\ntime_total:%{time_total}\n" -o /dev/null -s URL。其中 time_connect 反映 TCP 握手与网络延迟,time_starttransfer 是收到首个字节(含服务端处理 + TTFB)的耗时,time_total 是整体。分阶段拉长就能定位慢在哪一段。常见写法是 curl -w '%{time_total}\n'。
由 巧匠 维护
公开更新于 2026年7月21日,内容持续校对官方文档。