Перейти к основному содержимому

Утилита curl

Разработчику Архитектору Инженеру
Место в разделе «Терминал»

curl отправляет сетевые запросы из консоли — без браузера и без GUI-клиента вроде Postman. Типичные задачи: проверить, что API отвечает, скачать файл, воспроизвести запрос из CI или Bash-скрипта. Запрос часто делают с локальной машины или с сервера, куда вы зашли по SSH / PuTTY. Сборка и деплой рядом — make.


Утилита curl

Вы написали REST-эндпоинт и хотите быстро проверить ответ, не открывая IDE и не настраивая Postman. Или в логах nginx видите 502, и нужно понять, отвечает ли бэкенд напрямую. curl (cURL — Client for URLs) — консольная утилита и библиотека libcurl для передачи данных по HTTP, HTTPS, FTP, SFTP, SMTP и другим протоколам.

curl не рисует страницу как браузер: он показывает «сырой» ответ сервера (тело, заголовки, код статуса) или сохраняет его в файл. Это делает утилиту стандартом для отладки API, health-check в скриптах и автоматизации в DevOps.

HTTP — протокол обмена между клиентом и сервером; метод (GET, POST, …), URL, заголовки и тело запроса. Основы веб-запросов — как работают сайты; тестирование API с Postman — интеграционное взаимодействие.


Как curl выполняет запрос

[Терминал — ваш ПК или сервер]
|
| curl парсит аргументы (URL, -H, -d, -X …)
v
libcurl формирует HTTP-запрос
|
| TCP/TLS (порт 443 для HTTPS)
v
[Веб-сервер / API]
|
v
ответ: статус (200, 404, 500), заголовки, тело
|
v
curl печатает в stdout или пишет в файл (-o)

Один вызов curl — один запрос (если не включены редиректы -L или параллельный режим). В скриптах curl часто комбинируют с jq для разбора JSON и с grep для поиска строк в HTML.


Где установлен curl

ПлатформаКак получитьПроверка
Linuxпакет curl (Debian/Ubuntu, RHEL, Arch — везде в репозиториях)curl --version
macOSпредустановленcurl --version
Windows 10/11curl.exe из пакета Microsoft (в PATH по умолчанию)curl.exe --version
WSLкак в Linuxcurl --version
PowerShell и имя curl

В PowerShell команда curl часто является псевдонимом для Invoke-WebRequest — синтаксис другой (-X POST не сработает). Для настоящей утилиты пишите curl.exe или запускайте из CMD/WSL. Подробнее — Postman и curl для API.

Официальная документация и исходники — curl.se.


Базовые команды

curl печатает тело ответа в stdout (обычно прямо под строкой, где вы нажали Enter). Индикатор загрузки и служебные сообщения идут в stderr — поэтому progress-bar не «ломает» JSON, если вы перенаправляете вывод в файл (> out.json). После завершения снова появляется приглашение оболочки ($, > или PS C:\...>) — запрос закончен.

Проверить код завершения:

curl -s https://httpbin.org/status/200
echo $? # 0 — curl отработал без сетевой ошибки (HTTP 404 без -f тоже даст 0)

GET — получить ресурс

Самый частый случай: URL без дополнительных флагов — это GET. Тело ответа печатается в терминал.

curl https://httpbin.org/get
curl https://example.com

Явный метод (то же самое для GET):

curl -X GET "https://jsonplaceholder.typicode.com/posts/1"

Кавычки вокруг URL обязательны, если в адресе есть &, ? или пробелы — иначе оболочка разрежет строку на части (знаки препинания в CLI).

Пример в терминале — JSON API

Команда (флаг -s убирает progress-bar, остаётся только ответ):

curl -s "https://jsonplaceholder.typicode.com/posts/1"

Типичный вывод — одна «простыня» JSON, без префикса «HTTP 200»:

{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
}

Что это значит: сервер ответил 200 OK и отдал объект поста. Поле id: 1 — идентификатор ресурса в этом учебном API.

