Порядок заголовков (Header Order) для CapMonster Cloud: как воспроизвести браузерные заголовки и обойти антибот-защиту

При тестировании систем защиты на собственных сайтах и при работе с сервисом CapMonster Cloud многие разработчики сталкиваются с ситуацией: CAPTCHA успешно решена, токен получен — но сервер всё равно отклоняет запрос.
Когда вы внедряете CAPTCHA или антибот-механизмы, нужно понять, как именно сервер принимает решение — и какие сигналы он использует для выявления автоматизации. Причина часто лежит не в самой CAPTCHA, а в том, как отправляется HTTP-запрос.
Один из ключевых факторов здесь — порядок заголовков (Header Order). В этой статье вы разберётесь, почему порядок имеет значение, как правильно его воспроизвести и как интегрировать это с CapMonster Cloud.
Что такое порядок заголовков
HTTP-запрос состоит не только из URL и тела, но и из набора заголовков:
User-Agent
Accept
Accept-Language
Cookie
...Сервер читает не только содержимое заголовков — он видит и их порядок.
Почему это важно для антибот-защит
Современные системы защиты (Cloudflare, DataDome, Imperva и др.) анализируют:
- TLS fingerprint (JA3/JA3S)
- HTTP/2 SETTINGS fingerprint (Akamai H2 fingerprint)
- User-Agent
- IP-репутацию (ASN, IP дата-центра или резидентский IP)
- JavaScript fingerprint
- порядок заголовков
- поведение клиента
Реальные браузеры (Chrome, Firefox и др.) отправляют заголовки:
- в строго определённом порядке
- одинаково при каждом запросе
А вот обычные HTTP-библиотеки — requests (Python) и axios (Node.js) — могут добавлять служебные заголовки (User-Agent, Accept-Encoding, Connection) поверх пользовательских, сортировать заголовки или отправлять их в случайном порядке, что ломает ожидаемый порядок и выдаёт автоматизацию.
Как это связано с CapMonster Cloud
CapMonster Cloud только решает CAPTCHA и не делает ваш запрос «похожим на браузер».
То есть:
- Вы получили валидный токен
- Добавили его в запрос
- Но сервер всё равно отвечает ошибкой
Почему? Потому что ваш запрос выглядит как бот.
Как браузер отправляет заголовки (Chrome 146*)
Этот порядок повторяется в реальном браузере практически всегда:
* На момент написания статьи версия Chrome 146 является актуальной.
HTTP/2 псевдо-заголовки
:method
:authority
:scheme
:pathОбычные заголовки (пример Chrome)
sec-ch-ua
sec-ch-ua-mobile
sec-ch-ua-platform
upgrade-insecure-requests
user-agent
accept
sec-fetch-site
sec-fetch-mode
sec-fetch-user
sec-fetch-dest
accept-encoding
accept-language
priorityЧастая ошибка — копирование из DevTools
Многие разработчики делают так:
- Открывают Chrome DevTools
- Копируют заголовки
- Вставляют в код
Проблема:
- DevTools не всегда показывает реальный порядок и может сортировать заголовки
- В результате порядок в коде отличается от браузера
Как получить правильный порядок
Используйте инструменты, которые показывают реальные запросы:
- Charles Proxy
- mitmproxy
- powhttp
Они показывают заголовки так, как их видит сервер.
Например (захвачено Charles Proxy):
:method: GET
:authority: example
:scheme: https
:path: /assets/js/example.js
sec-ch-ua-full-version-list: "Chromium";v="146.0.7680.178", "Not-A.Brand";v="24.0.0.0", "Google Chrome";v="146.0.7680.178"
sec-ch-ua-platform: "Windows"
sec-ch-ua: "Chromium";v="146", "Not-A.Brand";v="24", "Google Chrome";v="146"
sec-ch-ua-bitness: "64"
sec-ch-ua-model: ""
sec-ch-ua-mobile: ?0
sec-ch-ua-arch: "x86"
sec-ch-ua-full-version: "146.0.7680.178"
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36
sec-ch-ua-platform-version: "19.0.0"
accept: */*
sec-fetch-site: same-origin
sec-fetch-mode: no-cors
sec-fetch-dest: script
referer: https://example.com/
accept-encoding: gzip, deflate, br, zstd
accept-language: en-US,en;q=0.9,ru;q=0.8
priority u=0, iКак воспроизвести порядок заголовков в коде
После того как вы получили реальный порядок заголовков, следующая задача — корректно воспроизвести его в своём HTTP-клиенте.
Ключевая проблема: большинство стандартных библиотек не гарантируют порядок заголовков.
Для точного воспроизведения поведения браузера рекомендуется использовать специализированные решения:
- tls-client (Go / Python) — реализует управление порядком заголовков через header_order + pseudo_header_order на уровне Go-биндинга bogdanfinn/tls-client, передавая параметры напрямую в нативную библиотеку
- кастомные HTTP/2 клиенты
- браузерная автоматизация (например, Playwright) — если допустимы накладные расходы
Пример настройки (Python + tls-client)
Ниже приведён пример, демонстрирующий базовый подход к воспроизведению порядка заголовков, аналогичного Chrome.
Важно: chrome_146 — валидный профиль в Go-библиотеке bogdanfinn/tls-client, задокументированный как «Latest». Однако стандартный Python-пакет FlorianREGAZ/Python-Tls-Client (pip install tls-client) заброшен и содержит профили только до chrome_120. Читатель, установивший стандартный пакет, получит ошибку. Используйте актуальный форк bogdanfinn/tls-client или совместимый Python-биндинг с поддержкой chrome_146.
import tls_client
session = tls_client.Session(
client_identifier="chrome_146",
random_tls_extension_order=True
)
session.pseudo_header_order = [
":method",
":authority",
":scheme",
":path",
]
session.header_order = [
"sec-ch-ua",
"sec-ch-ua-mobile",
"sec-ch-ua-platform",
"upgrade-insecure-requests",
"user-agent",
"accept",
"sec-fetch-site",
"sec-fetch-mode",
"sec-fetch-user",
"sec-fetch-dest",
"accept-encoding",
"accept-language",
"cookie",
"priority",
]
headers = {
"sec-ch-ua": '"Chromium";v="146", "Not-A.Brand";v="24", "Google Chrome";v="146"',
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": '"Windows"',
"upgrade-insecure-requests": "1",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/146.0.0.0 Safari/537.36",
"accept": "*/*",
"sec-fetch-site": "same-origin",
"sec-fetch-mode": "no-cors",
"sec-fetch-dest": "script",
"accept-encoding": "gzip, deflate, br, zstd",
"accept-language": "en-US,en;q=0.9",
"priority": "u=0, i",
}
response = session.get("https://example.com", headers=headers)
print(response.status_code)Порядок в session.header_order должен совпадать с тем, который вы получили из реального браузера. Любые отклонения могут повлиять на результат.
HTTP/2 SETTINGS fingerprint
Антибот-системы анализируют не только заголовки — они проверяют HTTP/2 SETTINGS fingerprint ещё до разбора заголовков. Cloudflare и DataDome используют так называемый Akamai H2 fingerprint, который кодирует параметры в строку формата:
SETTINGS|WINDOW_UPDATE|PRIORITY|PSEUDO_HEADER_ORDER
Этот сигнал позволяет мгновенно детектировать curl, requests и axios — без анализа содержимого запроса. tls-client закрывает эту проблему автоматически через client_identifier: он подставляет правильный H2 SETTINGS-профиль для выбранного браузера. Именно поэтому параметр client_identifier="chrome_146" — не просто «версия Chrome», а полноценный профиль всего сетевого стека.
Роль cookies после решения CAPTCHA
После успешного прохождения CAPTCHA серверы часто устанавливают дополнительные cookies. В зависимости от используемой системы защиты это могут быть:
- cf_clearance (Cloudflare)
- datadome (DataDome)
- visid_incap (Imperva)
Эти cookies становятся частью дальнейшей сессии и должны передаваться в последующих запросах.
Заголовок cookie должен находиться в правильной позиции внутри Header Order. Если он:
- отсутствует в списке порядка заголовков
- или добавляется автоматически в конец
это может нарушить ожидаемую структуру запроса и привести к отклонению.
Пример передачи cookies через session в tls-client:
import tls_client
session = tls_client.Session(
client_identifier="chrome_146",
random_tls_extension_order=True,
)
# После получения cf_clearance от CapMonster Cloud / вручную — передаём в сессию
session.cookies.set(
"cf_clearance",
"полученное_значение",
domain=".example.com",
)
# Все последующие запросы автоматически включат cookie в правильной позиции
response = session.get(
"https://example.com/protected-page",
headers=headers,
)
print(response.status_code)Дополнительные ошибки, влияющие на результат
Несогласованность заголовков между запросами
Реальные браузеры используют стабильный набор заголовков. Если ваш скрипт:
- отправляет разные заголовки на разных этапах
- меняет их порядок
- добавляет или убирает заголовки без логики
это воспринимается как аномалия.
Некорректный Referer
Заголовок referer играет важную роль в контексте навигации. Его отсутствие или несоответствие может выглядеть подозрительно.
Например, если вы запрашиваете ресурс, который обычно загружается со страницы, но не указываете referer, это может вызвать дополнительную проверку.
Несоответствие sec-fetch заголовков
Заголовки Sec-Fetch-Site, Sec-Fetch-Mode и Sec-Fetch-Dest должны соответствовать реальному контексту запроса. Sec-Fetch-Site показывает отношение между инициатором и целевым ресурсом, Sec-Fetch-Mode — режим запроса, а Sec-Fetch-Dest — назначение загружаемого ресурса.
Неверные или несогласованные значения могут противоречить остальным данным HTTP-запроса и использоваться сервером как сигнал для отклонения запроса. Особенно часто ошибки возникают, когда none ставят для обычного клика по ссылке или когда путают cross-origin с cross-site.
Таблица корректных значений в зависимости от типа запроса:
Использование HTTP/1.1 вместо HTTP/2
Современные браузеры, включая Chrome, по умолчанию используют HTTP/2.
Если ваш клиент работает через HTTP/1.1, это уже создаёт заметное отличие. В сочетании с другими факторами это может повлиять на решение антибот-системы.
Жёстко заданный sec-ch-ua-full-version-list
Заголовок sec-ch-ua-full-version-list появляется только в ответ на Accept-CH от сервера (Client Hints API) — не в каждом запросе автоматически. В «холодных» запросах его не должно быть вовсе.
Жёсткое (hardcoded) задание этого заголовка в коде может привести к несоответствию между User-Agent, sec-ch-ua и реальным TLS-профилем. В результате запрос выглядит неконсистентно и может быть отклонён антибот-системой.
В ряде случаев (например, при работе с DataDome) безопаснее либо получать его из реального трафика, либо не задавать вручную без необходимости.
Дублирующиеся cookies
Ещё одна распространённая ошибка — отправка нескольких cookies с одинаковым именем, но разными значениями. Например:

