HTTP заголовки это метаданные, которые путешествуют вместе с каждым запросом и ответом: они сообщают серверу, какой клиент обращается, какой тип контента содержит тело, какие учётные данные проверить и какой язык или формат вы ожидаете в ответ. Когда вы хотите отправить HTTP заголовки с помощью cURL, вся работа сводится к одному флагу, но именно детали вокруг него (несколько заголовков, переопределение значений по умолчанию, удаление одного и чтение ответа) это то, где большинство людей застревает.

Это руководство проходит через практическую механику с точки зрения работающего инженера. Вы изучите синтаксис -H / --header, как отправить один заголовок или много, заголовки, которые важнее всего в реальной работе (User-Agent, Accept, Authorization, Cookie и им подобные), как переопределить или убрать заголовок по умолчанию и как осмотреть то, что сервер присылает в ответ. В конце мы свяжем это со скрапингом: реалистичные заголовки делают запрос похожим на браузер, но это лишь половина истории, поэтому мы покажем, как маршрутизировать cURL через резидентный прокси, когда одних заголовков недостаточно.

Флаг -H: базовый синтаксис

cURL отправляет пользовательский заголовок с флагом -H (или его длинной формой --header), за которым следует имя заголовка, двоеточие и значение, всё обёрнутое в кавычки, чтобы оболочка воспринимала это как один аргумент.

bash
curl -H "Header-Name: value" https://example.com

Это весь паттерн. Кавычки важны: значение заголовка часто содержит пробелы, и без кавычек оболочка разбила бы значение на отдельные аргументы, и cURL отклонил бы его. Имя заголовка нечувствительно к регистру согласно спецификации HTTP, но хорошая практика писать его в канонической форме (User-Agent, а не user-agent), чтобы ваши команды читались чётко и совпадали с тем, что логирует сервер.

Если вы предпочитаете подробную длинную форму, --header ведёт себя идентично. Используйте ту, которая лучше читается в скриптах; большинство людей берётся за -H в командной строке и пишет полностью в закоммиченном коде.

Отправка одного заголовка

Самый распространённый одиночный заголовок это User-Agent. cURL отправляет свой собственный User-Agent по умолчанию (что-то вроде curl/8.4.0), что является мгновенным признаком для любого сервера, что вы не браузер. Переопределение это один флаг.

bash
curl -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" https://example.com

Теперь сервер видит строку текущего Chrome вместо идентификатора cURL. Тот же паттерн одного заголовка охватывает любое другое поле. Чтобы запросить JSON от API, а не то, что сервер ставит по умолчанию, задайте Accept:

bash
curl -H "Accept: application/json" https://api.example.com/data

Отправка нескольких заголовков

Реальные запросы редко несут лишь один заголовок. Чтобы отправить несколько, повторите -H по одному разу на заголовок. Порядок сохраняется, и cURL отправляет каждую строку ровно так, как вы её пишете.

bash
curl -H "Accept: application/json" \
     -H "Accept-Language: en-US,en;q=0.9" \
     -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
     https://api.example.com/data

Обратные слеши позволяют разбить команду по строкам для читаемости; на одной строке это работает так же. Нет практического ограничения на то, сколько флагов -H вы можете нагромоздить, поэтому запрос, имитирующий рукопожатие браузера, может нести дюжину заголовков без какой-либо особой обработки.

Заголовки, которые важнее всего

Горстка заголовков выполняет основную работу в работе с API и скрапинге. Вот для чего нужен каждый из них и как его задать.

User-Agent

Идентифицирует клиента. Задайте реальную, актуальную строку браузера, чтобы сервер обращался с запросом как с обычным трафиком. Устаревшие или явно синтетические User-Agent это распространённый триггер блокировки, поэтому держите свой свежим.

Accept и Accept-Language

Сообщают серверу, какие типы контента и языки вы можете обработать. Браузер всегда отправляет их; голый запрос cURL обычно нет, что само по себе является отпечатком. Отправка реалистичных значений закрывает этот разрыв.

bash
curl -H "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" \
     -H "Accept-Language: en-US,en;q=0.9" \
     https://example.com

Referer

Говорит, какая страница ссылалась на ту, которую вы запрашиваете. Многие сайты ожидают Referer того же источника при внутренней навигации и воспринимают его отсутствие как подозрительное. Установка его на собственный домен сайта (или страницу, с которой вы пришли бы) делает запрос более правдоподобным.