Что делать дальше:

ЦельДействие
Прочитать одно полеcurl -s URL | jq -r .title (нужен jq)
Сохранить ответ в файлcurl -s URL -o post.json — файл появится в текущем каталоге (см. pwd)
Убедиться, что API живcurl -s -o /dev/null -w "%{http_code}\n" URL → должно напечатать 200
Красиво отформатировать JSONcurl -s URL | jq .

Пример в терминале — HTML-страница

curl -s https://example.com | head -5

Вывод начинается с <!doctype html> и тегов <html>, <head>, <title>Example Domain</title> — это исходный HTML, не отрисованная страница браузера. Для проверки «сайт отдаёт контент» этого достаточно; для REST обычно смотрят JSON, а не HTML.

Заголовки вместе с телом

Флаг -i добавляет заголовки ответа перед телом — удобно, когда нужно увидеть Content-Type, Set-Cookie или код статуса в первой строке:

curl -i -s "https://httpbin.org/get?check=1"
HTTP/2 200
date: Sat, 31 May 2025 12:00:00 GMT
content-type: application/json
content-length: 429

{
"args": {
"check": "1"
},
"headers": {
"Accept": "*/*",
"Host": "httpbin.org"
},
"origin": "203.0.113.42",
"url": "https://httpbin.org/get?check=1"
}

Первая строка HTTP/2 200 — статус. Дальше — заголовки, пустая строка, затем JSON. httpbin эхо-сервис: он возвращает то, что получил (ваш IP в origin, query-параметры в args) — удобно для учебных проверок без своего бэкенда.

Только заголовки, без тела — отдельная команда curl -I (см. ниже в разделе «Заголовки ответа без тела»).


Скачивание файлов

ЗадачаКомандаРезультат
Сохранить под исходным именем из URLcurl -O https://example.com/archive.zipфайл archive.zip в текущем каталоге
Задать имя и путьcurl -o report.pdf https://example.com/report.pdfфайл report.pdf там, куда укажете
Продолжить прерванную загрузкуcurl -C - -O https://example.com/big.isoдокачка с места обрыва

Флаг -O (заглавная O) берёт имя из последнего сегмента URL. Флаг -o (строчная) задаёт путь явно — можно положить файл в подкаталог: -o ./downloads/tool.zip.

Где окажется файл

curl не открывает «Загрузки» автоматически. Файл попадает в каталог, который показывает pwd — откуда вы запустили команду.

pwd
# /home/student/lab

curl -O https://releases.example.com/sample.tar.gz

Во время загрузки в терминале (stderr) обычно видно progress-bar:

% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 2048 100 2048 0 0 8192 0 --:--:-- --:--:-- --:--:-- 8192

После этого приглашение $ снова доступно — загрузка завершена. Проверка:

ls -lh sample.tar.gz
# -rw-r--r-- 1 student student 2.0K May 31 15:30 sample.tar.gz

Файл лежит в /home/student/lab/sample.tar.gz. Открыть каталог в проводнике или перейти: cd /home/student/lab. В Windows CMD/PowerShell перед скачиванием имеет смысл явно перейти в нужную папку: cd $env:USERPROFILE\Downloads, затем curl.exe -O URL.

Явное имя и тихая загрузка

mkdir -p ./downloads
curl -fsSL -o ./downloads/report.pdf "https://example.com/files/report.pdf"
ls -lh ./downloads/report.pdf
ФлагЗачем в этой цепочке
-fОстановиться с ошибкой при HTTP 404/500 — не сохранять HTML-страницу «Not Found» как «pdf»
-sБез progress-bar (удобно в скриптах)
-SВместе с -s — всё равно показать текст ошибки
-LСледовать редиректам, если URL перенаправляет на CDN

Если ls показывает файл размером несколько килобайт с HTML внутри — часто это страница ошибки; проверьте URL и добавьте -f или -w "%{http_code}".


