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.pluginseWebGLRenderingContext. Bibliotecas como Selenium e Playwright deixam rastros detectáveis nessas APIs. - Timing de eventos: O Turnstile mede o tempo entre
mousemove,keydownesubmit. 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:
- 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.
- Está vinculado ao User-Agent: O User-Agent enviado durante o desafio deve corresponder exatamente ao User-Agent dos requests subsequentes.
- 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,RENDERERe 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_clearanceobtido 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-abc123no 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-USseleciona 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_cfficomimpersonatese 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.






