Запрос упал с кодом 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 после решения CAPTCHA-вызова?
Cookie выдаётся сразу после успешного прохождения проверки и используется Cloudflare, чтобы не показывать вызов повторно на последующих запросах в рамках той же сессии. Пока cookie действительна, повторные запросы проходят без нового CAPTCHA-вызова.
Коротко о главном
BIC и CAPTCHA-вызов — независимые уровни защиты Cloudflare, и путать их — верный способ чинить не то, что сломалось. BIC решается только заголовками, без CaptchaAI. CAPTCHA-вызов — реальная задача (Turnstile, Managed Challenge, JavaScript Challenge), и здесь без CaptchaAI не обойтись.
Порядок действий коротко:
- Смотрите на HTTP-статус — 403 или 503.
- Для 403 — проверьте и дополните заголовки запроса.
- Для 503 — подключите CaptchaAI (
turnstileилиcloudflare_challenge). - Если 403 держится при любых заголовках — дело в IP, меняйте адрес или прокси.