Comparisons

Verificação de integridade do navegador Cloudflare vs desafio CAPTCHA

Sua requisição voltou com 403 e nenhuma tela apareceu? Isso é o Browser Integrity Check (BIC) da Cloudflare — um bloqueio silencioso, só de cabeçalhos. Já um 503 com página "verificando seu navegador" ou widget para resolver é outra camada: o desafio CAPTCHA.

Confundir as duas custa tempo, porque a correção é oposta:

  • 403 sem tela nenhuma → BIC. Corrija os cabeçalhos da requisição, sem CaptchaAI.
  • 503 com desafio ou widget → CAPTCHA da Cloudflare. Resolva com a CaptchaAI (turnstile ou cloudflare_challenge).
  • 403 mesmo com cabeçalhos de navegador completos → não é nenhum dos dois; é IP ou regra de WAF.

Este guia mostra como diferenciar as duas em segundos e o que fazer em cada caso.


BIC ou desafio CAPTCHA: como diferenciar em segundos

O que cada camada detecta

Critério BIC Desafio CAPTCHA
O que verifica Só os cabeçalhos HTTP Comportamento do navegador + ambiente
Exige JavaScript? Não (nível de cabeçalho) Sim
O que o usuário vê Nada (passou) ou 403 (bloqueado) Widget de desafio ou página de verificação
Status HTTP na falha 403 503

Como BIC e CAPTCHA se resolvem

Critério BIC Desafio CAPTCHA
Dá para resolver? Não — corrija os cabeçalhos Sim — resolva o CAPTCHA
Emite cookie? Não Sim, cookie de validação
Precisa da CaptchaAI? Não Sim
Ativo por padrão Sim, em todos os planos Não — depende de regra
Onde se aplica Toda requisição Só nas regras de WAF correspondentes

O que é o BIC da Cloudflare

O BIC avalia os cabeçalhos da requisição HTTP para detectar tráfego obviamente automatizado.

Ele roda antes de qualquer desafio de JavaScript ou CAPTCHA entrar em cena — é a primeira barreira, não a única.

O que o BIC examina

O BIC cruza cinco sinais antes de deixar a requisição passar:

  • Validação do User-Agent — ausente, vazio ou inválido: python-requests/2.31, curl, wget.
  • Ordem dos cabeçalhos — fora da ordem típica de navegador, comum em libs HTTP.
  • Cabeçalhos ausentes — falta de Accept, Accept-Language ou Accept-Encoding.
  • Assinaturas de bot conhecidas — UAs de spam/scanner, Googlebot de IP que não é do Google.
  • IP em lista de abuso — IPs de datacenter em blocklist.

Como o BIC decide, passo a passo

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)

Como fazer sua requisição passar no BIC

O BIC se resolve enviando cabeçalhos parecidos com os de um navegador real — nenhuma resolução de CAPTCHA é necessária:

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)

Em 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;
}

Desafios CAPTCHA da Cloudflare: quando aparecem

Os desafios CAPTCHA entram em cena depois que o BIC já aprovou a requisição.

Eles exigem execução de JavaScript e apresentam uma tarefa solucionável — bem diferente do bloqueio silencioso do BIC.

Tipos de desafio CAPTCHA da Cloudflare

Quatro variantes aparecem na prática, e o método da CaptchaAI muda conforme o tipo:

  • Widget Turnstile — incorporado na página pelo desenvolvedor, aparece no formulário → turnstile.
  • Managed Challenge — regra de WAF correspondente, adaptativo (invisível ou checkbox) → turnstile.
  • JavaScript Challenge — regra IUAM ou WAF, página "Verificando seu navegador" → cloudflare_challenge.
  • Interactive Challenge — suspeita alta, desafio de página inteira → cloudflare_challenge.

Como funciona o fluxo do desafio (diferente do BIC)

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

Diagnosticando qual bloqueio você recebeu

Quando a requisição é bloqueada, identificar o tipo é o que determina a correção:

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 validação autorizada BIC
    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 a CaptchaAI turnstile_staging method"
        elif "cf-turnstile" in html or "challenge-platform" in html:
            result["diagnosis"] = "Managed/Turnstile challenge"
            result["fix"] = "Use a CaptchaAI turnstile method"
        else:
            result["diagnosis"] = "Unknown Cloudflare Turnstile em 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 a 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']}")

Rode essa função contra a URL real antes de escrever o resto do pipeline. Os quatro cenários abaixo cobrem os resultados que ela pode retornar.

Cenário 1: só bloqueio do BIC

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

Fix: Add proper browser headers. No CaptchaAI needed.