bash
curl -H "Referer: https://example.com/" https://example.com/products

Content-Type

Объявляет формат тела, которое вы отправляете. Он применяется только тогда, когда у вас есть тело запроса, поэтому вы увидите его на POST и PUT, а не на обычном GET. Отправьте JSON, и серверу нужно знать, что его надо разбирать как JSON.

Authorization

Несёт учётные данные. Преобладают две формы. Токен Bearer (OAuth, ключи API) идёт прямо в заголовок:

bash
curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" https://api.example.com/me

Для HTTP Basic auth вы можете построить заголовок вручную, но у cURL есть сокращение. Флаг -u кодирует user:pass в base64 в заголовок Authorization: Basic за вас, что менее подвержено ошибкам, чем кодировать самостоятельно.

bash
# cURL builds the Basic header for you
curl -u myuser:mypassword https://api.example.com/secure

# Equivalent, written out by hand
curl -H "Authorization: Basic bXl1c2VyOm15cGFzc3dvcmQ=" https://api.example.com/secure

Отправляет сохранённое состояние сессии. Вы можете передать cookie встроенно с -H для разового запроса или использовать флаг -b cURL, который также принимает файл cookie, записанный более ранним вызовом -c, чтобы сессия сохранялась между запросами.

bash
curl -H "Cookie: session_id=abc123; theme=dark" https://example.com/account
Имена заголовков нечувствительны к регистру, значения нет

HTTP трактует имена заголовков нечувствительно к регистру, поэтому User-Agent и user-agent достигают одного и того же поля. Значения, напротив, отправляются дословно. Опечатка в токене или случайный пробел в User-Agent передаются нетронутыми, поэтому, когда запрос ведёт себя странно, проверьте значение байт за байтом, прежде чем винить сервер.

Переопределение против добавления заголовка

cURL отправляет несколько заголовков автоматически: среди них Host, User-Agent и Accept. Когда вы передаёте -H для заголовка, который cURL уже отправляет, ваше значение заменяет значение по умолчанию, а не добавляет вторую копию. Вот почему -H "User-Agent: ..." чисто заменяет строку cURL вместо того, чтобы создавать две строки User-Agent.

Для заголовка, который cURL не отправляет по умолчанию, ваш -H просто добавляет его. Так что мысленная модель проста: если это заголовок по умолчанию, вы его переопределяете, иначе вы его добавляете. В любом случае синтаксис это тот же единственный флаг.

Удаление заголовка по умолчанию

Иногда вы хотите, чтобы заголовок исчез полностью, а не был заменён. Чтобы убрать заголовок по умолчанию, передайте его имя, за которым следует двоеточие и ничего после него. cURL читает пустое значение как сигнал опустить заголовок из запроса.

bash
# Remove the Accept header entirely
curl -H "Accept:" https://example.com

# Override one default and remove another in the same request
curl -H "User-Agent: Mozilla/5.0" -H "Accept:" https://example.com

Обратите внимание на разницу: "Accept: value" задаёт заголовок, "Accept:" без значения удаляет его, а завершающая точка с запятой ("Accept;") отправляет заголовок с пустым значением, что является третьим, более редким случаем. В большинстве случаев вам нужны первые два.

Просмотр заголовков ответа

Отправка заголовков это половина разговора; чтение того, что приходит обратно, это другая половина. cURL даёт вам три варианта в зависимости от того, хотите ли вы также тело.

Используйте -I (или --head), чтобы получить только заголовки ответа с помощью запроса HEAD, без загрузки тела:

bash
curl -I https://example.com

Используйте -i (или --include), чтобы напечатать заголовки, за которыми следует полное тело, что удобно, когда вы хотите и то, и другое сразу:

bash
curl -i https://example.com

Используйте -D (или --dump-header), чтобы записать заголовки ответа в файл, пока тело идёт в stdout. Передайте -D -, чтобы сбросить заголовки в stdout рядом с телом, что полезно, когда вы хотите сохранить их в логе.

bash
# Save response headers to a file, body to stdout
curl -D headers.txt https://example.com

Типичный блок заголовков ответа выглядит так, сообщая вам статус, тип контента и политику кеширования с одного взгляда:

bash
HTTP/2 200
content-type: text/html; charset=UTF-8
cache-control: max-age=3600
server: nginx

Отправка пользовательских заголовков на POST

