核心要点
- cURL 可帮助您在任意两个 URL 之间传输数据。
- 它在 Windows、macOS 和 Linux 上的使用方式相同。
- 您可以使用 cURL 测试 API、自动提交表单、下载文件,以及排查连接问题。
cURL 是 Client URL 的缩写,是一种远没有得到应有关注的工具。或许是因为它低调内敛,总是默默在后台工作。但正如您所知,cURL 是在 URL 之间传输数据最简单、最强大的方式之一。
无论您使用哪种协议、处于哪个平台、想要完成什么任务,只要数据在网络上,cURL 总能想办法搞定。本文将为您详细介绍它的使用方法。
cURL 是什么?
cURL 是一种命令行工具,最初是为了解决一个实际问题而诞生的。1996年,瑞典开发者 Daniel Stenberg 正在开发一个互联网中继聊天(IRC)机器人,他需要一种方法从网络上获取实时汇率数据,并将其发送到聊天对话中。
他找到了一个起点:httpget,这是巴西开发者 Rafael Sagula 最初编写的一款命令行工具。Daniel 在此基础上不断扩展、重写并持续更新。在接下来的几年里,他成为该项目的核心维护者,陆续加入了对更多协议的支持、更完善的传输处理,以及跨平台的稳定性。
这款工具几经更名,最终定名为 cURL,即“Client URL”的缩写。这个名字沿用至今,因为它恰如其分。从那以后,cURL 悄然成为了互联网基础设施的一部分。如果您曾好奇 cURL 究竟是什么、开发者为何如此依赖它,答案就在于它的简单与灵活。
不过您来这里应该不是为了了解历史(如果您对 cURL 的历史感兴趣,可以阅读这篇文章)。您更想知道的是如何使用它,以及它如何适配您的使用场景。那么,我们先从在您的设备上找到并运行它开始。
如何安装 cURL
如果您使用的是现代系统,cURL 很可能已经预装。在尝试手动安装之前,请先用 curl --version 命令确认是否可用。
在 Windows 上安装 cURL
我们先检查一下系统中是否已经安装了 cURL:
步骤一:打开 CMD
按下“Windows + R”,然后输入“cmd”即可打开命令提示符。
步骤二:检查是否已安装 cURL
粘贴以下 cURL 命令:
curl --version
按下回车键,如果您看到类似这样的版本信息,

那就说明一切就绪,cURL 已经安装在您的设备上,可以直接跳转到“理解 cURL 语法”部分继续阅读。
步骤三:手动下载 cURL(如有需要)
如果尚未安装,或者想使用更新的版本,请前往 cURL for Windows 下载页面。

步骤四:选择合适的下载版本
选择适合的构建版本,系统会提示您下载并保存 zip 文件。

步骤五:为 cURL 新建一个文件夹
建议在一个比较稳妥的位置新建文件夹,例如本地磁盘 C。只需在文件夹列表的任意空白处右键单击,并将鼠标悬停在“新建”上即可。

步骤六:准备新文件夹
右侧会出现“文件夹”选项,点击它。再点击“新建文件夹”,系统会提示您为其命名,这里我们将其命名为“cURL”。

步骤七:将 zip 文件保存到新文件夹中
点击“保存”,等待 zip 文件下载完成。
步骤八:找到 cURL 的 zip 文件
找到已下载的文件并选中它。

步骤九:找到解压 cURL 文件的选项
右键单击下载的 cURL 压缩包,会弹出一个下拉菜单。

步骤十:解压 zip 文件
选择“全部提取”,并选择要解压到的位置。

步骤十一:打开解压后的文件
点击“提取”,等待文件解压完成,完成后右键单击新生成的文件。

步骤十二:复制解压文件的路径
在弹出的下拉菜单中,点击“复制为路径”,然后将路径粘贴到一个安全的地方保存,它看起来应该是这样的:
c:\cURL\curl-8.15.0_4-win32-mingw
步骤十三:打开开始菜单
按下 Windows 键,或点击屏幕左下角的 Windows 图标。在弹出的菜单中输入“环境变量”并打开它。

步骤十四:打开环境变量
在系统属性菜单底部点击“环境变量”。

步骤十五:编辑系统路径
在“系统变量”中找到“Path”,选中它,然后点击“编辑”。

步骤十六:将 cURL 文件夹添加到系统路径中
点击“新建”,粘贴此前复制的解压文件路径。

