Введение
curl (Client URL) — самый универсальный инструмент для работы с API из командной строки. Он установлен на каждой Linux и macOS системе, доступен на Windows, и работает одинаково везде: от локальной машины до CI/CD-пайплайна.
Разработчики используют curl каждый день: быстро проверить эндпоинт, отладить ошибку, написать smoke-тест, воспроизвести баг из DevTools. В этой статье — всё, что нужно знать для работы с REST API через curl: от базовых GET-запросов до продвинутых сценариев с аутентификацией, файлами и замером производительности.
📋 Содержание
Основы curl
# Установка (обычно уже предустановлен)
# macOS: встроен
# Linux: sudo apt install curl / sudo yum install curl
# Windows: winget install curl (или встроен в Windows 10+)
# Проверить версию
curl --version
# curl 8.x.x (дата) libcurl/8.x.x ...
# Простейший запрос — GET по умолчанию
curl https://api.example.com/users
# Вывести красиво через jq
curl -s https://api.example.com/users | jq .
curl по умолчанию
Без флагов curl делает GET запрос, выводит тело ответа в stdout и скрывает прогресс-бар. Это самый частый сценарий использования.
Все HTTP-методы
curl поддерживает все HTTP-методы:
GET — получение данных
# Простой GET
curl https://api.example.com/users
# GET с query-параметрами
curl "https://api.example.com/users?page=2&limit=10"
# GET с query-параметрами (URL-кодирование)
curl -G https://api.example.com/search \
--data-urlencode "q=hello world" \
--data-urlencode "lang=ru"
# → GET /search?q=hello%20world&lang=ru
POST — создание ресурса
# POST с JSON-телом
curl -X POST https://api.example.com/users \
-H "Content-Type: application/json" \
-d '{"name": "Иван", "email": "ivan@test.ru"}'
# -d автоматически устанавливает метод POST, поэтому -X POST можно опустить:
curl https://api.example.com/users \
-H "Content-Type: application/json" \
-d '{"name": "Иван", "email": "ivan@test.ru"}'
# POST из файла
curl https://api.example.com/users \
-H "Content-Type: application/json" \
-d @user.json
# POST form data (application/x-www-form-urlencoded)
curl https://api.example.com/login \
-d "email=ivan@test.ru" \
-d "password=secret123"
PUT — полная замена ресурса
# PUT — замена всего ресурса
curl -X PUT https://api.example.com/users/42 \
-H "Content-Type: application/json" \
-d '{"name": "Иван Петров", "email": "ivan@test.ru", "role": "admin"}'
PATCH — частичное обновление
# PATCH — обновить только указанные поля
curl -X PATCH https://api.example.com/users/42 \
-H "Content-Type: application/json" \
-d '{"role": "admin"}'
DELETE — удаление
# DELETE
curl -X DELETE https://api.example.com/users/42
# DELETE с телом (некоторые API требуют)
curl -X DELETE https://api.example.com/users/42 \
-H "Content-Type: application/json" \
-d '{"reason": "user request"}'
Заголовки
# Один заголовок
curl -H "Accept: application/json" https://api.example.com/users
# Несколько заголовков
curl https://api.example.com/users \
-H "Accept: application/json" \
-H "Authorization: Bearer TOKEN" \
-H "X-Request-Id: req_abc123" \
-H "Accept-Language: ru"
# Посмотреть заголовки ОТВЕТА
curl -I https://api.example.com/users
# HTTP/2 200
# content-type: application/json
# x-ratelimit-remaining: 98
# Включить заголовки ответа в вывод
curl -i https://api.example.com/users
⚠️ -I vs -i vs -v
-I(HEAD) — отправляет HEAD-запрос, показывает только заголовки ответа-i(include) — отправляет GET, показывает заголовки + тело ответа-v(verbose) — показывает всё: заголовки запроса, ответа, TLS, тело
Работа с JSON
# POST JSON
curl https://api.example.com/users \
-H "Content-Type: application/json" \
-d '{
"name": "Иван",
"email": "ivan@test.ru",
"tags": ["admin", "developer"]
}'
# JSON из файла
echo '{"name": "Иван", "email": "ivan@test.ru"}' > user.json
curl https://api.example.com/users \
-H "Content-Type: application/json" \
-d @user.json
# Вывод с форматированием через jq
curl -s https://api.example.com/users | jq .
# Извлечь конкретное поле
curl -s https://api.example.com/users/42 | jq '.email'
# "ivan@test.ru"
# Фильтрация массива
curl -s https://api.example.com/users | jq '.[].name'
# Компактный вывод
curl -s https://api.example.com/users | jq -c '.[]'
jq — незаменимый спутник curl
Установите jq (apt install jq / brew install jq). Это процессор JSON для командной строки: форматирование, фильтрация, извлечение полей. curl + jq = мощная связка.
Аутентификация
Bearer Token (OAuth 2.0)
# Через заголовок
curl https://api.example.com/me \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
# Из переменной окружения (безопаснее)
export API_TOKEN="eyJhbGciOiJIUzI1NiIs..."
curl https://api.example.com/me \
-H "Authorization: Bearer $API_TOKEN"
Basic Auth
# Через -u (user:password)
curl -u admin:secret123 https://api.example.com/admin
# Без пароля — curl запросит интерактивно
curl -u admin https://api.example.com/admin
# Через заголовок (base64)
curl https://api.example.com/admin \
-H "Authorization: Basic $(echo -n 'admin:secret123' | base64)"
API Key
# В заголовке
curl https://api.example.com/data \
-H "X-API-Key: your_api_key_here"
# В query-параметре
curl "https://api.example.com/data?api_key=your_api_key_here"
Не храните токены в истории команд!
Используйте переменные окружения или файл конфигурации:
# Чтение токена из файла
curl https://api.example.com/me \
-H "Authorization: Bearer $(cat ~/.api_token)"
# Или через .netrc
echo "machine api.example.com login token password YOUR_TOKEN" >> ~/.netrc
curl --netrc https://api.example.com/me
Загрузка файлов
# Upload файла (multipart/form-data)
curl -X POST https://api.example.com/upload \
-F "file=@photo.jpg" \
-F "description=Фотография профиля"
# Несколько файлов
curl -X POST https://api.example.com/upload \
-F "files[]=@photo1.jpg" \
-F "files[]=@photo2.jpg"
# Указать Content-Type файла
curl -X POST https://api.example.com/upload \
-F "file=@data.csv;type=text/csv"
# Скачать файл
curl -o report.pdf https://api.example.com/reports/2026-02.pdf
# Скачать с оригинальным именем
curl -O https://api.example.com/files/export.xlsx
# Скачать с прогресс-баром
curl -# -o big-file.zip https://api.example.com/files/archive.zip
Отладка и verbose
# Verbose — показать всё: TLS, заголовки запроса/ответа, тело
curl -v https://api.example.com/users
# Пример вывода -v:
# * Connected to api.example.com (93.184.216.34) port 443
# * SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
# > GET /users HTTP/2 ← заголовки ЗАПРОСА (>)
# > Host: api.example.com
# > User-Agent: curl/8.4.0
# > Accept: */*
# >
# < HTTP/2 200 ← заголовки ОТВЕТА (<)
# < content-type: application/json
# < x-request-id: req_abc123
# <
# [{"id":1,"name":"Иван"}] ← тело ответа
# Записать отладку в файл (не засорять терминал)
curl -v https://api.example.com/users 2>debug.log
# Только HTTP-статус код
curl -s -o /dev/null -w "%{http_code}" https://api.example.com/health
# 200
# Trace — максимально подробный вывод (включая hex-дамп)
curl --trace trace.log https://api.example.com/users
Расшифровка вывода curl -v
*— служебная информация curl (TLS, DNS, подключение)>— заголовки вашего запроса<— заголовки ответа сервера- Без символа — тело ответа
Замер времени
curl умеет детально измерять все этапы HTTP-запроса:
# Полная разбивка по этапам
curl -o /dev/null -s -w "\
DNS Lookup: %{time_namelookup}s\n\
TCP Connect: %{time_connect}s\n\
TLS Handshake: %{time_appconnect}s\n\
Start Transfer:%{time_starttransfer}s\n\
Total Time: %{time_total}s\n\
HTTP Code: %{http_code}\n\
Download Size: %{size_download} bytes\n\
" https://api.example.com/users
# Пример вывода:
# DNS Lookup: 0.012s
# TCP Connect: 0.045s
# TLS Handshake: 0.123s
# Start Transfer:0.234s ← Time to First Byte (TTFB)
# Total Time: 0.256s
# HTTP Code: 200
# Download Size: 4523 bytes
# Сохранить формат в файл для переиспользования
cat > curl-timing.txt << 'EOF'
DNS: %{time_namelookup}s
Connect: %{time_connect}s
TLS: %{time_appconnect}s
TTFB: %{time_starttransfer}s
Total: %{time_total}s
Code: %{http_code}
Size: %{size_download}B
EOF
# Использование
curl -o /dev/null -s -w "@curl-timing.txt" https://api.example.com/users
| Переменная | Что измеряет |
|---|---|
time_namelookup | DNS-резолвинг |
time_connect | TCP-подключение |
time_appconnect | TLS-handshake |
time_pretransfer | Готовность к передаче |
time_starttransfer | TTFB — время до первого байта |
time_total | Общее время запроса |
http_code | HTTP-статус код |
size_download | Размер ответа (байты) |
Продвинутые приёмы
Таймауты
# Таймаут подключения (секунды)
curl --connect-timeout 5 https://api.example.com/users
# Максимальное время выполнения запроса
curl --max-time 30 https://api.example.com/slow-report
# Оба вместе
curl --connect-timeout 5 --max-time 30 https://api.example.com/users
Редиректы
# Следовать редиректам (301, 302, 307)
curl -L https://api.example.com/old-endpoint
# Ограничить количество редиректов
curl -L --max-redirs 3 https://api.example.com/old-endpoint
SSL / TLS
# Игнорировать SSL-ошибки (для тестирования!)
curl -k https://localhost:8443/api
# Указать конкретный CA-сертификат
curl --cacert /path/to/ca.crt https://internal-api.company.com
# Клиентский сертификат (mutual TLS)
curl --cert client.crt --key client.key https://api.example.com
# Проверить SSL-сертификат
curl -vI https://api.example.com 2>&1 | grep -E "subject:|expire"
Cookies
# Отправить cookie
curl -b "session=abc123" https://api.example.com/me
# Сохранить cookies в файл
curl -c cookies.txt https://api.example.com/login \
-d "email=admin@test.ru&password=secret"
# Использовать сохранённые cookies
curl -b cookies.txt https://api.example.com/dashboard
Прокси
# HTTP-прокси
curl -x http://proxy.company.com:8080 https://api.example.com/users
# SOCKS5-прокси
curl --socks5 localhost:1080 https://api.example.com/users
# Исключить хосты из прокси
curl --noproxy "localhost,*.company.com" -x http://proxy:8080 https://api.example.com
Retry
# Повторить при ошибке (таймаут, 5xx)
curl --retry 3 https://api.example.com/unstable-endpoint
# Повторить с задержкой
curl --retry 3 --retry-delay 2 https://api.example.com/unstable
# Повторить при конкретных HTTP-кодах
curl --retry 3 --retry-all-errors https://api.example.com/users
Шпаргалка по флагам
curl в скриптах
Health Check в CI/CD
#!/bin/bash
# health-check.sh — проверка здоровья API после деплоя
API_URL="${1:-https://api.example.com}"
MAX_RETRIES=10
RETRY_DELAY=3
echo "Checking $API_URL/health..."
for i in $(seq 1 $MAX_RETRIES); do
STATUS=$(curl -s -o /dev/null -w "%{http_code}" \
--connect-timeout 5 --max-time 10 \
"$API_URL/health")
if [ "$STATUS" = "200" ]; then
echo "✓ Health check passed (attempt $i)"
exit 0
fi
echo " Attempt $i/$MAX_RETRIES: HTTP $STATUS"
sleep $RETRY_DELAY
done
echo "✗ Health check failed after $MAX_RETRIES attempts"
exit 1
CRUD-тестирование
#!/bin/bash
# test-crud.sh — быстрый CRUD-тест API
BASE_URL="https://api.example.com/api"
TOKEN="Bearer $API_TOKEN"
echo "=== CREATE ==="
CREATE_RESPONSE=$(curl -s -w "\n%{http_code}" \
-H "Content-Type: application/json" \
-H "Authorization: $TOKEN" \
-d '{"name": "Test User", "email": "test@test.ru"}' \
"$BASE_URL/users")
HTTP_CODE=$(echo "$CREATE_RESPONSE" | tail -1)
BODY=$(echo "$CREATE_RESPONSE" | sed '$d')
USER_ID=$(echo "$BODY" | jq -r '.id')
echo "Status: $HTTP_CODE, User ID: $USER_ID"
[ "$HTTP_CODE" = "201" ] || { echo "FAIL: expected 201"; exit 1; }
echo "=== READ ==="
READ_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
-H "Authorization: $TOKEN" \
"$BASE_URL/users/$USER_ID")
echo "Status: $READ_CODE"
[ "$READ_CODE" = "200" ] || { echo "FAIL: expected 200"; exit 1; }
echo "=== UPDATE ==="
UPDATE_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
-X PATCH \
-H "Content-Type: application/json" \
-H "Authorization: $TOKEN" \
-d '{"name": "Updated User"}' \
"$BASE_URL/users/$USER_ID")
echo "Status: $UPDATE_CODE"
[ "$UPDATE_CODE" = "200" ] || { echo "FAIL: expected 200"; exit 1; }
echo "=== DELETE ==="
DELETE_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
-X DELETE \
-H "Authorization: $TOKEN" \
"$BASE_URL/users/$USER_ID")
echo "Status: $DELETE_CODE"
[ "$DELETE_CODE" = "204" ] || { echo "FAIL: expected 204"; exit 1; }
echo "=== ALL TESTS PASSED ==="
Мониторинг времени ответа
#!/bin/bash
# monitor-latency.sh — мониторинг задержки API
URL="https://api.example.com/health"
INTERVAL=10
THRESHOLD=1.0
while true; do
TOTAL=$(curl -o /dev/null -s -w "%{time_total}" "$URL")
CODE=$(curl -o /dev/null -s -w "%{http_code}" "$URL")
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
if (( $(echo "$TOTAL > $THRESHOLD" | bc -l) )); then
echo "⚠ $TIMESTAMP | $CODE | ${TOTAL}s (SLOW!)"
else
echo "✓ $TIMESTAMP | $CODE | ${TOTAL}s"
fi
sleep $INTERVAL
done
DevTools → curl
Самый быстрый способ воспроизвести запрос из браузера:
- Откройте DevTools → Network
- Найдите нужный запрос
- ПКМ → Copy → Copy as cURL
- Вставьте в терминал
Это копирует все заголовки, cookies, тело запроса. Идеально для отладки — вы получаете точную копию запроса из браузера.
FAQ
❓ Как отправить POST-запрос с JSON через curl?
Ответ: curl -X POST URL -H "Content-Type: application/json" -d '{"key": "value"}'. Флаг -d автоматически устанавливает метод POST, поэтому -X POST можно опустить. Для данных из файла: -d @file.json.
❓ Как передать Bearer-токен в curl?
Ответ: Через заголовок: -H "Authorization: Bearer TOKEN". Для безопасности используйте переменные окружения: -H "Authorization: Bearer $API_TOKEN". Basic auth: -u user:password.
❓ Как увидеть заголовки ответа в curl?
Ответ: -v — все заголовки запроса и ответа. -i — заголовки ответа + тело. -I — только заголовки (HEAD-запрос). Для отладки используйте -v.
❓ Как замерить время ответа API через curl?
Ответ: Используйте -w (write-out): curl -o /dev/null -s -w "Total: %{time_total}s\nTTFB: %{time_starttransfer}s\n" URL. Это покажет общее время и TTFB. Доступны переменные для DNS, TCP, TLS.
Заключение
📝 Ключевые выводы
- curl — универсальный инструмент для работы с API. Установлен везде, работает одинаково.
- Основные флаги:
-X(метод),-H(заголовки),-d(тело),-v(отладка),-s(silent). - curl + jq — мощная связка для работы с JSON-ответами API.
- -w (write-out) — замер DNS, TCP, TLS, TTFB. Незаменимо для мониторинга.
- DevTools → Copy as cURL — мгновенное воспроизведение запроса из браузера.
- В CI/CD — health-check, smoke-тесты, CRUD-проверки через bash-скрипты с curl.
curl — один из тех инструментов, которые используешь каждый день. Чем лучше вы его знаете, тем быстрее отлаживаете API, тем увереннее пишете скрипты. Сохраните эту шпаргалку — она пригодится.
🎯 Тестируйте API с LightBox
Нужен API для практики curl? LightBox API создаёт моковые эндпоинты за минуту — отправляйте любые запросы и получайте настроенные ответы.
- ✓ Настраиваемые HTTP-статусы и JSON-ответы
- ✓ Все HTTP-методы
- ✓ Логирование входящих запросов
- ✓ Swagger документация
- ✓ Бесплатный план для старта
Статья опубликована: 23 февраля 2026
Автор: LightBox API Team