Internos do Cloudflare Turnstile: Como o Bot Management Avalia Sessões em 2026

Um mergulho técnico nos internos do Cloudflare Turnstile e no score de confiança do Bot Management: JA4, HTTP/2, fingerprint de browser, IP e como passar com proxies residenciais sticky e cf_clearance.

Cloudflare Turnstile Internals: How the 2026 Trust Score Works and How Legitimate Automation Passes

Os internos do Cloudflare Turnstile determinam se o seu request automatizado recebe uma página limpa ou um desafio interativo em 2026. Para engenheiros de scraping e pesquisadores de segurança, entender como o sistema avalia TLS, HTTP/2, fingerprint de navegador e reputação de IP é a diferença entre uma pipeline estável e uma taxa de bloqueio de 90%.

Aviso legal: Este artigo cobre técnicas para acesso autorizado a dados públicos, pentesting com permissão explícita e pesquisa de segurança. O acesso não autorizado a sistemas protegidos pode violar leis como a Computer Fraud and Abuse Act (CFAA) dos EUA e o Regulamento Geral de Proteção de Dados (GDPR) da UE. Sempre verifique os Termos de Serviço e o arquivo robots.txt do alvo antes de qualquer coleta automatizada.

Internos do Cloudflare Turnstile: O Que o Sistema Realmente Executa

O Turnstile é o produto de challenge gerenciado da Cloudflare que substituiu o reCAPTCHA tradicional. Quando você acessa um site protegido, o Turnstile executa um conjunto de verificações invisíveis antes de decidir se libera o acesso. Compreender os internos do Cloudflare Turnstile começa por entender o que acontece no browser do visitante.

O fluxo começa com o carregamento de um script JavaScript ofuscado hospedado em challenges.cloudflare.com. Esse script coleta dezenas de sinais do navegador em tempo real — não há um único "clique no botão" que resolve tudo. Os principais componentes são:

  • Proof-of-Work (PoW) adaptativo: O servidor envia um desafio criptográfico que o cliente deve resolver antes de enviar o formulário. A dificuldade é ajustada dinamicamente — um browser moderno resolve em 50–200ms, mas um script simples em Python pode levar 5–10 segundos ou falhar completamente.
  • Probes de API do navegador: O script verifica a presença e o comportamento de APIs como navigator.webdriver, window.chrome, Notification.permission, navigator.plugins e WebGLRenderingContext. Bibliotecas como Selenium e Playwright deixam rastros detectáveis nessas APIs.
  • Timing de eventos: O Turnstile mede o tempo entre mousemove, keydown e submit. Movimentos perfeitamente lineares ou ausência total de eventos são sinais negativos.
  • Fingerprint de canvas e WebGL: O script renderiza imagens off-screen e compara o hash resultante com o esperado para o User-Agent declarado. Um Chrome real no Windows produz um hash diferente de um Chrome emulado no Linux.

Se todos os sinais passarem, o Turnstile emite um token (cf_clearance) que é armazenado como cookie e enviado em requests subsequentes. Esse token é o "passaporte" que permite navegar pelo site sem novos desafios — mas vem com restrições rigorosas, como veremos adiante. A documentação oficial da Cloudflare sobre Turnstile descreve o fluxo de integração do lado do servidor.

O Cookie cf_clearance e Suas Restrições

O cookie cf_clearance é o resultado de um desafio bem-sucedido. Ele tem três propriedades críticas que afetam qualquer estratégia de automação:

  1. Está vinculado ao IP: O token é emitido para o IP que completou o desafio. Se o IP mudar, o cookie é rejeitado e um novo desafio é exigido.
  2. Está vinculado ao User-Agent: O User-Agent enviado durante o desafio deve corresponder exatamente ao User-Agent dos requests subsequentes.
  3. Tem validade limitada: O tempo de vida típico é de 30 minutos a 2 horas, dependendo da configuração do site. Após a expiração, um novo desafio é necessário.

Essas restrições significam que qualquer solução que envolva rotação de IPs ou mudança de User-Agent entre requests vai invalidar o token imediatamente. Isso é intencional — a Cloudflare quer garantir que a mesma "identidade" que passou no desafio continue sendo a mesma ao longo da sessão.

Os Quatro Sinais do Cloudflare Bot Management JA4

Além do Turnstile, o Cloudflare Bot Management avalia cada conexão usando um score de confiança composto por quatro sinais principais. O sistema não publica a fórmula exata, mas pesquisadores de segurança e engenharia reversa identificaram consistentemente estes componentes:

1. JA4 — Fingerprint TLS

O JA4 é o sucessor do JA3 e foi desenvolvido pela FoxIO. Diferente do JA3, que concatenava os campos em ordem de aparição, o JA4 ordena as extensões TLS alfabeticamente antes de aplicar o hash SHA-256. Isso torna o fingerprint determinístico e independente da ordem de negociação do servidor.

