curl для работы с API: полное руководство с примерами

← Вернуться к статьям

Введение

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

Работа с 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 умеет детально измерять все этапы 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_namelookupDNS-резолвинг
time_connectTCP-подключение
time_appconnectTLS-handshake
time_pretransferГотовность к передаче
time_starttransferTTFB — время до первого байта
time_totalОбщее время запроса
http_codeHTTP-статус код
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

Шпаргалка по флагам

-X METHOD HTTP-метод: GET, POST, PUT, PATCH, DELETE
-H "Header" Добавить заголовок запроса
-d 'data' Тело запроса (автоматически POST)
-d @file.json Тело запроса из файла
-F "file=@f.jpg" Multipart form upload
-u user:pass Basic-аутентификация
-o file Сохранить ответ в файл
-O Сохранить с оригинальным именем
-s Silent — скрыть прогресс-бар
-S Показать ошибки даже в silent-режиме
-v Verbose — показать всё (отладка)
-i Включить заголовки ответа в вывод
-I Только заголовки (HEAD-запрос)
-L Следовать редиректам
-k Игнорировать SSL-ошибки
-w "format" Вывод метрик (время, код, размер)
--connect-timeout N Таймаут подключения (секунды)
--max-time N Максимальное время запроса
--retry N Повторить при ошибке N раз
-G --data-urlencode URL-кодирование query-параметров

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

Самый быстрый способ воспроизвести запрос из браузера:

  1. Откройте DevTools → Network
  2. Найдите нужный запрос
  3. ПКМ → Copy → Copy as cURL
  4. Вставьте в терминал

Это копирует все заголовки, 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.

Заключение

📝 Ключевые выводы

  1. curl — универсальный инструмент для работы с API. Установлен везде, работает одинаково.
  2. Основные флаги: -X (метод), -H (заголовки), -d (тело), -v (отладка), -s (silent).
  3. curl + jq — мощная связка для работы с JSON-ответами API.
  4. -w (write-out) — замер DNS, TCP, TLS, TTFB. Незаменимо для мониторинга.
  5. DevTools → Copy as cURL — мгновенное воспроизведение запроса из браузера.
  6. В CI/CD — health-check, smoke-тесты, CRUD-проверки через bash-скрипты с curl.

curl — один из тех инструментов, которые используешь каждый день. Чем лучше вы его знаете, тем быстрее отлаживаете API, тем увереннее пишете скрипты. Сохраните эту шпаргалку — она пригодится.

🎯 Тестируйте API с LightBox

Нужен API для практики curl? LightBox API создаёт моковые эндпоинты за минуту — отправляйте любые запросы и получайте настроенные ответы.

Попробовать бесплатно →

Статья опубликована: 23 февраля 2026
Автор: LightBox API Team