Comparisons

Проверка целостности браузера Cloudflare против CAPTCHA-вызова

Запрос упал с кодом 403 — почти наверняка виноват Browser Integrity Check (BIC). Запрос упал с 503 и на странице появился JS-виджет — это уже CAPTCHA-вызов Cloudflare. Разработчики регулярно путают эти механизмы, хотя чинятся они совершенно по-разному. Ниже — таблица различий, разбор каждого механизма и код для автоматической диагностики того, что заблокировало запрос.

Коротко: 403 без сопроводительной страницы — это BIC, чинится только заголовками HTTP. 503 с виджетом или JS-страницей — это CAPTCHA-вызов, здесь без CaptchaAI не обойтись.


Сравнение BIC и CAPTCHA-вызова Cloudflare

Параметр Browser Integrity Check CAPTCHA-вызов
Что проверяется Только HTTP-заголовки Поведение браузера и окружение
Нужен JavaScript? Нет (уровень заголовков) Да
Что видит пользователь Ничего (прошёл) или 403 (не прошёл) Виджет проверки или JS-страница
HTTP-статус при блоке 403 503
Можно решить? Нет — только исправить заголовки Да — решить CAPTCHA
Какая cookie выдаётся Не выдаётся qa_validation_cookie
Нужен ли CaptchaAI Нет — чините заголовки запроса Да
Включена по умолчанию Да, на всех планах Cloudflare Нет, настраивается под конкретное правило
Область действия Каждый запрос Только запросы, подпадающие под правило WAF

Диагностика по симптомам: с чего начать

Прежде чем разбирать механизмы по отдельности, сверьтесь с таблицей симптомов — часто она сразу даёт ответ:

Симптом Причина Что делать
403 на минимальных заголовках, 200 на браузерных Сработал только BIC Используйте заголовки как у настоящего браузера
403 при любых заголовках Блок по IP или правило WAF Смените IP или прокси
503 со страницей проверки Это уже CAPTCHA-вызов, не BIC Решите его через CaptchaAI
403 время от времени Rate limiting или проверка сессии Снизьте частоту запросов, сохраняйте сессию
Заголовки в порядке, но всё равно 403 Проверяется TLS-сигнатура соединения (JA3) Используйте curl_cffi или настоящий браузер

Что такое Browser Integrity Check

BIC анализирует заголовки HTTP-запроса и отсекает трафик, который явно не похож на браузер, — ещё до того, как сработает любой JavaScript- или CAPTCHA-вызов. Проверка держится на пяти сигналах:

  • корректность и наличие User-Agent;
  • порядок заголовков в запросе;
  • наличие браузерных заголовков (Accept, Accept-Language, Accept-Encoding);
  • совпадение UA с известными сигнатурами ботов;
  • репутация IP-адреса.

Какие сигналы проверяет BIC

Проверка На что смотрит Типичная причина блока
User-Agent Отсутствует, пустой или из чёрного списка python-requests/2.31, curl, wget
Порядок заголовков Заголовки идут не в том порядке, что у браузера Нестандартные HTTP-библиотеки
Отсутствие браузерных заголовков Нет Accept, Accept-Language, Accept-Encoding Минималистичные HTTP-клиенты
Известные сигнатуры ботов UA спам-ботов и сканеров Googlebot не с IP-адресов Google
IP в чёрных списках Известные вредоносные IP Дата-центровые IP из блок-листов

Пошагово это выглядит так:

Request hits Cloudflare edge
    ↓
BIC evaluates HTTP headers:
  ├─ User-Agent present and valid?
  ├─ Required headers (Accept, Accept-Language) present?
  ├─ Header order consistent with browser?
  └─ IP not on abuse list?
    ↓
Pass → Request forwarded to origin
    OR
Fail → 403 Forbidden (no challenge offered)

Как пройти BIC на практике. BIC не требует решения CAPTCHA — достаточно отправить заголовки, похожие на настоящий браузер:

import requests

# ❌ FAILS BIC — minimal headers
response = requests.get("https://cloudflare-protected.com")
# User-Agent: python-requests/2.31.0
# Result: 403 Forbidden

# ✅ PASSES BIC — browser-like headers
headers = {
    "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",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,"
              "image/avif,image/webp,*/*;q=0.8",
    "Accept-Language": "en-US,en;q=0.9",
    "Accept-Encoding": "gzip, deflate, br",
    "Connection": "keep-alive",
    "Upgrade-Insecure-Requests": "1",
    "Sec-Fetch-Dest": "document",
    "Sec-Fetch-Mode": "navigate",
    "Sec-Fetch-Site": "none",
    "Sec-Fetch-User": "?1",
}

response = requests.get("https://cloudflare-protected.com", headers=headers)
# Result: 200 OK (passed BIC)