O formato JA4 é estruturado como: q(t)(a)(i)(j)_k_k_k, onde:

  • q = protocolo de transporte (t = TCP, q = QUIC)
  • (t) = versão TLS (d = TLS 1.2, e = TLS 1.3)
  • (a) = suporte a ALPN (d = "h2", h = "http/1.1")
  • (i)(j) = número de cipher suites e extensões
  • _k_k_k = hashes de cipher suites, extensões e assinaturas

Um Chrome 131 no Windows 10 produz um JA4 diferente do Firefox 131 no Linux, que por sua vez é diferente do requests no Python. O repositório oficial do JA4 na FoxIO mantém uma lista de fingerprints conhecidos por cliente.

2. SETTINGS do HTTP/2

Quando a conexão usa HTTP/2, o cliente envia um frame SETTINGS na fase de preface. A ordem e os valores dos parâmetros — como SETTINGS_MAX_CONCURRENT_STREAMS, SETTINGS_INITIAL_WINDOW_SIZE e SETTINGS_HEADER_TABLE_SIZE — variam entre implementações. O Chrome envia um conjunto específico; o Python httpx envia outro; o curl envia um terceiro. Esse fingerprint de SETTINGS é menos conhecido mas igualmente discriminativo.

3. Fingerprint de Navegador

O Turnstile coleta uma vasta gama de sinais via JavaScript:

  • Canvas: Renderiza texto e formas em um <canvas> off-screen e calcula o hash dos pixels. Diferentes GPUs, drivers e sistemas operacionais produzem resultados distintos.
  • WebGL: Verifica VENDOR, RENDERER e parâmetros de extensões. Um headless browser sem GPU real reporta valores atípicos como "SwiftShader".
  • AudioContext: Processa um sinal de áudio de teste e mede diferenças de precisão de ponto flutuante. Isso distingue entre engines JavaScript reais e implementações simuladas.
  • Fontes: Mede a largura de strings em fontes específicas do sistema. Um ambiente headless tipicamente não tem as mesmas fontes que um desktop real.

4. Reputação de IP

A Cloudflare mantém um banco de dados de reputação de IP que classifica endereços em categorias como datacenter, residential, mobile, known-bot, proxy e Tor. IPs de datacenters de provedores de nuvem (AWS, GCP, DigitalOcean) recebem scores baixos por padrão. IPs residenciais de ISPs legítimos recebem scores mais altos porque são associados a usuários reais.

A tabela abaixo resume como cada sinal contribui para o score:

Sinal Peso Estimado Detecta Difícil de Falsificar?
JA4 TLS Alto Cliente HTTP não-browser Médio — requer biblioteca TLS compatível
HTTP/2 SETTINGS Médio Cliente HTTP não-browser Alto — requer implementação HTTP/2 específica
Fingerprint de browser Alto Headless, Selenium, Playwright não-patched Médio — navegadores patched passam
Reputação de IP Alto Datacenter, proxy, Tor Baixo — use proxy residencial

Por Que Chrome no User-Agent com JA4 do Python É Desafiado Instantaneamente

Este é o erro número um que vemos em pipelines de scraping. Um desenvolvedor configura o requests ou httpx com um User-Agent do Chrome 131:

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
                  "(KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
}
response = requests.get("https://exemplo-protegido.com", headers=headers)

O problema é que o User-Agent é apenas uma string de texto — qualquer cliente pode declarar qualquer valor. Mas o JA4 fingerprint revela a verdade. O requests usa a biblioteca urllib3 que por sua vez usa OpenSSL ou libcurl. O ClientHello enviado por essas bibliotecas tem uma ordem de cipher suites e extensões completamente diferente do ClientHello enviado pelo BoringSSL (a biblioteca TLS do Chrome).

Quando o Cloudflare Bot Management recebe uma conexão que declara Chrome/131.0.0.0 no User-Agent mas apresenta um JA4 que corresponde a python-requests/2.31, a inconsistência é imediata e o score de confiança despenca. O resultado é um desafio 403 ou um redirect para a página de Turnstile.

Isso não é um bug — é uma feature. A Cloudflare sabe que bots mentem no User-Agent, então usa o JA4 como uma fonte independente de verdade. Para passar, você precisa de um cliente cujo stack TLS seja indistinguível do browser que você está imitando.

Cookie cf_clearance: Por Que Proxies Residenciais Importam

Como vimos, o cf_clearance é vinculado ao IP que completou o desafio. Isso tem implicações diretas na escolha de proxy:

Proxies de datacenter não funcionam bem porque seus IPs já têm baixa reputação no Cloudflare Bot Management. Mesmo que você obtenha um cf_clearance, o score de IP pode fazer com que a Cloudflare desafie novamente em requests subsequentes, criando um ciclo de desafios infinitos.

