Команда curl: опции, POST-запросы и скачивание файлов
Команда curl — это инструмент, который из терминала отправляет запрос на веб-адрес и выводит ответ как есть. Одной строкой можно проверить тело страницы, заголовки и код состояния. Когда мы отправили запросы curl с сервера AlmaLinux 9 на сайт WordPress, http-адрес ответил кодом 301 с указанием https-адреса, а запрос к REST API без аутентификации был отклонён с кодом 401.
1️⃣ Основы команды curl и тело ответа
Если указать после curl один адрес, curl отправит на него GET-запрос и выведет тело ответа на экран. Когда мы запросили robots.txt, который создаёт WordPress, содержимое файла из трёх строк пришло без изменений.
curl https://example.com/robots.txtUser-agent: *
Disallow: /wp-admin/
Allow: /wp-admin/admin-ajax.phpЛегко ожидать ту же страницу, что открывается при вводе адреса в браузере, но curl выводит исходный HTML, присланный сервером. curl не выполняет скрипты и не запрашивает отдельно изображения и CSS. HTML страницы длинный, поэтому для адресов веб-страниц мы передаём вывод через конвейер в head и смотрим только первые несколько строк.
curl -s https://example.com/ | head -n 2<!DOCTYPE html>
<html lang="ko-KR">С -s скрывается индикатор хода, который иначе смешивается с выводом при передаче через конвейер. HTML, полученный только с адреса главной страницы, занял 96 679 байт. Файлы изображений и скриптов в этот размер не входят.
2️⃣ Проверка заголовков через curl -I и переадресации через -L
По одному телу нельзя понять, успешен ли запрос, поэтому код состояния и заголовки проверяются отдельно через -I. -I отправляет HEAD-запрос и выводит только заголовки ответа, без тела. Это как прочитать транспортную накладную, не открывая посылку.
curl -I https://example.com/HTTP/2 200
server: nginx/1.28.0
date: Wed, 28 Oct 2026 05:29:23 GMT
content-type: text/html; charset=UTF-8
vary: Accept-Encoding
last-modified: Tue, 27 Oct 2026 21:12:18 GMT
cache-control: max-age=0
expires: Wed, 28 Oct 2026 05:29:23 GMT
accept-ranges: none
alt-svc: h3=":443"; ma=86400[HTTP/2 200] в первой строке — это код состояния. Ниже идут тип сервера, тип содержимого и заголовки, связанные с кешем. Если отправить тот же запрос на http-адрес, придёт 301, а в заголовке [Location] будет https-адрес, куда нужно перейти.
curl -I http://example.com/HTTP/1.1 301 Moved Permanently
Server: nginx/1.28.0
Date: Wed, 28 Oct 2026 05:27:51 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Location: https://example.com/При запросе http-адреса без опций curl не стал повторно запрашивать адрес из [Location]: он вывел только 7 строк тела ответа 301 и завершил работу.
curl http://example.com/<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.28.0</center>
</body>
</html>С -L curl повторно запрашивает адрес из [Location]. Если объединить его с -I и запустить -IL, после заголовков ответа 301 по порядку идут заголовки ответа 200.
curl -IL http://example.com/HTTP/1.1 301 Moved Permanently
Server: nginx/1.28.0
Date: Wed, 28 Oct 2026 05:29:23 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Location: https://example.com/
HTTP/2 200
server: nginx/1.28.0
date: Wed, 28 Oct 2026 05:29:23 GMT
content-type: text/html; charset=UTF-8
vary: Accept-Encoding
last-modified: Tue, 27 Oct 2026 21:12:18 GMT
cache-control: max-age=0
expires: Wed, 28 Oct 2026 05:29:23 GMT
accept-ranges: none
alt-svc: h3=":443"; ma=86400На схеме ниже можно по шагам сравнить, сколько запросов уходит и что появляется на экране при каждой опции.
3️⃣ Скачивание файлов командой curl (-o, -O)
-O сохраняет файл в текущую папку под последним именем файла из адреса. Во время сохранения на экране вместо тела показывается индикатор хода.
curl -O https://example.com/wp-includes/images/w-logo-blue.png % Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
100 3113 100 3113 0 0 178k 0 --:--:-- --:--:-- --:--:-- 190kls -l w-logo-blue.png-rw-r--r-- 1 root root 3113 Oct 28 14:29 w-logo-blue.pngПосле скачивания [Total] и [Received] в индикаторе хода оба показали 3113, а размер файла, проверенный через ls -l, тоже совпал: 3113 байт.
Чтобы самому задать имя файла, напишите его после -o. Ниже — результат сохранения адреса главной страницы как home.html.
curl -o home.html https://example.com/ % Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
100 96679 0 96679 0 0 4291k 0 --:--:-- --:--:-- --:--:-- 4291kls -l home.html-rw-r--r-- 1 root root 96679 Oct 28 14:29 home.html-O берёт имя файла в конце адреса как есть, поэтому не подходит для адресов страниц, которые заканчиваются косой чертой. Если добавить -O к адресу главной страницы, curl не найдёт имя файла и завершится с ошибкой ниже.
curl -O https://example.com/curl: Remote file name has no length!
curl: (23) Failed writing received data to disk/application4️⃣ POST-запросы curl и отправка данных JSON
Чтобы отправить данные запросом, который до этого только читал, используйте -d, а чтобы указать формат данных, добавьте -H. -d отправляет записанные после него данные как тело POST. Если ничего не указано, [Content-Type] равен [application/x-www-form-urlencoded].
С -d метод запроса меняется на POST, поэтому [-X POST] можно не писать. Официальная документация тоже поясняет, что -X обычно не нужен.
При отправке JSON смените через -H [Content-Type] на [application/json]. Ниже — результат запроса на создание записи, отправленного в REST API WordPress без аутентификации.
curl -s -X POST -H 'Content-Type: application/json' -d '{"title":"curl test"}' https://example.com/wp-json/wp/v2/posts{"code":"rest_authentication_error","message":"\uc8c4\uc1a1\ud569\ub2c8\ub2e4. REST API \uc694\uccad\uc744 \ud560 \uc218 \uc788\ub294 \uad8c\ud55c\uc774 \uc5c6\uc2b5\ub2c8\ub2e4.","data":{"status":401}}Сайт, на который мы отправили запрос, блокирует запросы к REST API от пользователей, не вошедших в систему поэтому code вернул [rest_authentication_error], а статус был 401. Из-за той же настройки GET-запрос списка записей на тот же адрес тоже вернул 401. Значение message — это сообщение об ошибке на языке сайта, преобразованное в Unicode-запись JSON.
Чтобы проверить только код состояния, отбросьте тело через [-o /dev/null] и выведите через -w только http_code.
curl -s -o /dev/null -w '%{http_code}\n' -X POST -H 'Content-Type: application/json' -d '{"title":"curl test"}' https://example.com/wp-json/wp/v2/posts4015️⃣ Измерение времени ответа командой curl (-w)
Когда ответ медленный, легко смотреть только на total, но чтобы понять, ушло ли время на соединение или на обработку на сервере, нужно вывести время каждого этапа отдельно. -w после завершения запроса выводит измеренные значения в заданном формате. Значения подставляются на места [%{имя переменной}] в формате.
Тело отбросьте через [-o /dev/null], а индикатор хода скройте через -s.
curl -o /dev/null -s -w 'code: %{http_code}\nconnect: %{time_connect}\ntls: %{time_appconnect}\nttfb: %{time_starttransfer}\ntotal: %{time_total}\n' https://example.com/code: 200
connect: 0.001507
tls: 0.017728
ttfb: 0.021912
total: 0.022825connect — это TCP-соединение, tls — согласование TLS, ttfb — время до момента перед отправкой первого байта, а total — время до конца передачи. Все четыре значения — секунды, накопленные с начала запроса.
Поскольку сервер, на котором запускался curl, и сайт, принимавший запрос, находились на одном сервере, соединение заняло всего 0,0015 с, согласование TLS завершилось к 0,0177 с, а первый байт пришёл к 0,0219 с. От конца согласования TLS до прихода первого байта прошло около 0,004 с. Официальная документация поясняет, что этот этап включает время, которое сервер тратит на подготовку результата.
Когда мы запустили ту же команду ещё три раза, total держался в пределах от 0,0219 до 0,0226 с.
🔲 Симулятор команды curl
В симуляторе ниже вы можете сами ввести команды из статьи и проверить, как меняется вывод при каждой опции.
🔢 FAQ & рекомендуемые материалы








ℹ️ О партнёрских ссылках
Материалы этого сайта содержат партнёрские ссылки. Если посетитель покупает товар или услугу по такой ссылке, сайт получает комиссию от продавца. При этом сумма, которую платит покупатель (при акционных скидках сумма снижается ↓), не увеличивается. Указанные цены, скидки и наличие актуальны на момент написания и могут отличаться, поэтому перед покупкой уточняйте их у продавца. Товары выбираются и оцениваются по нашим собственным критериям, а комиссия не влияет ни на порядок, ни на содержание обзоров.