Такая ситуация может возникать, если:
- cookies управляются вручную без использования cookie jar
- библиотека некорректно объединяет cookies
- происходит повторная установка значений
Корректный подход:
- использовать встроенные механизмы управления cookies (cookie jar)
- проверять итоговый заголовок cookie перед отправкой
- избегать дублирования имён
Практический подход к отладке
Наиболее надёжный способ диагностики — сравнение реального браузерного запроса с вашим.
Рекомендуемый процесс:
- Захватить запрос из браузера с помощью инструментов вроде Charles Proxy или mitmproxy
- Выполнить аналогичный запрос из вашего кода
- Сравнить их построчно
Особое внимание следует уделить:
- порядку заголовков
- наличию или отсутствию отдельных заголовков
- значениям заголовков
- cookies
Даже небольшие различия могут иметь значение.
Заключение
Сервис CapMonster Cloud помогает получить корректное решение CAPTCHA, однако дальнейшая обработка и использование этого решения в вашем приложении остаются на вашей стороне.
Так, например, Cloudflare Bot Management проверяет TLS, H2 SETTINGS и заголовки одновременно — провал на одном слое достаточен для блокировки. Для успешного взаимодействия с защищёнными системами необходимо:
- воспроизводить поведение браузера на уровне HTTP
- соблюдать точный порядок заголовков
- использовать корректный TLS-профиль и H2 SETTINGS через client_identifier
- поддерживать согласованность запросов
- правильно обрабатывать cookies через cookie jar
Только совокупность этих факторов позволяет добиться стабильного результата при тестировании и работе с антибот-защитами.