Заголовки раскрываются на запросах записи. Типичному JSON POST к API нужен как минимум Content-Type, чтобы сервер правильно разобрал тело, и обычно также заголовок Authorization. Флаг -d поставляет тело, и cURL автоматически переключается на POST, когда видит его.

bash
curl -X POST https://api.example.com/items \
     -H "Content-Type: application/json" \
     -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
     -d '{"name": "widget", "qty": 12}'

-X POST технически избыточен, как только вы передаёте -d, но прописывание его явно делает намерение очевидным в скрипте. Если сервер ожидает данные формы вместо JSON, измените Content-Type на application/x-www-form-urlencoded и передайте поля тем же способом.

Если вы строите на основах запросов, наше руководство о том, как отправлять запросы GET с помощью cURL охватывает сторону чтения того же инструментария.

Заголовки и веб-скрапинг: что они могут и чего не могут

Вот где знание заголовков встречается с реальностью. Запрос от установки cURL по умолчанию тривиально отличим от браузера: он отправляет User-Agent curl/x.y.z, опускает Accept-Language, не несёт Referer и не приносит ни одной из подсказок клиента, которые включает настоящий браузер. Серверы даже с базовой защитой ориентируются именно на эти пробелы.

Установка реалистичных заголовков закрывает лёгкие пробелы. Текущий User-Agent Chrome, правдоподобные Accept и Accept-Language и Referer того же источника вместе делают ваш запрос гораздо больше похожим на обычный трафик браузера. Для слабо защищённых страниц одного этого часто достаточно, чтобы перестать отскакивать. Наше руководство о cURL для веб-скрапинга глубже разбирает сборку правдоподобного набора заголовков.

Но у заголовков есть жёсткий потолок. Они описывают запрос; они ничего не говорят о том, откуда он приходит. Системы анти-бот также взвешивают репутацию IP, частоту запросов, отпечатки TLS и поведенческие сигналы. Если вы выпускаете сотню запросов в минуту с одного IP дата-центра, никакой набор заголовков вас не спасёт: сам адрес выдаёт. Реалистичные заголовки сокращают тривиальные блокировки, но сами по себе они не побеждают серьёзную защиту анти-бот или плохую репутацию IP.

Маршрутизация cURL через резидентный прокси

Недостающая половина это IP. Когда вы маршрутизируете cURL через пул ротируемых резидентных адресов, ваши запросы приходят с IP, которые читаются как реальные пользователи, при этом вы сохраняете полный контроль над каждым заголовком. cURL уже общается с прокси нативно через флаг -x (или --proxy), поэтому добавление одного это единственный аргумент поверх заголовков, которые вы уже отправляете.

Smart AI Proxy (также называемый AI Proxy) показывает резидентную ротацию как единый drop-in эндпоинт. Вы направляете на него cURL с помощью -x, аутентифицируетесь своим токеном и отправляете любые заголовки, какие захотите; прокси ротирует выходной IP за кулисами.

bash
curl -x "http://[email protected]:8012" \
     -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" \
     -H "Accept-Language: en-US,en;q=0.9" \
     -k https://example.com

Флаг -x задаёт прокси, флаги -H несут ваши реалистичные заголовки ровно как раньше, и запрос уходит с доверенного резидентного IP. Вы сохраняете полный контроль над заголовками, который даёт вам cURL, и получаете репутацию IP, которую одни заголовки обеспечить не могут. Об общей механике проксирования любого запроса cURL смотрите то, как использовать cURL с прокси.

Crawlbase Smart AI Proxy

Продолжайте писать свои собственные заголовки в cURL и позвольте проблеме IP решиться сама собой. Smart AI Proxy ротирует резидентные адреса за одним эндпоинтом, так что ваши тщательно созданные User-Agent, Accept-Language и Referer уходят с IP, которому серверы доверяют. Направьте на него cURL одним флагом -x и сохраните полный контроль над каждым заголовком.

Если вам нужна разница между прямым прокси, как этот, и обратным видом, сидящим перед сервером, наш разъясняющий материал о прямых против обратных прокси проводит черту чётко.

Отладка проблем с заголовками

Когда запрос ведёт себя неожиданно, самый быстрый инструмент это -v (verbose), который печатает заголовки запроса, которые cURL фактически отправил (с префиксом >), и заголовки ответа, которые он получил (с префиксом <). Он выявляет ровно то, что ушло по проводу, чего обычно достаточно, чтобы заметить отсутствующий заголовок или опечатку.