То же самое на Node.js:

const axios = require("axios");

// Browser-like headers to pass BIC
const headers = {
  "User-Agent":
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0.0.0",
  Accept:
    "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,*/*;q=0.8",
  "Accept-Language": "en-US,en;q=0.9",
  "Accept-Encoding": "gzip, deflate, br",
  Connection: "keep-alive",
  "Upgrade-Insecure-Requests": "1",
  "Sec-Fetch-Dest": "document",
  "Sec-Fetch-Mode": "navigate",
  "Sec-Fetch-Site": "none",
  "Sec-Fetch-User": "?1",
};

async function fetchWithBIC(url) {
  const response = await axios.get(url, { headers });
  console.log(`Status: ${response.status}`);
  return response.data;
}

Когда включается CAPTCHA-вызов

CAPTCHA-вызов запускается уже после того, как запрос прошёл BIC. Он требует выполнения JavaScript и представляет собой задачу, которую действительно нужно решить:

Cloudflare различает четыре вида CAPTCHA-вызова:

Тип вызова Условие срабатывания Виден пользователю? Метод CaptchaAI
Виджет Cloudflare Turnstile Встроен на страницу разработчиком Виджет в форме turnstile
Managed Challenge Совпадение с правилом WAF Адаптивный (невидимый или чекбокс) turnstile
JavaScript Challenge Правило IUAM или WAF Страница «Checking your browser» cloudflare_challenge
Interactive Challenge Высокий уровень подозрения Полноэкранная проверка cloudflare_challenge

Последовательность прохождения:

Request passes BIC check
    ↓
WAF rules evaluate bot score, IP, path
    ↓
Rule triggers CAPTCHA challenge (HTTP 503)
    ↓
Browser executes JavaScript challenge
    ↓
Challenge solved → qa_validation_cookie cookie issued
    ↓
Subsequent requests pass with cookie

Как диагностировать: BIC или CAPTCHA заблокировали запрос

Когда запрос падает, тип блока определяет, что чинить:

import requests

def diagnose_cloudflare_block(url):
    """Determine if block is BIC or CAPTCHA."""
    # Intentionally use minimal headers to trigger BIC
    minimal_response = requests.get(url, timeout=15, allow_redirects=False)

    # Use browser headers to inspect BIC in QA
    browser_headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                      "AppleWebKit/537.36 Chrome/120.0.0.0",
        "Accept": "text/html,application/xhtml+xml,*/*;q=0.8",
        "Accept-Language": "en-US,en;q=0.9",
        "Accept-Encoding": "gzip, deflate, br",
    }
    browser_response = requests.get(
        url, headers=browser_headers, timeout=15, allow_redirects=False
    )

    result = {
        "minimal_headers_status": minimal_response.status_code,
        "browser_headers_status": browser_response.status_code,
    }

    if minimal_response.status_code == 403 and browser_response.status_code == 200:
        result["diagnosis"] = "BIC only — fix headers to pass"
        result["fix"] = "Add browser-like headers"

    elif minimal_response.status_code == 403 and browser_response.status_code == 403:
        result["diagnosis"] = "IP or WAF block — not just BIC"
        result["fix"] = "Change IP or check WAF rules"

    elif browser_response.status_code == 503:
        html = browser_response.text
        if "jschl" in html:
            result["diagnosis"] = "IUAM JavaScript challenge"
            result["fix"] = "Use CaptchaAI turnstile method"
        elif "cf-turnstile" in html or "challenge-platform" in html:
            result["diagnosis"] = "Managed/Turnstile challenge"
            result["fix"] = "Use CaptchaAI turnstile method"
        else:
            result["diagnosis"] = "Unknown страница Cloudflare-защиты в staging"
            result["fix"] = "Inspect page source for challenge type"

    elif browser_response.status_code == 200:
        html = browser_response.text
        if "cf-turnstile" in html:
            result["diagnosis"] = "Page loads but has Turnstile widget"
            result["fix"] = "Use CaptchaAI turnstile method for form submission"
        else:
            result["diagnosis"] = "No challenge — page accessible"
            result["fix"] = "None needed"

    return result


# Usage
diagnosis = diagnose_cloudflare_block("https://example-cf-site.com")
print(f"Diagnosis: {diagnosis['diagnosis']}")
print(f"Fix: {diagnosis['fix']}")

Частые сценарии на практике

Сценарий 1: заблокировал только BIC.

Request with python-requests UA → 403
Request with Chrome UA → 200 ✓

Fix: Add proper browser headers. No CaptchaAI needed.

Сценарий 2: BIC пройден, дальше CAPTCHA.

Request with Chrome UA → 503 (challenge page)

Fix: Headers are fine. Use CaptchaAI to solve the challenge.