步骤十七:保存更改
点击“确定”。
步骤十八:验证安装结果
返回命令行工具,粘贴以下 cURL 命令:
curl --version
一切顺利的话,您现在应该能看到新安装的 cURL 版本号。
在 macOS 上安装 cURL
大多数 macOS 版本都默认自带 cURL,我们先来检查一下这个命令行工具是否已经安装:
步骤一:打开终端
按下“Cmd + Space”,输入“Terminal”打开命令行界面。
步骤二:检查 cURL 是否已经安装
执行以下 cURL 命令:
curl --version
如果显示当前 cURL 的版本信息,就说明一切就绪;如果出现错误,则需要手动安装 cURL。
步骤三:安装 Homebrew(如有需要)
首先需要检查是否已安装 Homebrew:
brew --version
如果出现错误提示,请执行以下命令:
/bin/bash -c "$(curl -fsSL
https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
让安装程序运行,并按照提示完成 Homebrew 的设置和 shell 的更新。
步骤四:重启终端
安装完成后,关闭并重新打开终端。
步骤五:通过 Homebrew 安装 cURL
执行以下命令,通过 Homebrew 安装 cURL:
brew install cURL
步骤六:验证安装结果
执行以下命令确认安装成功:
/opt/homebrew/bin/curl --version
您应该能看到 cURL 版本的详细信息。
在 Linux 上安装 cURL
大多数 Linux 发行版都预装了 cURL,不过我们还是先确认一下。
步骤一:打开终端
按下“Ctrl + Alt + T”打开终端。
步骤二:检查是否已安装 cURL
执行以下 cURL 命令:
curl --version
如果看到版本信息,就说明一切就绪;如果没有,则说明尚未安装 cURL。
步骤三:安装 cURL(如尚未安装)
更新软件包列表:
sudo apt update
然后安装 cURL:
sudo apt install curl -y
到这里,您应该已经知道“cURL 是什么、我的系统中是否已经安装”这个基本问题的答案了。接下来,我们来看看它究竟是如何工作的。
理解 cURL 语法
掌握 cURL 语法最简单的方式就是上手实践。我们将使用 MockAPI 进行练习,这是一款免费工具,可以快速搭建一个测试 API 用于发送请求。
创建 MockAPI 账户以供练习
按照以下步骤创建您的免费 MockAPI 账户:
步骤一:注册 MockAPI
访问官网,创建一个免费账户,并按照提示完成设置。

步骤二:创建新项目
在 MockAPI 控制台中,点击蓝色的“+”图标创建新项目。

将其命名为“cURL Test”(或任意您喜欢的名称),API 前缀可以留空。

点击“创建”,您的项目会出现在下一个界面中。

步骤三:打开项目
选中项目将其打开。

步骤四:创建新资源
点击“New Resource”创建新资源,并将其命名为“users”。

步骤五:在 Schema 中添加自定义字段
您会看到一些默认字段,比如“id”“createdAt”等。点击蓝色的“+”按钮可以添加自己的默认字段,以下是我们用于示例的字段:

在 MockAPI 的 Schema 中,效果如下所示:

点击“创建”按钮。

步骤六:打开资源
“users”资源现已就绪。点击 users 方框即可打开数据视图,您可以在此手动添加记录,也可以使用 cURL 自动创建、修改和更新数据。

您会在地址栏中看到完整的端点 URL,请将其复制并妥善保存。
通过 API 请求掌握 cURL 语法
现在打开终端,让我们开始动手,发送一些 API 请求:
cURL 基本语法
以下是基本的 cURL 命令:
curl [OPTIONS] [URL]
它包含三个核心部分:
- curl:命令行工具本身
- [OPTIONS]:用于修改请求的参数标志(稍后会详细介绍)
- [URL]:您要发送请求的目标地址
了解了这些基础知识后,接下来我们来聊聊使用 cURL 可以发送的不同类型的请求。
使用 cURL 发送 GET 请求
第一种请求类型是 GET,顾名思义,它用于获取数据。
在我们的 MockAPI 设置中,我们将用它发送 API 请求,获取资源中的用户数据。只需在终端中输入 cURL 命令,后面加上此前复制的端点即可:
curl https://68a41d6cc123272fb9b1603e.mockapi.io/users
输出结果如下:

您会发现什么都没有返回。这是因为我们还没有添加任何实际数据,只是定义了字段。这就引出了第二种 API 请求类型。
发送 POST 请求添加新数据
既然资源目前为空,我们来尝试用 POST 请求添加几个用户。下面是一份模拟数据表:

现在我们需要把这些数据转化为一条 cURL 命令,向 MockAPI 端点发送 POST 请求:
curl -X POST https://68a41d6cc123272fb9b1603e.mockapi.io/users -H "Content-Type: application/json" -d "{\"name\":\"Jane Doe\", \"email\":\"jane@example.com\", \"role\":\"Admin\"}" && ^
curl -X POST https://68a41d6cc123272fb9b1603e.mockapi.io/users -H "Content-Type: application/json" -d "{\"name\":\"John Smith\", \"email\":\"john.smith@example.com\", \"role\":\"Contributor\"}" && ^
curl -X POST https://68a41d6cc123272fb9b1603e.mockapi.io/users -H "Content-Type: application/json" -d "{\"name\":\"Ada Lovelace\", \"email\":\"ada@history.dev\", \"role\":\"Developer\"}"
我们来拆解这条 cURL 命令,让它不再只是一堆看不懂的符号:
- curl
这是我们用来发送 POST 请求的工具。
- -X
-X 属于 cURL 命令选项中的一类,叫做标志(flag)。可以把它们想象成一个个小开关,用来改变 cURL 的行为方式:告诉 cURL 要发送哪种类型的请求(比如 POST 而不是 GET)、以何种格式处理数据(比如 JSON)、是否添加请求头,甚至响应结果要保存到哪里。以下是常见 cURL 命令选项的介绍:

我们使用了 -X 这个 cURL 命令选项,紧接着是 POST,这告诉 cURL 您正在发起一个 POST 请求。
- https://68a41d6cc123272fb9b1603e.mockapi.io/users
这就是您之前从 MockAPI 复制的端点,POST 请求会发送到这里,将新的用户数据添加到 users 资源中。
- -H "Content-Type: application/json"
这个标志会为您的 POST 请求添加额外信息。在这里,它相当于告诉服务器:“我发送的内容是 JSON 格式。”
- -d
接下来是 -d 标志,用来告诉 cURL 我们即将在请求体中发送数据。
- JSON 数据:“{\"name\":\"Jane Doe\", \"email\":\"jane@example.com\", \"role\":\"Admin\"}”
现在,为了理解为什么我们要把整个内容放进引号里并添加这么多反斜杠,不妨先看看这段 JSON 本身简洁易读的原始形式:
{
"name": "Jane Doe",
"email": "jane@example.com",
"role": "Admin"
}
很简单,对吧?但如果直接把它输入终端,就像这样:
curl -X POST -H "Content-Type: application/json" -d {
"name": "Jane Doe",
"email": "jane@example.com",
"role": "Admin"
} https://example.com/users
这样是不行的。无论您使用的是命令提示符、Bash 还是 Zsh,您发送的数据几乎肯定会出错,原因如下:
首先,当 CMD 在 -d 后面看到花括号时,它可能会以为您在开启一个代码块,尤其是在脚本环境下;其次是空格问题——终端不会把这段数据当作一个连续的完整参数,而是会将其拆分成多个独立的片段,比如 {、"name":、"Jane Doe" 等,这些片段都无法正确传递给 cURL。
这就是为什么我们要对双引号进行转义,并把整段数据压缩成一行长字符串——本质上,您是在终端命令里的一个字符串中发送 JSON,而这一点会改变一切。
为了避免这种混乱,我们使用反斜杠来转义内部的引号:
"{\"name\":\"Jane Doe\", \"email\":\"jane@example.com\", \"role\":\"Admin\"}"
这是在告诉 CMD:“内部这些引号并不是字符串的结束标志,它们只是我想发送的 JSON 内容的一部分。”
- &&
我们来聊聊这两个符号。MockAPI 虽然很适合用来做演示,但一次只能发送一个请求(不支持批量操作)。而我们需要添加三个用户,如果分别用三个独立的 POST 请求来完成,效率实在太低。
这时候 && 就派上用场了。它会告诉终端:“只有在前一条命令执行成功后,才运行下一条命令。”于是,我们把三条 cURL POST 请求串联在同一行中,每一条都要等上一条成功后才会执行。
- ^(插入符号)
在 Windows CMD 中,每一行通常都会被当作一条独立的命令。如果您在命令还没写完时就按下回车,CMD 就会尝试执行它,问题也就随之而来。
这就是为什么我们要使用插入符号(^)——它会告诉 CMD 当前这一行还没有结束,这样 CMD 就会继续读取下一行的内容。
因此,即使您把命令写成了多行,CMD 仍然会把它当作同一个 POST 请求来处理,插入符号只是让命令更易读,同时不会让终端产生混淆。
接下来,只需对剩下的两个用户重复同样的写法即可。把完整的命令粘贴到终端中,您很可能会看到类似这样的警告:

不用担心,我们已经用插入符号(^)正确地拆分了各行,直接点击“Paste anyway”即可。

完成后,cURL 会依次发出每一个 POST 请求,逐一填入各字段。要确认是否成功,回到 MockAPI 资源页面点击“Refresh”即可。

这里显示的是我们用 cURL 发送这些 POST 请求后,MockAPI 返回的原始 JSON 响应。
每个用户都被包裹在花括号 {} 中,Jane Doe、John Smith 和 Ada Lovelace 这三位用户都被列在同一个长数组里,这说明您的 cURL 命令全部执行成功。
下面快速说明一下每个用户数据中各字段的含义:
- "createdAt" 是 MockAPI 记录该请求的时间
- "name"、"email" 和 "role" 就是您发送的原始数据
- "avatar" 是头像图片的 URL
- "active" 表示该用户是否被标记为激活状态(我们把它们都设为了 false)
- "id" 是自动生成的
简而言之,如果您看到的是这样的结果,就说明一切正常:您发送了数据,MockAPI 也成功接收了,这就是 cURL 中 POST 请求的工作方式!
使用 PUT 请求替换数据
当您需要替换资源中已有的数据时,PUT 请求就派上用场了。比如团队新加入了一名开发者,这时就该更新数据库了。
在此之前,我们再来看一眼 users 资源中花括号里的数据:
[
{
"createdAt": "2025-08-18T11:45:52.086Z",
"name": "Jane Doe",
"avatar":
"https://cdn.jsdelivr.net/gh/faker-js/assets-person-portrait/female/512/22.jpg",
"email": "jane@example.com",
"role": "Admin",
"active": false,
"id": "1"
},
{
"createdAt": "2025-08-19T02:33:05.804Z",
"name": "John Smith",
"avatar": "https://avatars.githubusercontent.com/u/89730203",
"email": "john.smith@example.com",
"role": "Contributor",
"active": false,
"id": "2"
},
{
"createdAt": "2025-08-19T00:58:20.811Z",
"name": "Ada Lovelace",
"avatar":
"https://cdn.jsdelivr.net/gh/faker-js/assets-person-portrait/male/512/40.jpg",
"email": "ada@history.dev",
"role": "Developer",
"active": false,
"id": "3"
}
]
这样一来就更容易看清我们要处理的数据了——每个用户末尾都有一个 ID:"id": "1"、"id": "2"、"id": "3",这就是我们的参照依据。
如果我们要更新开发者这一职位,就需要定位到 "id": "3" 的用户。
Ada Lovelace 离开了,Ian Deacon 加入进来,我们将使用 PUT 请求完全替换掉 ID 为 3 的用户数据。
下面是我们要发送的更新后的 JSON 数据:
{
"name": "Ian Deacon",
"avatar":
"https://cdn.jsdelivr.net/gh/faker-js/assets-person-portrait/male/512/12.jpg",
"email": "ian.deacon@example.com",
"role": "Developer",
"active": true
}
以下就是实现这一操作的 cURL 命令:
curl -X PUT ^
-H "Content-Type: application/json" ^
-d "{\"name\":\"Ian Deacon\",
\"avatar\":\"https://cdn.jsdelivr.net/gh/faker-js/assets-person-portrait/male/512/12.jpg\", \"email\":\"ian.deacon@example.com\",
\"role\":\"Developer\", \"active\":true}" ^
https://68a41d6cc123272fb9b1603e.mockapi.io/users/3
下面逐一说明这段命令的含义:
- curl
这是我们的命令行工具,无需多作解释。
- -X PUT ^
-X 参数告诉 cURL 这是一个 PUT 请求,我们用插入符号(^)来换行。
- -H "Content-Type: application/json" ^
-H 参数用于添加请求头,这里是告诉 cURL 我们发送的是 JSON 数据,再次使用插入符号来保持命令整洁。
- -d "{\"name\":\"Ian Deacon\", \"avatar\":\"https://cdn.jsdelivr.net/gh/faker-js/assets-person-portrait/male/512/12.jpg\", \"email\":\"ian.deacon@example.com\", \"role\":\"Developer\", \"active\":true}" ^
-d 参数的意思是:“cURL,请求体里有数据。”实际的 JSON 内容用引号包裹,并通过反斜杠转义,以免 CMD 误读;随后我们再用插入符号换行。
- https://68a41d6cc123272fb9b1603e.mockapi.io/users/3
最后,我们把整条命令指向目标 API 端点。注意到区别了吗?这次端点末尾多了 /3,正是我们要更新的那个用户的 ID。
把这段代码粘贴到终端中并执行,如果出现警告,直接点击“Paste anyway”即可。

就这样,我们把 Ada Lovelace 替换成了 Ian Deacon。
这是我们在 CMD 中使用 PUT 请求执行的完整 cURL 命令。我们将目标指向 /users/3(也就是 Ada 原来的 ID),并把她的数据替换成了 Ian 的:新姓名、新邮箱、新头像,还把他标记为了激活状态。
返回结果确认了替换成功,回到资源页面点击“Refresh”也可以验证这一点。

现在可以看到,Ian Deacon 已经作为 ID 为 3 的开发者出现在这里了。
使用 PATCH 请求更新字段
Jane Doe 刚刚获得晋升,现在是 CEO,我们需要在 API 中反映这一变化。
这正是 PATCH 请求派上用场的地方——当您只想更新某一项数据而不改动其余内容时,它再合适不过。
在这个例子中,我们已经知道 Jane 的 ID 是 1,所以直接定位到这个 ID;由于只需要修改她的角色,我们在数据中也只传入这一个字段即可。
以下是对应的 JSON 数据:
{
"role": "CEO"
}
以下是对应的 cURL 命令:
curl -X PATCH ^
-H "Content-Type: application/json" ^
-d "{\"role\":\"CEO\"}" ^
https://68a41d6cc123272fb9b1603e.mockapi.io/users/1
已经开始熟悉这种写法了吧?我们来逐一拆解一下:
- curl X PATCH ^
这里我们通过 -X 参数告诉 cURL 这是一个 PATCH 请求,然后用插入符号结束这一行。
- -H "Content-Type: application/json" ^
-H 参数依旧用于把请求头设置为 JSON,和之前的做法一样,再次用插入符号换行。
- -d "{\"role\":\"CEO\"}" ^
这里我们用 -d 参数传入数据,只更新 role 这一个字段,并为它赋一个新值。
- https://68a41d6cc123272fb9b1603e.mockapi.io/users/1
最后,我们直接访问该 API 端点,目标是 ID 为 1 的用户。
把这条 cURL 命令粘贴进去并按下回车(和之前一样,忽略报错即可)。

可以清楚地看到,cURL 已成功将角色从 Admin 更新为 CEO,这一变化在资源中也同步体现出来:

使用 DELETE 请求删除记录
假设公司刚被收购,我们的贡献者 John 被辞退了,cURL 可以轻松地在 API 中反映这一变化,只需执行:
curl.exe -X DELETE ^
https://68a41d6cc123272fb9b1603e.mockapi.io/users/2
流程和之前一样:先写 cURL,再用 -X 参数声明请求类型(这里是 DELETE),然后定位到 John 的专属端点 /users/2。
粘贴这条 cURL 命令,忽略报错,然后按下“Enter”。

回到您的 API 页面并刷新:

John 已经不在了,ID 2 已成功从 API 中删除。
如果您想删除另一条记录,比如 ID 为 1 的记录,只需修改端点末尾的数字即可:
https://68a41d6cc123272fb9b1603e.mockapi.io/users/1
就是这么简单!
为什么 cURL 命令如此强大?
说完这些,我们再来聊聊为什么 cURL 会成为各类终端工作流中高度依赖的工具之一。
协议无关性
设想这样一个场景:您需要备份公司的关键资源,部分日志来自云服务器,可以通过 HTTPS 访问;日常报告则存放在老旧的本地服务器上,只能通过 FTP 访问。
此外,还有一些机密知识产权(IP)数据,只能从一台加固的堡垒机(bastion)通过安全复制协议(SCP)访问;要管理这一切,通常意味着要在多种工具之间切换,或者为每种协议单独编写客户端。
但使用 cURL 就不必如此,这正是其协议无关性的优势所在:您可以用同样的 cURL 命令格式访问上述所有数据源。
以下是一条使用 -i 参数、针对 GitHub 公共 API 发出的基本 GET 请求 cURL 命令:
curl -i https://api.github.com
要理解其底层原理,需要先了解libcurl——这个可移植的 C 语言库支撑着您执行的每一条 cURL 命令,在幕后处理协议、连接、数据传输、重试和错误等全部网络逻辑。
执行命令后,cURL 首先要做的是解析 URL 协议头。https:// 这个前缀之所以重要,是因为它告诉 cURL 应该从 libcurl 中调用哪个协议处理程序;在这里,它会询问:“我们有没有针对 HTTPS 的处理程序?”libcurl 给出肯定的答复。
所谓处理程序,是 libcurl 内部一个独立的协议模块,知道如何与特定协议进行通信。以 HTTPS 为例,它知道如何建立安全连接、发送请求、格式化请求头或命令、接收并解析响应——上面那条响应正是这样得到的。
现在,假设您想查询GNU Bash release目录,尽管这个目录是通过 FTP 托管的,您依然可以使用同样熟悉的语法:
curl -i ftp://ftp.gnu.org/gnu/bash/
这就是协议无关性的核心所在:您只需替换 URL,剩下的交给 cURL 处理即可。以下是它支持的主要协议:
- HTTP:互联网的基础协议,支撑 REST API、网站等
- HTTPS:加密连接的安全版 HTTP
- FTP:用于远程目录和旧系统的文件传输协议
- FTPS:基于 SSL/TLS 的安全文件传输版 FTP
- SFTP:基于 SSH 的文件传输协议,常用于安全性要求较高的企业环境
- SCP:安全复制协议,同样基于 SSH
- SMTP:用于发送邮件
- SMTPS:安全版 SMTP
- POP3:用于接收邮件
- POP3S:安全版 POP3
- IMAP:另一种邮件协议
- IMAPS:安全版 IMAP
- LDAP:用于访问目录服务
- LDAPS:安全版 LDAP
- DICT:词典协议(用于查询释义)
- FILE:通过 file:// URI 访问本地文件
- TELNET:用于操作 telnet 服务
- TFTP:简单文件传输协议(常用于嵌入式系统)
- RTMP:用于流媒体传输的实时消息传输协议
- RTSP:用于媒体传输的实时流传输协议
- GOPHER:早于 HTTP 的内容协议,出于兼容旧系统的原因仍受支持
- SMB / SMB2:Windows 网络文件共享协议
不受平台限制
cURL 强大的另一个原因在于它不受平台限制——这不仅意味着它可以在任何平台上运行,更意味着无需任何修改即可在任意平台上运行。
无论在 Linux、macOS、Windows 还是其他系统上,之前用于从 GitHub 或 GNU Bash 目录获取信息的同一条命令都会返回相同的结果。
这一切都要归功于 cURL 背后的核心——libcurl。正如之前提到的,它是一种基于 C 语言、轻量且高度可移植(重点是可移植)的网络引擎。
只要存在 C 编译器,libcurl 就能运行,这意味着同一条 cURL 命令既能在运行 Debian 的 2013 款 ThinkPad 上执行,也能在 ARM 服务器的 Docker 容器中运行,还能在使用 PowerShell 的 Windows 11 设备上运行。
不限定使用场景
cURL 不关心您的身份角色,它并非只为数据分析师或网络爬虫开发者而生,它唯一在意的是您是否懂得互联网的“语言”。
可以把 cURL 想象成在网络中运送数据的车厢,而 libcurl 则是驱动这些车厢在任意轨道(协议)上运行的引擎。
这正是 cURL 能够适配多种角色的原因:
- 开发者
进行网络开发时,您需要可靠、可测试的请求,cURL 可以成为代码与外部世界之间的默认桥梁。无论请求头、负载还是协议如何设置,cURL 都能顺畅执行。
- 安全工程
借助简单且可脚本化的命令,cURL 可以帮助您测试服务器漏洞、验证 TLS 配置、评估防火墙或 WAF 规则的响应情况,清晰呈现系统的实际行为。
- 数据专业人员
如果您的工作涉及从网站收集数据,cURL 可以帮助实现自动化流程。不过,对于动态或大量依赖 JavaScript 的网站,由于 cURL 在处理客户端渲染方面存在局限,通常更适合搭配其他工具使用。
- 金融与科研
金融从业者常用 cURL 轮询 Benzinga、Reuters、Finviz 等财经新闻 API,从而自动掌握市场动态,无需人工查看。在科研领域,cURL 可用于从 PubMed 等来源获取科学数据,或向远程计算服务提交任务。
如果您所在的行业依赖数据,而这些数据可以通过 URL 访问,那么 cURL 可以成为得力工具。但客观来说,它并非万能:面对大量依赖 JavaScript 的页面时表现吃力,也无法单独绕过高级反机器人防护机制。
cURL 的局限之处
假设您想抓取Amazon 上好评较多的手机壳数据,听起来很简单,对吧?
您执行以下 cURL 命令:
curl -i
https://www.amazon.com/Best-Sellers-Cell-Phones/zgbs/wireless/7072561011
返回结果如下:

您会看到 503 状态码,这说明服务器在线,但拒绝放行。原因在于 cURL 无法识别 JavaScript,既无法处理动态渲染,也无法绕过 Amazon 多层反机器人防护机制。它只能获取服务器返回的原始响应,而 Amazon 在这里并未提供任何有用内容。
简而言之,当内容公开可访问、或易于直接获取时,cURL 往往能顺利完成任务;一旦内容被 JavaScript、防火墙或速率限制层层阻拦,就需要借助更强大的工具。
第一步可以打开浏览器的网络面板,查看数据是否通过简洁的 API 或 JSON 文件加载。如果是,那么 cURL 仍然可能适用。
如果不是,就需要借助 Selenium 等无头浏览器,它们能够模拟真实用户会话,并像浏览器一样渲染页面。在此基础上,可以结合更智能的抓取策略,例如退避逻辑、住宅代理轮换,以及更接近真实用户行为的操作模式。
这种组合能帮助您借助稳定的 IP 发送更接近真实用户行为的请求,不易引发网站警觉。
用 cURL 抓取 Amazon 数据,不再被 503 拦截
获取住宅代理排查常见 cURL 错误
至此,您已经了解了 cURL 是什么、如何安装、以及其工作原理。但实际使用中难免会遇到问题,因此了解常见的 cURL 错误及其排查方法同样重要。
连接错误
有时执行 cURL 命令后,会出现以下错误:
curl: (7) Failed to connect to example.com port 443: Connection refused
cURL 成功访问了服务器,但连接被拒绝,可能的原因如下:
- 端口错误:请求的是 443 端口上的 HTTPS,但服务器只在 80 端口提供普通 HTTP 服务
- 防火墙拦截:服务器可能通过防火墙屏蔽了您的 IP、所在地区或整个端口
- 服务未运行:nginx 或 Apache 可能未启动,或配置有误而未监听请求
- DNS 不匹配:域名可以解析,但服务器无法识别该域名,或未配置为处理相应请求
总之,服务器确实存在,只是没有放行 cURL。您需要找出究竟是哪一把“锁”挡住了您的“钥匙”,具体排查方法取决于目标网站的情况。
Ping 目标地址
首先可以 ping 该网站,检查其在网络层面是否可达。如果 ping 通但 cURL 请求失败,说明服务器在线,问题很可能出在端口或服务本身。
ping yourtarget.com
使用 netcat(或 telnet)测试端口连通性
确认服务器可通过 ping 访问后,下一步是检查目标端口是否确实处于监听状态。
这时就需要用到 nc,执行以下命令:
nc -zv yourtarget.com 443
具体说明如下:
- nc 是 netcat 的缩写
- -z 表示仅探测端口而不发送数据
- -v 表示启用详细模式,以获取清晰的反馈信息
- 443 是端口号,HTTPS 的标准端口
如果端口开放并接受连接,会显示成功信息;如果不行,则会明确告知失败原因。由此即可判断服务是否在线,或 cURL 是否遇到了死路。
如果未安装 netcat,也可以使用 telnet,执行以下命令:
telnet example.com 443
切换到详细模式,查看 cURL 所看到的信息
当情况不如预期时,可以开启详细模式,追踪连接的每个步骤,从而准确定位问题所在。
使用以下 cURL 命令执行:
curl -v https://yourtarget.com
您将看到完整的执行过程。
使用 traceroute 查看数据包在何处中断
如果您身处防火墙或代理之后,traceroute 可以帮助您追踪请求在到达服务器之前经过的每一个节点(无论是否成功到达),从而清楚看到连接在何处中断。
执行方法如下:
traceroute yourtarget.com
这样即可清晰看到完整的路由路径。
SSL 证书错误
SSL 全称为 Secure Sockets Layer(安全套接层),TLS 全称为 Transport Layer Security(传输层安全协议),二者都是保障网络连接安全的协议。
您每天都在使用它们,却很少留意——输入 https:// 时地址栏出现的小锁图标,正是 SSL 在发挥作用。
SSL 证书就像服务器的数字护照,用于确认服务器身份、证明连接已加密,并表明该证书由受信任的机构签发。
一张典型的 SSL 证书通常包含以下信息:
- 服务器的公钥
- 证书适用的域名(如 api.example.com)
- 签发该证书的证书颁发机构(CA)
- 有效期
- CA 的数字签名
当证书存在问题时就会出现错误,常见原因如下:
- 自签名证书:服务器自行签发证书,而非使用受信任的机构
- 证书过期:证书的有效期已结束,不再被视为安全
- 域名不匹配:您访问的是 abc.com,但证书上显示的是 xyz.com
- 根证书不受信任:签发该证书的机构不在您的受信任证书列表中
- 系统时间误差:系统时钟不准确,可能导致有效证书显示为已过期或尚未生效
如果您访问的网站并非由您管理,首先应联系网站所有者核实情况。您也可以在浏览器中打开该网站,点击锁图标查看证书详情,通常即可判断证书是否已过期、是否为自签名、或是否由系统不信任的 CA 签发。
如果问题出在证书颁发机构不受信任,不要直接跳过验证,可以通过以下 cURL 命令手动指定受信任的 CA:
curl --cacert /path/to/trusted-root.pem https://yourtarget.com
这样既能保证安全性,又无需关闭 SSL 验证。如果您本身管理该服务器,更推荐直接更新证书。只有在确实必要时,才应跳过证书验证。
超时与响应缓慢
根据您的 IP、目标网站以及尝试获取的数据类型,cURL 请求有时会像卡住一样迟迟没有响应,但这并不一定意味着服务器已宕机。如果这种情况经常出现,不妨了解如何设置 cURL 超时时间,让请求快速失败,而不是无限期挂起。
服务器可能处于不可用、过载、或故意拖延响应的状态。有些目标网站看似即将返回响应,实则卡住不动,这可能是有意为之,也可能是配置错误所致。以下是解决该问题的方法。
Ping 目标地址
首先 ping 目标地址:
ping yourtarget.com
如果没有响应,问题可能出在网络层面:服务器可能已宕机、DNS 配置有误,或防火墙正在拦截请求。
接下来需要逐步排查缩小范围。
检查端口是否开放
接下来,确认目标端口是否确实处于监听状态,这时可以借助 netcat 或 telnet。
Netcat:
nc -zv yourtarget.com 443
nc 是 netcat 的缩写,-z 表示仅扫描端口而不发送数据,-v 则启用详细输出,便于查看具体情况。
如果没有安装 netcat,可以尝试 telnet,它的普及度更高,命令也更简单:
Telnet:
telnet yourtarget.com 443
使用详细模式追踪连接的各个阶段
如果仍然无法判断问题所在,可以切换到详细模式,它会展示连接的每个阶段,帮助您准确定位卡顿位置。
curl -v https://yourtarget.com
当您需要查看 cURL 所看到的信息时,可以使用该模式。
使用 curl -w 测量各阶段耗时
这种方法设置起来稍显繁琐,但配置完成后使用非常简单,它可以测量连接各阶段所耗费的时间,从而准确找出延迟出现的位置。
- 第一步:打开文本编辑器
打开一个空白文本编辑器,用于创建自定义输出格式。
- 第二步:粘贴计时模板
添加 cURL 计时变量,用于追踪请求的各个阶段。
DNS Lookup: %{time_namelookup}s
Connect: %{time_connect}s
SSL Handshake: %{time_appconnect}s
Start Transfer: %{time_starttransfer}s
Total: %{time_total}s
您刚才做的是设置自定义输出格式,让 cURL 清楚显示延迟具体出现在哪个环节。每一行都对应请求过程中的一个阶段:
- DNS 查询:将域名解析为 IP 所花费的时间
- 连接:建立到该 IP 的连接所花费的时间
- SSL 握手:协商安全连接所花费的时间
- 开始传输:服务器实际开始发送数据的时间点
- 总耗时:整个请求从开始到结束所花费的时间
- 第三步:保存文件并复制其路径
将文件保存为 curl-format.txt(在“保存类型”框中选择“所有文件”,以避免生成 .txt.txt 后缀)。复制该文件的路径。
- 第四步:执行计时命令
使用 -w 参数运行 cURL 并结合格式文件,即可查看各阶段的耗时详情。以下是对应的 cURL 命令:
curl -w "yourfilepath" -o NUL -s https://yourtarget.com
您将清楚看到请求在前面提到的每个阶段分别花费了多少秒。
cURL 与 wget:该选哪个工具?
很多人在了解 cURL 是什么之后,也会好奇它与 wget 相比有什么不同。
乍一看,两者十分相似:都能从 URL 获取数据,都在终端中运行,也都常被用在脚本里,很容易混淆。但它们其实并不相同。
那么两者究竟有什么区别?又有哪些重合之处?该在什么情况下选择其中一个?
了解 cURL 与 wget 的工作原理
一边是 cURL,前面已经详细介绍过。另一边是 wget,同样非常实用。
wget 的名字已经说明了一切:web get,意思就是从网络获取文件。给它一个 URL,它就会把文件抓取下来,没有多余的花样,只负责获取和保存。需要的话,它还能递归下载。
下面是一条基础命令,展示它的用法:
wget https://wordpress.org/latest.zip
这条命令会将最新版 WordPress 的压缩包下载到当前目录,是不是很简单?
接下来把 cURL 和 wget 放在一起对比一下:
- 两者都支持 HTTP、HTTPS 和 FTP
- 两者都可以配合代理使用
- 两者都能用来从 URL 下载文件
- 两者都提供身份验证方式
- 两者都能跟随重定向(cURL 使用 -L,wget 使用 --max-redirect)
- 两者在 Shell 脚本和定时任务(cron job)中都表现出色
cURL 与 wget 的区别
两者的区别主要体现在默认行为上。
交互性与自定义能力
这两种工具最明显的区别在于,它们对传输过程的控制程度不同。
- 自定义 HTTP 方法
使用 cURL,您可以完全掌控请求方式:PUT、DELETE、PATCH,任务需要什么就用什么,前面已经介绍过。而 wget 基本只能用 GET 和 POST,仅此而已。
- 自定义请求头
如果您在对接 API,几乎总会用到请求头。cURL 可以轻松设置认证令牌、User-Agent、内容类型等各种所需内容。wget 虽然能伪造 User-Agent,但也就到此为止了。
- 表单提交
cURL 可以使用 POST 模拟浏览器式的表单提交。wget 也能发送数据,但方式比较生硬,因为它本来就不是为这种精细操作设计的。
- Cookie 处理
两种工具都支持 Cookie。cURL 需要您用 -b 和 -c 手动控制,而 wget 更简单,只需设置一次,它就会自动保存并发送 Cookie。
- FTP 上传
需要通过 FTP 或 SFTP 上传文件?cURL 可以干净利落地完成。wget 不支持上传,只能下载。
文件下载与续传
这方面 wget 表现出色,只需加上 -c 参数。如果下载中途中断,它会检查本地文件,与服务器上的版本进行比对,并从中断的地方精确续传。以下是对应的 wget 命令:
wget -c https://example.com/yourfile.zip
cURL 也能续传,但前提是本地已有部分文件、服务器支持范围请求,并且语法正确(-C - 这个参数很关键)。如果涉及重定向或 Cookie,情况就会变得不太稳定。
简单来说,wget 天生就是为应对各种复杂情况而设计的;cURL 只有在精心配置的情况下才能做到同样的事。以下是用 cURL 续传文件下载的命令:
curl -C - -O https://example.com/yourfile.zip
如果您想下载整个网站,wget是更合适的选择,它可以完整镜像整个网站,包括 HTML、图片、脚本、结构等所有内容。
只需在命令中加上 --mirror 即可开始工作。cURL 并不是为此设计的,它一次只能下载一个文件,仅此而已。
安全性与身份验证
在对接现代 API、使用加密连接或需要安全传递凭证时,cURL 是更合适的选择,它可以让您:
- 附加客户端证书以实现双向 TLS 验证
- 指定自定义 CA 证书包
- 在有严格合规要求时锁定加密套件
- 强制指定 SSL/TLS 版本,这在对接旧版 API 或安全限制严格的金融系统时尤为重要
wget 虽然支持 HTTPS 并能验证证书,但功能也就到此为止了。
该在什么情况下使用哪种工具?

结语
能看到这里,非常不错!您现在已经了解了 cURL 是什么、它的工作原理、擅长做什么,以及适合在什么场景下使用。您也见过它的语法、参数,以及各种边界情况。
也许您已经在考虑如何把它融入自己的工作流程,又或者您发现自己的使用场景需要更强大的工具,比如 Selenium 或代理轮换引擎。
但如果您只是需要一种简单可靠的工具来通过 HTTP 下载文件,wget 可能是更简便、更稳定的选择。不管选哪种,现在您已经有了足够的选项,放心使用 cURL 吧。
想结合代理等功能进一步提升 cURL 的使用效果?欢迎加入我们的 Discord 社区。
什么是 cURL 命令?
cURL 命令可以直接在终端中向 URL 传输数据或从 URL 获取数据。您可以用它发送 HTTP 请求、下载文件、测试 API、发送数据或调试网络流量,可以把它理解为一种能与互联网交互的命令行工具。
cURL 代表什么?
cURL 是 Client URL 的缩写。之所以这样命名,是因为它能让您的设备(客户端)通过多种协议与 URL 进行交互,因此得名 Client URL。
cURL 是默认安装的吗?
如果您使用的是 Linux 或 macOS,cURL 通常是预装的,可以打开终端运行 curl --version 来检查。在 Windows 上,从 Windows 10 版本 1803 开始默认也会包含 cURL。如果发现它缺失或运行异常,也可以按照前文介绍的方法安装或更新。
cURL 有什么用途?
cURL 用于通过 HTTP、FTP 等支持的协议向服务器传输数据或从服务器获取数据,常用于测试 API、下载文件,以及在终端中与 URL 进行交互。