Cenário 2: passa no BIC, cai no CAPTCHA

Request with Chrome UA → 503 (challenge page)

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

Cenário 3: BIC e CAPTCHA juntos

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

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

Cenário 4: nenhum dos dois — IP bloqueado

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

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

Contexto para quem roda automação a partir do Brasil

Se seus workers rodam em nuvem, meça o RTT antes de decidir se um 403 é BIC ou rede lenta: partindo de sa-east-1 (São Paulo), a latência até sites Cloudflare costuma ser menor que partindo de us-east-1, reduzindo falsos positivos de timeout. Se o script de diagnóstico registra IP e cabeçalhos em log, trate como dado pessoal sob a LGPD — use domínios de staging e retenção mínima.


Cabeçalhos que fazem sua requisição passar

Conjunto de cabeçalhos essenciais

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"',
}

Nem todo cabeçalho da lista acima é obrigatório — os quatro primeiros bastam na maioria dos casos.


Cabeçalhos que costumam acionar o BIC

Seis padrões respondem pela maioria dos bloqueios que a equipe vê no dia a dia:

  • User-Agent: python-requests/2.31.0 — identificador de biblioteca HTTP conhecida.
  • User-Agent: curl/7.81.0 — ferramenta de linha de comando.
  • Cabeçalho Accept ausente — nenhum navegador real omite o Accept.
  • Accept-Language ausente — todo navegador envia esse cabeçalho.
  • User-Agent: "" (vazio) — inválido, automação óbvia.
  • User-Agent: Googlebot/2.1 partindo de IP que não é do Google — identidade de bot falsificada.

Diagnóstico rápido: sintoma, causa e correção

Cinco combinações cobrem quase todos os casos:

  • 403 com cabeçalhos mínimos, 200 com cabeçalhos de navegador → só BIC. Use cabeçalhos de navegador.
  • 403 em qualquer combinação → IP bloqueado ou regra de WAF. Tente outro IP ou proxy.
  • 503 com página de desafio → CAPTCHA, não BIC. Use a CaptchaAI.
  • 403 intermitente → rate limit ou sessão. Reduza a taxa, mantenha a sessão.
  • Cabeçalhos corretos, mas ainda 403 → sinal de navegador TLS (JA3). Use curl_cffi ou navegador real.

Perguntas frequentes

O CaptchaAI resolve o bloqueio do BIC?

Não. O BIC não apresenta desafio solucionável — corrige-se ajustando os cabeçalhos HTTP, não com uma API de CAPTCHA. A CaptchaAI entra depois, nos desafios Turnstile e Cloudflare Challenge que aparecem após o BIC ser aprovado.

Passar no BIC significa que eu nunca mais vou ver um CAPTCHA?

Não. BIC e CAPTCHA são camadas independentes. Passar no BIC só garante cabeçalhos legítimos — regras de WAF, pontuação de bot ou o modo IUAM ainda podem acionar um CAPTCHA depois.

Recebo 403 de forma intermitente mesmo depois de corrigir os cabeçalhos. Por quê?

Nesse caso, o mais comum é rate limiting ou bloqueio por sessão — a Cloudflare libera a primeira requisição e barra as seguintes se o padrão de acesso mudar. Reduza a taxa e mantenha os cookies de sessão antes de investigar outra causa.

Todo 403 da Cloudflare significa que meu IP foi bloqueado?

Não necessariamente. Pode ser BIC (cabeçalhos ruins), regra de WAF ou bloqueio de IP. Rode a requisição com cabeçalhos mínimos e depois completos: se a segunda passa, era só BIC; se ambas falham, é um bloqueio mais duro (IP ou WAF).

Dá para saber, antes de programar a automação, se um site usa BIC, CAPTCHA ou os dois?

Dá, com o mesmo teste deste artigo: uma requisição com cabeçalhos mínimos e outra completa contra a mesma URL. Comparar os códigos de status (403, 200 ou 503) já indica qual camada tratar antes do resto do pipeline.


Resumo

O BIC da Cloudflare bloqueia com 403 requisições cujos cabeçalhos não vêm de um navegador; o desafio CAPTCHA aparece como 503 e apresenta uma tarefa solucionável. O BIC se corrige com cabeçalhos adequados — sem CaptchaAI. O desafio CAPTCHA exige o método turnstile ou cloudflare_challenge da CaptchaAI. Diagnostique o bloqueio primeiro: cabeçalhos para o BIC, CaptchaAI para os CAPTCHAs, e troque de IP só quando nenhum dos dois resolver.

Artigos relacionados

Os comentários estão desativados para este artigo.