Сценарий 3: BIC и CAPTCHA вместе.

Request with python-requests UA → 403 (BIC block)
Request with Chrome UA → 503 (CAPTCHA challenge)

Fix: First fix headers, then solve CAPTCHA with CaptchaAI.

Сценарий 4: ни то ни другое — блокировка по IP.

Request with python-requests UA → 403
Request with Chrome UA → 403

Fix: Neither BIC nor solvable challenge. IP is blocked.
Try different IP/proxy.

Для команд, которые разворачивают парсеры и QA-стенды из европейских дата-центров или из Казахстана, чаще встречается именно сценарий 4: диапазон дата-центра уже в чёрном списке до первого запроса. Резидентный прокси как нейтральная инфраструктура снимает проблему быстрее, чем правка заголовков. И отдельно: собирайте только те данные, которые вы вправе обрабатывать, — это касается и 152-ФЗ, и GDPR для трансграничных проектов.


Как собрать заголовки, которые проходят BIC

Обязательный набор заголовков выглядит так:

CLOUDFLARE_SAFE_HEADERS = {
    # Mandatory
    "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",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "Accept-Language": "en-US,en;q=0.9",
    "Accept-Encoding": "gzip, deflate, br",

    # Strongly recommended
    "Connection": "keep-alive",
    "Upgrade-Insecure-Requests": "1",

    # Sec-Fetch headers (modern Chrome)
    "Sec-Fetch-Dest": "document",
    "Sec-Fetch-Mode": "navigate",
    "Sec-Fetch-Site": "none",
    "Sec-Fetch-User": "?1",

    # Recommended for consistency
    "Sec-Ch-Ua": '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"',
    "Sec-Ch-Ua-Mobile": "?0",
    "Sec-Ch-Ua-Platform": '"Windows"',
}

А вот заголовки, которые чаще всего ловят блок BIC:

Заголовок Почему он проваливает проверку
User-Agent: python-requests/2.31.0 Известный идентификатор HTTP-библиотеки
User-Agent: curl/7.81.0 Идентификатор CLI-инструмента
Отсутствует заголовок Accept Ни один браузер не пропускает Accept
Отсутствует Accept-Language Его отправляют все браузеры
User-Agent: "" (пустой) Явный признак автоматизации
User-Agent: Googlebot/2.1 не с IP Google Поддельная идентификация бота

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

Как быстро отличить BIC от CAPTCHA-вызова по коду ответа?

Смотрите на HTTP-статус. 403 без какой-либо страницы — это BIC: заголовки не прошли проверку ещё до рендера. 503 с HTML-страницей или JS-виджетом — это уже CAPTCHA-вызов, который требует реального решения.

Нужен ли CaptchaAI, чтобы пройти сам BIC?

Нет. BIC — это фильтр по заголовкам, а не решаемая задача. Если запрос падает с 403 на BIC, проблема в заголовках HTTP. CaptchaAI нужен только для CAPTCHA-вызовов (Turnstile, Managed Challenge, JavaScript Challenge), которые появляются уже после того, как BIC пройден.

Сколько заголовков минимально нужно отправить, чтобы не словить блок BIC?

На практике достаточно четырёх: корректный User-Agent современного браузера, Accept, Accept-Language и Accept-Encoding. Заголовки Sec-Fetch-* и Connection: keep-alive не обязательны для прохода, но заметно повышают правдоподобность профиля запроса.

Что делать, если после успешного BIC всё равно появляется CAPTCHA?

Это нормально — BIC и CAPTCHA-вызов работают независимо. Пройденный BIC означает лишь то, что заголовки выглядят как у браузера; правило WAF или режим IUAM может всё равно запросить CAPTCHA. Решайте её через CaptchaAI, заголовки трогать не нужно.

Cookie выдаётся сразу после успешного прохождения проверки и используется Cloudflare, чтобы не показывать вызов повторно на последующих запросах в рамках той же сессии. Пока cookie действительна, повторные запросы проходят без нового CAPTCHA-вызова.


Коротко о главном

BIC и CAPTCHA-вызов — независимые уровни защиты Cloudflare, и путать их — верный способ чинить не то, что сломалось. BIC решается только заголовками, без CaptchaAI. CAPTCHA-вызов — реальная задача (Turnstile, Managed Challenge, JavaScript Challenge), и здесь без CaptchaAI не обойтись.

Порядок действий коротко:

  1. Смотрите на HTTP-статус — 403 или 503.
  2. Для 403 — проверьте и дополните заголовки запроса.
  3. Для 503 — подключите CaptchaAI (turnstile или cloudflare_challenge).
  4. Если 403 держится при любых заголовках — дело в IP, меняйте адрес или прокси.

Похожие статьи

Комментарии для этой статьи отключены.