POST с JSON

curl -X POST \
-H "Content-Type: application/json" \
-d '{"title":"hello","body":"text","userId":1}' \
https://jsonplaceholder.typicode.com/posts

Пример в терминале — что вернёт сервер

У jsonplaceholder POST не сохраняет данные навсегда, но ответ выглядит как у настоящего API:

curl -s -X POST \
-H "Content-Type: application/json" \
-d '{"title":"hello","body":"text","userId":1}' \
https://jsonplaceholder.typicode.com/posts
{
"title": "hello",
"body": "text",
"userId": 1,
"id": 101
}

Что это значит: сервер принял JSON, «создал» ресурс и вернул его с новым id: 101. В реальном API по этому id потом делают GET /posts/101 или смотрят заголовок Location в ответе.

Проверить HTTP-код (jsonplaceholder отдаёт 201 Created):

curl -s -o /dev/null -w "HTTP %{http_code}\n" -X POST \
-H "Content-Type: application/json" \
-d '{"title":"hello","body":"text","userId":1}' \
https://jsonplaceholder.typicode.com/posts
HTTP 201

Что делать с ответом:

ЦельКоманда
Сохранить ответ серверадобавить -o created.json
Вытащить только id... | jq -r .id101
Увидеть заголовки (Location, Set-Cookie)добавить -i перед URL
Отладить «400 Bad Request»-i и проверить, что Content-Type: application/json и тело — валидный JSON

Эхо POST без своего сервера — httpbin:

curl -s -X POST -H "Content-Type: application/json" \
-d '{"title":"hello"}' https://httpbin.org/post

В JSON в поле json будет ровно то, что вы отправили — удобно убедиться, что тело дошло.

Windows CMD (одна строка, экранирование кавычек):

curl.exe -X POST "https://jsonplaceholder.typicode.com/posts" ^
-H "Content-Type: application/json" ^
-d "{\"title\":\"hello\",\"body\":\"text\",\"userId\":1}"

Данные из файла вместо строки в -d:

curl -X POST -H "Content-Type: application/json" \
-d @payload.json \
https://api.example.com/v1/items

Символ @ перед путём означает «прочитать тело из файла». Ответ по-прежнему печатается в терминал, если не указать -o.


Заголовки ответа без тела

Только заголовки (HEAD-запрос):

curl -I https://example.com

Пример вывода — тела нет, только метаданные ответа:

HTTP/2 200
accept-ranges: bytes
content-type: text/html; charset=UTF-8
content-length: 1256
last-modified: Thu, 17 Oct 2024 07:18:26 GMT

По content-type видно, что при обычном GET без -I придёт HTML. По content-length — размер в байтах. Код 200 в первой строке — ресурс найден; 404 или 500 — ошибка на стороне сервера (curl без -f всё равно завершится с exit code 0).

Заголовки и тело (удобно при отладке):

curl -i https://httpbin.org/get

Подробный разбор формата -i — в разделе GET выше.


HTTP-методы и REST

МетодНазначениеПример curl
GETЧтение ресурсаcurl URL
POSTСоздание, действиеcurl -X POST -d '...' URL
PUTПолная заменаcurl -X PUT -d @file.json URL
PATCHЧастичное обновлениеcurl -X PATCH -d '{"name":"x"}' URL
DELETEУдалениеcurl -X DELETE URL
HEADТолько заголовкиcurl -I URL

REST и контракты API — основы интеграционного взаимодействия.


Полезные флаги

Навигация и отладка

ФлагДействие
-LСледовать редиректам (301, 302, …)
-vПодробный вывод (TLS, заголовки запроса/ответа)
-s«Тихий» режим — без progress-bar (удобно в скриптах)
-SВместе с -s — показывать ошибки
-w "\nHTTP %{http_code}\n"После тела — форматированная строка (код, время)
--trace-ascii -Полный дамп обмена (глубокая отладка)

Пример с редиректом и кодом ответа:

curl -sL -w "\nHTTP %{http_code} time %{time_total}s\n" -o /dev/null https://google.com

Аутентификация и заголовки

ФлагДействие
-H "Name: value"Произвольный заголовок запроса
-u user:passwordHTTP Basic Auth
-u userBasic Auth — пароль запросит интерактивно
-H "Authorization: Bearer TOKEN"Bearer-токен (JWT, API key)
curl -u admin:secret https://httpbin.org/basic-auth/admin/secret
curl -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
https://api.example.com/me

Тема паролей и токенов — аутентификация и авторизация.


Формы и загрузка файлов

application/x-www-form-urlencoded (как HTML-форма):

curl -X POST -d "login=user&password=pass" https://httpbin.org/post

multipart/form-data (файл + поля):

curl -X POST -F "file=@./photo.jpg" -F "description=avatar" \
https://httpbin.org/post

TLS, прокси, таймауты

ФлагДействие
-k / --insecureНе проверять сертификат сервера (только для локальной отладки)
-x http://proxy:8080HTTP-прокси
--connect-timeout 5Лимит на установку соединения (секунды)
-m 30Общий лимит времени операции
--retry 3Повтор при временных сбоях
--failЗавершить с ненулевым кодом при HTTP 4xx/5xx (удобно в CI)
--fail-with-bodyКак --fail, но тело ошибки всё равно выводится

Не отключайте проверку TLS в проде
Флаг -k обходит проверку сертификата и открывает путь для MITM-атаки. В учебной среде с самоподписанным cert на localhost — допустимо; на боевых URL — нет.


Разбор ответа в скрипте

Только HTTP-код (для health-check):