Proxies residenciais são essenciais porque:

  • O IP de saída é de um ISP real, com score de reputação alto.
  • O cf_clearance obtido através desse IP permanece válido enquanto o IP não mudar.
  • A consistência entre o IP do desafio e o IP dos requests subsequentes é mantida.

Rotação de IP é inimiga do cf_clearance. Se você usa um pool de proxies que rotaciona a cada request, cada request sai de um IP diferente. O cookie obtido no IP A é rejeitado quando enviado pelo IP B. A solução é usar sessões sticky — um IP fixo que dura toda a sessão de scraping.

Abordagem Prática com ProxyHat: Sessões Residenciais Sticky e cf_clearance

Aqui está uma abordagem legítima e prática para acessar sites protegidos por Turnstile em cenários de automação autorizada. A estratégia tem duas fases: (1) obter o cf_clearance usando um browser real através de um proxy residencial sticky, e (2) reusar esse cookie em requests subsequentes através do mesmo IP.

Fase 1: Obter cf_clearance com um Browser Real

Use um navegador real — não headless puro — controlado por Playwright, conectado ao ProxyHat através de uma sessão sticky residencial:

from playwright.sync_api import sync_playwright

# ProxyHat com sessão sticky residencial
proxy_config = {
    "server": "http://gate.proxyhat.com:8080",
    "username": "user-session-abc123-country-US",
    "password": "sua_senha"
}

with sync_playwright() as p:
    browser = p.chromium.launch(
        headless=False,  # headless é mais facilmente detectado
        proxy=proxy_config
    )
    context = browser.new_context(
        user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                   "AppleWebKit/537.36 (KHTML, like Gecko) "
                   "Chrome/131.0.0.0 Safari/537.36"
    )
    page = context.new_page()
    page.goto("https://exemplo-protegido.com")

    # Aguardar o Turnstile resolver automaticamente
    page.wait_for_timeout(5000)

    # Extrair cookies
    cookies = context.cookies()
    cf_clearance = None
    for cookie in cookies:
        if cookie["name"] == "cf_clearance":
            cf_clearance = cookie["value"]
            break

    print(f"cf_clearance: {cf_clearance}")
    browser.close()

Os pontos críticos aqui são:

  • Sessão sticky: O flag -session-abc123 no username garante que o ProxyHat atribua um IP residencial fixo para essa sessão. Todos os requests — do browser e dos requests subsequentes — sairão pelo mesmo IP.
  • Browser real: O Chrome via Playwright envia um JA4 autêntico do BoringSSL, passa pelas probes de WebGL/Canvas com GPU real, e executa o PoW do Turnstile nativamente.
  • Geo-targeting: O flag -country-US seleciona um IP residencial dos EUA, útil se o site restringir conteúdo por geolocalização. Confira os países disponíveis no ProxyHat.

Fase 2: Reusar cf_clearance em Requests Subsequentes

Após obter o cf_clearance, você pode reusá-lo em requests HTTP diretos — desde que use o mesmo IP (mesma sessão sticky) e o mesmo User-Agent:

import requests

# Mesma sessão sticky do ProxyHat
proxy_url = "http://user-session-abc123-country-US:sua_senha@gate.proxyhat.com:8080"
proxies = {"http": proxy_url, "https": proxy_url}

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                  "AppleWebKit/537.36 (KHTML, like Gecko) "
                  "Chrome/131.0.0.0 Safari/537.36",
    "Cookie": f"cf_clearance={cf_clearance}"
}

response = requests.get(
    "https://exemplo-protegido.com/api/dados",
    headers=headers,
    proxies=proxies
)
print(response.status_code)

Atenção: O requests envia um JA4 diferente do Chrome. Se o site valida JA4 em cada request (não apenas no desafio), o request será bloqueado mesmo com o cookie válido. Para sites mais agressivos, considere usar curl_cffi ou tls-client, que imitam o stack TLS do Chrome:

from curl_cffi import requests as cffi_requests

response = cffi_requests.get(
    "https://exemplo-protegido.com/api/dados",
    headers=headers,
    proxies=proxies,
    impersonate="chrome131"  # imita o JA4 do Chrome 131
)
print(response.status_code)

A biblioteca curl_cffi usa uma versão modificada do curl compilada com BoringSSL, produzindo um JA4 idêntico ao do Chrome real. Isso resolve a inconsistência entre User-Agent e TLS fingerprint.

Gerenciando a Validade do Cookie

O cf_clearance expira. Implemente um mecanismo de renovação:

import time