bash
curl -v -H "Authorization: Bearer YOUR_ACCESS_TOKEN" https://api.example.com/me

На три проблемы приходится большинство багов с заголовками. Первая, отсутствующие кавычки: значение с пробелом разбивается на лишние аргументы оболочки, и cURL выдаёт ошибку, поэтому всегда заключайте в кавычки всю строку name: value. Вторая, непреднамеренное переопределение: передача -H "User-Agent: ..." заменяет значение по умолчанию, а не добавляет к нему, что является тем, чего вы хотите для User-Agent, но сюрпризом, если вы ожидали оба. Третья, случайное удаление: случайный "Header:" без значения убирает заголовок полностью. Запустите с -v, и правда прямо там, в строке запроса.

Итоги

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

  • Один флаг делает всё. -H "Name: value" отправляет любой заголовок; повторяйте -H для стольких заголовков, сколько вам нужно, и порядок сохраняется.
  • Переопределяйте, добавляйте или удаляйте. -H для заголовка по умолчанию заменяет его, -H для нового добавляет его, а "Header:" без значения удаляет его.
  • Читайте также ответ. -I получает только заголовки, -i добавляет их перед телом, а -D сбрасывает их в файл или stdout.
  • Реалистичные заголовки сокращают тривиальные блокировки. Реальный User-Agent, Accept-Language и Referer делают запрос похожим на браузер, но они не побеждают серьёзную защиту анти-бот.
  • Сочетайте заголовки с доверенным IP. Маршрутизируйте cURL через Smart AI Proxy с помощью -x, чтобы запросы уходили с ротируемых резидентных адресов, при этом вы сохраняете полный контроль над заголовками.

Часто задаваемые вопросы

Как мне добавить пользовательский HTTP заголовок в cURL?

Используйте флаг -H (или его длинную форму --header), за которым следует имя заголовка, двоеточие и значение, всё в кавычках: curl -H "Header-Name: value" https://example.com. Кавычки не дают оболочке разбить значение, содержащее пробелы, на отдельные аргументы.

Как мне отправить несколько заголовков в одном запросе cURL?

Повторите флаг -H по одному разу на заголовок. Например, curl -H "Accept: application/json" -H "Authorization: Bearer TOKEN" https://api.example.com отправляет оба. Практического ограничения нет, и cURL сохраняет порядок, в котором вы их пишете.

Как мне задать токен Bearer или Basic auth с помощью cURL?

Для токена Bearer передайте его напрямую: -H "Authorization: Bearer YOUR_TOKEN". Для HTTP Basic auth флаг -u user:pass проще, чем строить заголовок вручную, потому что cURL кодирует учётные данные в base64 и задаёт заголовок Authorization: Basic за вас.

Как мне просмотреть только заголовки ответа с помощью cURL?

Используйте -I (или --head), чтобы получить только заголовки с помощью запроса HEAD и пропустить тело. Если вы хотите заголовки и тело вместе, используйте -i (или --include). Чтобы сохранить заголовки в файл, используйте -D filename.

Как мне убрать заголовок по умолчанию, который отправляет cURL?

Передайте имя заголовка с двоеточием и без значения: curl -H "Accept:" https://example.com удаляет заголовок Accept полностью. Это отличается от "Accept: value", который задаёт его, и "Accept;", который отправляет его с пустым значением.

Остановят ли пользовательские заголовки блокировку моего парсера?

Реалистичные заголовки помогают со слабо защищёнными сайтами, делая ваш запрос похожим на браузер, но они не могут сами по себе победить серьёзные системы анти-бот или плохую репутацию IP. Заголовки описывают запрос, а не то, откуда он приходит. Сочетайте их с ротируемыми резидентными IP, например, маршрутизируя cURL через Smart AI Proxy с флагом -x, чтобы ваш трафик уходил с доверенных адресов, при этом вы сохраняете полный контроль над заголовками.

Начать создавать

Обходите любой сайт в масштабе, без борьбы с инфраструктурой.

Crawlbase берёт на себя прокси, отпечатки и CAPTCHA, чтобы ваша команда выпускала конвейеры данных вместо поддержки обвязки краулинга. 1 000 запросов бесплатно, без карты.

Самообслуживание · Звонок отдела продаж не требуется · Доступны корпоративные объёмы краулинга