code=$(curl -s -o /dev/null -w "%{http_code}" https://api.example.com/health)
echo "status: $code"

JSON через jq:

curl -s https://httpbin.org/ip | jq -r .origin

Несколько заголовков в переменные — через -D - (заголовки в stdout) или -o + -D headers.txt.

Пример проверки в Bash:

#!/usr/bin/env bash
set -euo pipefail
URL="${1:-https://httpbin.org/status/200}"
curl -sf "$URL" > /dev/null && echo "OK: $URL"

Флаг -f (--fail) превращает HTTP 4xx/5xx в ошибку shell — скрипт остановится благодаря set -e.


Cookies и сессии

Сохранить cookies после логина:

curl -c cookies.txt -X POST -d "user=u&pass=p" https://example.com/login
curl -b cookies.txt https://example.com/dashboard
ФлагДействие
-c fileЗаписать cookies в файл
-b fileОтправить cookies из файла
-b "name=value"Одна cookie в строке

Файл конфигурации

Повторяющиеся параметры можно вынести в ~/.curlrc (Linux/macOS) или _curlrc в каталоге %USERPROFILE% (Windows).

Пример ~/.curlrc:

# всегда следовать редиректам, таймаут 30 с
location
max-time = 30
user-agent = "MyApp/1.0"

Отключить чтение конфига для одного вызова: curl -q URL.


curl и wget

Обе утилиты качают файлы по HTTP, но акценты разные.

Критерийcurlwget
Основная силаЛюбые HTTP-методы, API, заголовкиРекурсивное зеркалирование сайтов
POST / PUT / PATCHдаограниченно
Типичный сценарийcurl -X POST …, health-checkwget -r для офлайн-копии
В справочнике Linux101 — curl и wgetтот же раздел

Для REST и отладки API выбирайте curl. Для массовой загрузки статики с сайта — чаще wget.


Другие утилиты для HTTP и загрузки

Кроме curl и wget в реальной работе часто используют инструменты со своими сильными сторонами.

Про get — чтобы не запутаться в названии

В Linux и macOS нет стандартной отдельной утилиты get для HTTP-запросов. Обычно под словом «get» имеют в виду одно из трёх:

  • HTTP-метод GET в curl, HTTPie, xh и других клиентах;
  • команду wget (её иногда сокращают в разговоре до «get»);
  • пакетный менеджер apt-get (это установка пакетов, не HTTP-клиент для API).

Рабочее правило: когда речь о запросах к API, пишите точное имя инструмента — curl, http, xh, wget2.


Быстрое сравнение инструментов

ИнструментКогда братьСильная сторонаОграничение
wget2Массовые загрузки, зеркалирование, высокая скоростьСовременная многопоточная загрузка, HTTP/2API-отладка хуже, чем у curl/HTTPie
lftpFTP/SFTP/FTPS, синхронизация каталоговНадёжные зеркала, докачка, автоматизация transfer-задачДля REST API используется редко
aria2c (aria2)Большие файлы, нестабильный каналМногопоточная скачка, металинки, торренты, RPCНе основной выбор для сложных HTTP API
httrackОфлайн-копия сайтаРекурсивное зеркалирование HTML/CSS/ресурсовПочти не подходит для API и SPA с активным JS
HTTPie (http)Человеко-читаемое тестирование RESTУдобный синтаксис, красивый вывод JSON, сессииМеньше низкоуровневых опций, чем в curl
xhБыстрый CLI-клиент в стиле HTTPieВысокая скорость, удобный UX, совместимый стильЭкосистема и распространённость меньше, чем у curl

wget2

wget2 — наследник wget с современным сетевым стеком и лучшей производительностью на больших загрузках.

wget2 https://example.com/big.iso
wget2 --continue --output-file=download.log https://example.com/big.iso

Когда полезен:

  • выгружать большие артефакты сборки;
  • качать много файлов по списку;
  • зеркалировать статику сайта.

lftp

lftp ориентирован на FTP/SFTP и зеркалирование директорий.

lftp -u user,pass sftp://example.com
lftp -e "mirror --reverse ./local-dir /remote-dir; quit" -u user,pass sftp://example.com

Когда полезен:

  • синхронизировать каталоги на удалённый хост;
  • автоматически докачивать после обрыва;
  • делать регулярные выгрузки по SFTP.

aria2 (aria2c)

aria2c качает файл в несколько потоков и хорошо переживает плохой канал.

aria2c -x 16 -s 16 https://example.com/large-file.zip
aria2c --continue=true --max-tries=5 https://example.com/large-file.zip

Когда полезен:

  • крупные ISO/backup-архивы;
  • параллельные скачивания из нескольких источников;
  • автоматические загрузки в CI-агентах.

httrack

httrack создаёт офлайн-копию сайта с рекурсивной загрузкой страниц и ресурсов.

httrack "https://docs.example.com" -O "./mirror-docs" "+*.example.com/*"

Когда полезен:

  • локальный архив документации;
  • учебный офлайн-стенд;
  • анализ структуры статического сайта.

Ограничение: современные SPA с динамической подгрузкой JavaScript часто зеркалируются неполно.


HTTPie (http)

HTTPie упрощает ручную работу с REST за счёт «читаемого» синтаксиса.

http GET https://httpbin.org/get
http POST https://httpbin.org/post name=alice age:=30
http GET https://api.example.com/me Authorization:"Bearer $TOKEN"

Когда полезен:

  • быстро проверять эндпоинты руками;
  • демонстрировать запросы команде без длинного набора флагов;
  • видеть форматированный JSON без jq.

xh

xh — быстрый клиент в стиле HTTPie, написанный на Rust.

xh GET https://httpbin.org/get
xh POST https://httpbin.org/post title=hello count:=1

Когда полезен:

  • нужен короткий синтаксис как у HTTPie;
  • важна скорость запуска и компактный бинарник;
  • хочется современный UX без потери CLI-подхода.

Как выбрать инструмент под задачу

ЗадачаРекомендуемый инструмент
Тест REST API, заголовки, auth, сложные сценарииcurl
Читаемые ручные запросы в командной строкеHTTPie или xh
Большая загрузка файлов, многопоточностьaria2c или wget2
Офлайн-зеркало сайтаhttrack
SFTP/FTP и зеркалирование каталоговlftp

Для базовой профессиональной практики достаточно уверенно владеть двумя инструментами:

  • curl — универсальный стандарт для API и скриптов;
  • один «специализированный» клиент под вашу задачу (aria2c, lftp, HTTPie или xh).

Типовые сценарии

Health-check в cron или systemd timer

curl -sf --connect-timeout 3 https://myservice.example.com/health || logger "myservice down"

Проверка, что nginx проксирует на бэкенд

curl -sI -H "Host: api.internal" http://127.0.0.1:8080/v1/ping

Отправка webhook (Slack, Telegram, GitHub)

curl -X POST -H "Content-Type: application/json" \
-d '{"text":"Deploy finished"}' \
"$WEBHOOK_URL"

Скачать и распаковать (осторожно с источником)

curl -fsSL https://releases.example.com/tool-1.2.tar.gz -o tool.tar.gz
tar xzf tool.tar.gz

curl | bash
Цепочка curl https://unknown/install.sh | bash выполняет чужой код без просмотра. Риски и стоп-лист — Опасные скрипты. Сначала сохраните скрипт (-o), прочитайте, потом запускайте.


Экспорт из Postman и обратно

В Postman у каждого запроса есть кнопка Code → cURL — готовая строка для терминала или CI. Вставьте её в .sh, Dockerfile RUN или job GitHub Actions.

Обратный импорт: Postman → Import → Raw text — вставьте команду curl, получите коллекцию. Подробнее — Postman и curl.


Коды выхода и ошибки

СитуацияПоведение
Сеть недоступна, DNS, timeoutненулевой exit code, сообщение в stderr
HTTP 404/500 без -fexit 0, тело ошибки в stdout
HTTP 404/500 с -fненулевой exit code
Неверный URL или синтаксисcurl пишет подсказку, exit ≠ 0

В CI проверяйте и exit code, и тело ответа: curl -sf … или явная проверка %{http_code} через -w.


Официальная документация curl

РесурсНазначение
Документация curlХаб: руководства, FAQ, протоколы
TutorialПошаговое введение
HTTP scriptingСценарии для веб и REST
Man pageПолный список опций
Options by subject«Когда какой флаг нужен»

При расхождении с учебным текстом приоритет у официальной man page и версии curl --version на вашей машине.


Шпаргалка — частые однострочники

# GET
curl -s URL

# GET + только код
curl -s -o /dev/null -w "%{http_code}" URL

# POST JSON
curl -s -X POST -H "Content-Type: application/json" -d '{"k":"v"}' URL

# Скачать файл
curl -fsSL -o out.bin URL

# Заголовки ответа
curl -sI URL

# Basic Auth + verbose
curl -v -u user:pass URL

# Bearer
curl -s -H "Authorization: Bearer $TOKEN" URL

# Следовать редиректам
curl -sL URL

Контрольный список

Перед тем как вставить curl в скрипт или runbook:

[ ] URL в кавычках, секреты — в переменных окружения, а не в истории shell
[ ] Для POST указан Content-Type
[ ] В CI используется -f / --fail или явная проверка кода ответа
[ ] В PowerShell вызывается curl.exe, если нужен именно curl
[ ] TLS -k только на доверенных учебных стендах
[ ] Чужие install-скрипты не piped в bash без просмотра


Смежные материалы

Раздел «Терминал»оглавление, команды Linux, скрипты Unix, итоги.

Рядом по маршрутуPuTTY и SSH, утилита make.

API и интеграцииPostman и curl для тестирования API, основы интеграционного взаимодействия, практикум REST.

Сетьсеть и интернет, как работают сайты.

Безопасностьопасные скрипты, аутентификация.

WindowsPowerShell, Invoke-RestMethod как альтернатива в нативных скриптах.


См. также

Другие статьи этого же раздела в боковом меню (как на странице "О разделе").