class CfClearanceManager:
    def __init__(self, proxy_session_id, proxy_password):
        self.session_id = proxy_session_id
        self.password = proxy_password
        self.clearance = None
        self.user_agent = None
        self.obtained_at = 0
        self.ttl = 1800  # 30 minutos

    def get_clearance(self):
        if self.clearance and (time.time() - self.obtained_at) < self.ttl:
            return self.clearance, self.user_agent
        self._renew()
        return self.clearance, self.user_agent

    def _renew(self):
        # Executar o fluxo do Playwright aqui
        # ...
        self.obtained_at = time.time()

Para pipelines de alta vazão, você pode manter um pool de sessões sticky, cada uma com seu próprio cf_clearance. O ProxyHat suporta 100 sessões concorrentes por padrão, permitindo paralelismo sem compartilhar IPs. Confira os planos e limites do ProxyHat.

Quando Isso É Apropriado — e Quando Não É

As técnicas descritas neste artigo são apropriadas para:

  • Coleta de dados públicos: Preços de e-commerce, resultados de SERP, dados públicos governamentais — desde que permitido pelos Termos de Serviço.
  • Pentesting autorizado: Testes de segurança em sistemas onde você tem permissão explícita do proprietário.
  • Pesquisa de segurança: Análise de campanhas de phishing, monitoramento de infraestrutura maliciosa, estudos acadêmicos.
  • QA e monitoramento: Verificação automatizada do seu próprio site ou de sites que você administra.

Não é apropriado para:

  • Credential stuffing ou brute-force de senhas.
  • Scraping de dados protegidos por login sem autorização.
  • Criação de contas em massa ou spam.
  • Bypass de rate limits em APIs de terceiros sem permissão.

Sob a CFAA, acessar um sistema "sem autorização" ou "excedendo a autorização concedida" é um crime federal nos EUA. Sob o GDPR, coletar dados pessoais sem base legal pode resultar em multas de até 4% do faturamento global anual. Quando em dúvida, consulte um advogado.

Erros Comuns e Casos de Borda

1. Usar Headless Puro

Chrome em modo --headless=new ainda é detectável por várias probes. O navigator.webdriver retorna true, e o WebGL renderer pode reportar "SwiftShader". Use Playwright com headless=False em um ambiente com display virtual (Xvfb) ou use bibliotecas de stealth como playwright-stealth.

2. Trocar de IP Entre Desafio e Requests

Se você obtém o cf_clearance através de um proxy A e depois faz requests através de um proxy B (mesmo que ambos sejam residenciais), o cookie é rejeitado. A sessão sticky deve ser mantida do início ao fim.

3. Ignorar o User-Agent

O cf_clearance é vinculado ao User-Agent. Se o Playwright usa um UA e o requests usa outro (mesmo que parecido), o cookie é invalidado. Padronize o UA em toda a pipeline.

4. Não Renovar o Cookie a Tempo

Se o cookie expira no meio de um batch de 10.000 requests, você recebe 403 em todos os requests subsequentes até renovar. Implemente renovação proativa (renovar aos 25 minutos se o TTL é 30 minutos) e retry com backoff exponencial.

5. Usar SOCKS5 Quando HTTP É Suficiente

O ProxyHat suporta tanto HTTP (porta 8080) quanto SOCKS5 (porta 1080). Para a maioria dos casos, HTTP é suficiente e mais simples. SOCKS5 é necessário apenas quando você precisa de proxying de conexões não-HTTP ou quando o cliente não suporta proxy HTTP. Para SOCKS5:

socks5://user-session-abc123-country-US:sua_senha@gate.proxyhat.com:1080

Principais Conclusões

O Turnstile não é um CAPTCHA que você "resolve" — é um sistema de score que avalia consistência entre múltiplos sinais independentes. Passar não significa enganar um sinal; significa ser indistinguível de um browser real em todos os quatro: JA4, HTTP/2, fingerprint de browser e IP.

  • Consistência é tudo: User-Agent, JA4, HTTP/2 SETTINGS e fingerprint de browser devem contar a mesma história. Qualquer inconsistência é um sinal de automação.
  • cf_clearance é IP-pinned: Use sessões sticky residenciais do início ao fim da sessão.
  • Browser real > biblioteca HTTP: Para obter o cookie, use um browser real. Para requests subsequentes, use curl_cffi com impersonate se o site valida JA4 em cada request.
  • Proxies residenciais são não-negociáveis: IPs de datacenter têm baixa reputação e invalidam o score de confiança.
  • Renovação proativa: Implemente TTL tracking e renove o cookie antes da expiração.

Para mais detalhes sobre configuração de proxies, consulte a documentação oficial do ProxyHat. Para casos de uso específicos de scraping e rastreamento de SERP, visite nossas páginas de web scraping e SERP tracking.

Pronto para começar?

Acesse mais de 50M de IPs residenciais em mais de 148 países com filtragem por IA.

Ver preçosProxies residenciais
← Voltar ao Blog