Aviso legal: Este artigo destina-se a pesquisa de segurança autorizada, teste de penetração consentido e automação legítima de dados públicos. O acesso não autorizado a sistemas pode violar leis como a Computer Fraud and Abuse Act (CFAA) dos EUA e o GDPR europeu. Não utilize estas técnicas para abuso de credenciais, fraude ou violação de termos de serviço.
Se você já tentou automatizar requisições contra um site protegido pelo Cloudflare Turnstile e recebeu um 403 Forbidden sem nunca ter visto um CAPTCHA visível, você não está sozinho. O Turnstile moderno não mostra quebra-cabeças visuais — ele executa desafios invisíveis que avaliam a integridade do navegador em milissegundos. Os internais do Cloudflare Turnstile combinam prova de trabalho em JavaScript, sondagens de API do navegador, fingerprinting TLS via JA4 e reputação de IP em uma pontuação de confiança que decide, antes mesmo da página carregar, se você é humano ou bot.
Para engenheiros de scraping e pesquisadores de segurança, entender esse mecanismo não é opcional — é a diferença entre uma pipeline de dados que funciona e uma que retorna erros 403 em massa.
Internais do Cloudflare Turnstile: O Que Acontece Nos Bastidores
O Turnstile é um sistema de desafio gerenciado que substitui o antigo reCAPTCHA do Cloudflare. Quando um cliente solicita uma página protegida, o edge do Cloudflare injeta um pequeno payload JavaScript — tipicamente entre 30 KB e 80 KB — que executa uma série de verificações no navegador do visitante. Esse payload é o coração do managed challenge.
O fluxo é aproximadamente o seguinte:
- O cliente faz uma requisição HTTP para a página protegida.
- O edge do Cloudflare responde com um HTML intermediário contendo uma tag
<script>que carrega o turnstile.js (ou equivalente gerenciado). - Esse JavaScript executa uma prova de trabalho (proof-of-work) — um cálculo de hash iterativo (semelhante a hashcash) que força o cliente a gastar ciclos de CPU. O resultado prova que o cliente executou JavaScript real por um tempo mínimo.
- Paralelamente, o script coleta sondagens de API do navegador:
navigator.userAgent,navigator.webdriver,window.chrome, APIs de canvas, WebGL, áudio (AudioContext), permissões, plugins, fontes instaladas e dezenas de outras propriedades. - O resultado é enviado de volta ao edge do Cloudflare, que combina esses sinais com a impressão digital TLS da conexão original e a reputação do IP para calcular uma pontuação de confiança.
- Se a pontuação for alta o suficiente, o Cloudflare emite um cookie
cf_clearancee redireciona o cliente para a página real.
O cookie cf_clearance é o passaporte que permite acessar o conteúdo protegido sem repetir o desafio. Ele tem um TTL configurável (frequentemente 30 minutos a 24 horas, dependendo da configuração do site) e — crucialmente — é vinculado estritamente ao par User-Agent + IP. Se qualquer um dos dois mudar, o cookie é rejeitado e o desafio é reexecutado.
Para mais detalhes técnicos, consulte a documentação oficial do Cloudflare Turnstile.
A Pontuação de Confiança de Quatro Sinais
O Cloudflare Bot Management não confia em um único sinal. A decisão de desafiar ou não um visitante é baseada em uma pontuação composta por pelo menos quatro categorias de sinais. Entender cada uma é fundamental para qualquer engenheiro que precisa passar por esses desafios de forma legítima.
1. Fingerprint TLS — JA4
O JA4 é a evolução do JA3, introduzida pela FoxIO em 2023 e adotada amplamente por WAFs e sistemas anti-bot em 2024-2026. Diferente do JA3, que hasheia as extensões TLS na ordem em que aparecem no ClientHello, o JA4 ordena as extensões alfabeticamente antes de hashear. Isso elimina a variabilidade introduzida por implementações que embaralham a ordem das extensões, tornando o fingerprint mais estável e mais difícil de spoofar.
O JA4 é composto por vários sub-fingerprints:
- JA4: hash do conjunto TLS (versão, cifras suportadas, extensões ordenadas).
- JA4_S: fingerprint das extensões SNI, ALPN e assinaturas.
- JA4_O: fingerprint das extensões originais não ordenadas (para comparação).
Um navegador Chrome real em um sistema Windows produz um JA4 específico e previsível. Uma biblioteca Python requests usando urllib3 produz um JA4 completamente diferente — com um conjunto de cifras menor, extensões ausentes (como GREASE) e ordem distinta. Esse descompasso é a causa número um de bloqueios instantâneos.
Para detalhes técnicos sobre o algoritmo JA4, consulte o repositório oficial do JA4 no GitHub.
2. HTTP/2 SETTINGS Frame
Além do TLS, o Cloudflare inspeciona o frame SETTINGS do HTTP/2. Diferentes clientes HTTP/2 enviam parâmetros distintos: HEADER_TABLE_SIZE, ENABLE_PUSH, MAX_CONCURRENT_STREAMS, INITIAL_WINDOW_SIZE e MAX_FRAME_SIZE. A ordem e os valores desses parâmetros formam um fingerprint HTTP/2 que é quase tão discriminatório quanto o JA4.
Por exemplo, o Chrome envia HEADER_TABLE_SIZE=65536 e INITIAL_WINDOW_SIZE=6291456, enquanto o hyper (Python) envia valores padrão diferentes. O Cloudflare mantém um banco de dados de fingerprints HTTP/2 conhecidos por navegador e versão, e qualquer descompasso entre o User-Agent declarado e o fingerprint HTTP/2 observado é um sinal forte de automação.
3. Fingerprint do Navegador — Canvas, WebGL e Áudio
O JavaScript do Turnstile coleta dezenas de propriedades do navegador. As mais discriminatórias são:
- Canvas fingerprint: renderiza texto e formas em um elemento
<canvas>e hasheia os pixels resultantes. Varia por GPU, driver de vídeo, sistema operacional e versão do navegador. - WebGL fingerprint: consulta
WEBGL_debug_renderer_infopara obter o fornecedor e o nome do renderizador da GPU. - AudioContext fingerprint: processa um sinal de áudio silencioso via OfflineAudioContext e hasheia o resultado. Varia por implementação de ponto flutuante.
- navigator.webdriver: se
true, é uma bandeira vermelha imediata — indica Selenium, Puppeteer ou Playwright sem configuração de stealth.
Um navegador headless não configurado retorna navigator.webdriver === true, canvas fingerprints anômalos (por não ter GPU real) e WebGL com renderer SwiftShader — todos sinais que o Turnstile detecta instantaneamente.
4. Reputação de IP
O Cloudflare mantém um banco de dados de reputação de IP que classifica endereços por risco. Os fatores incluem:
- ASN (Autonomous System Number) — provedores de datacenter conhecidos (AWS, DigitalOcean, OVH) têm reputação baixa por padrão.
- Volume de tráfego e padrões de requisição do ASN.
- Histórico de abuso (spam, ataques, scraping detectado).
- Geolocalização e coerência com o idioma da página.
IPs residenciais de provedores legítimos (Comcast, Deutsche Telekom, Vivo) têm reputação alta por padrão. IPs de datacenter têm reputação baixa — frequentemente classificados como bot likely sem nem executar o desafio.
| Sinal | Peso Aproximado | Detecta |
|---|---|---|
| JA4 (TLS) | Alto | Bibliotecas HTTP não-browser, spoofing de UA |
| HTTP/2 SETTINGS | Médio-Alto | Clientes HTTP/2 não-padronizados |
| Browser fingerprint | Alto | Headless, Selenium, Puppeteer não-stealth |
| Reputação de IP | Alto | Datacenter, VPNs conhecidas, IPs em blacklist |
Por Que Uma Conexão Com User-Agent Chrome Mas JA4 Python É Desafiada Instantaneamente
Este é o erro mais comum que engenheiros de scraping cometem: enviar um header User-Agent: Mozilla/5.0 ... Chrome/120.0 em uma requisição Python requests e esperar que funcione. Não funciona — e a razão é puramente técnica.
O Cloudflare não confia no User-Agent. Ele confia no JA4. Quando uma conexão chega ao edge, o Cloudflare extrai o JA4 do ClientHello TLS antes de ler qualquer header HTTP. Se o JA4 corresponde ao Chrome 120 no Windows, mas o User-Agent diz Chrome 120 no macOS, isso é uma inconsistência. Se o JA4 corresponde ao Python urllib3, mas o User-Agent diz Chrome, isso é uma mentira flagrante.
O resultado é previsível: o Cloudflare emite um desafio managed ou bloqueia diretamente com 403. Não importa se você rotaciona User-Agents a cada requisição — o JA4 não muda com o User-Agent, porque o JA4 é determinado pela biblioteca TLS subjacente, não pelo header HTTP.
Para passar pelo JA4, você precisa de uma stack TLS que produza um fingerprint de navegador real. Isso significa:
- Usar uma biblioteca que suporte cipher suites GREASE (que Python
requestsnão faz por padrão). - Enviar extensões TLS na ordem e quantidade que o Chrome envia.
- Usar HTTP/2 com os mesmos parâmetros SETTINGS do navegador alvo.
Ferramentas como curl-impersonate, tls-client (Go) e bibliotecas como cycletls (Node.js) foram criadas especificamente para resolver esse problema. Elas reimplementam a stack TLS de navegadores específicos para produzir JA4s idênticos.
Por Que Proxies Residenciais Importam: cf_clearance É IP-Pinned
Mesmo que você resolva o desafio do Turnstile e obtenha um cookie cf_clearance, esse cookie é vinculado ao IP que resolveu o desafio. Se a próxima requisição vier de um IP diferente, o cookie é rejeitado.
Isso tem implicações profundas para estratégias de proxy:
- Proxies datacenter rotativos são inúteis para sessões Turnstile. Cada rotação de IP invalida o
cf_clearance, forçando um novo desafio. Se o novo IP também for de datacenter, o desafio pode falhar por reputação baixa. - Proxies residenciais rotativos são melhores, mas ainda problemáticos se rotacionarem a cada requisição. O cookie só funciona se o IP de saída permanecer o mesmo durante toda a sessão.
- Proxies residenciais sticky são a solução correta. Um IP residencial fixo por sessão permite resolver o desafio uma vez e reutilizar o
cf_clearancepara todas as requisições subsequentes dessa sessão.
A reputação do IP também é crítica. Um IP residencial de um provedor legítimo (ASN residencial) tem reputação alta, o que significa que o desafio managed pode ser simplificado ou até pulado em alguns casos. Um IP de datacenter, mesmo com JA4 perfeito, frequentemente recebe um desafio completo ou bloqueio direto.
Consulte nossa lista de localizações de proxy para ver a cobertura geográfica de IPs residenciais disponíveis.
Abordagem Prática: Sessões Residenciais Sticky com ProxyHat
Aqui está uma arquitetura que funciona para automação legítima contra sites protegidos por Turnstile. O princípio é simples: use um navegador real (ou uma ferramenta que produza fingerprints de navegador reais) para resolver o desafio uma vez, capture o cf_clearance, e reutilize esse cookie em requisições subsequentes — sempre pelo mesmo IP residencial.
Passo 1: Configurar Uma Sessão Residencial Sticky no ProxyHat
O ProxyHat suporta sessões sticky via flag no username. O identificador de sessão mantém o mesmo IP de saída por toda a duração da sessão.
# HTTP proxy com sessão sticky
http://user-session-abc123:pass@gate.proxyhat.com:8080
# SOCKS5 proxy com sessão sticky
socks5://user-session-abc123:pass@gate.proxyhat.com:1080
# Sessão sticky com geolocalização (EUA)
http://user-country-US-session-abc123:pass@gate.proxyhat.com:8080
# Sessão sticky com cidade específica (Berlim, Alemanha)
http://user-country-DE-city-berlin-session-abc123:pass@gate.proxyhat.com:8080
O identificador abc123 pode ser qualquer string alfanumérica. Use um identificador único por sessão para garantir que cada sessão tenha seu próprio IP fixo.
Passo 2: Resolver o Desafio com um Navegador Real
Use Playwright ou Puppeteer com o proxy configurado para carregar a página protegida. O navegador real resolve o desafio automaticamente.
from playwright.sync_api import sync_playwright
proxy = {
"server": "http://gate.proxyhat.com:8080",
"username": "user-session-abc123",
"password": "pass"
}
with sync_playwright() as p:
browser = p.chromium.launch(
headless=False, # headless pode ser detectado
proxy=proxy,
args=["--disable-blink-features=AutomationControlled"]
)
context = browser.new_context(
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"
)
page = context.new_page()
page.goto("https://exemplo-protegido.com/pagina")
# Aguarda o Turnstile resolver (timeout: 15s)
page.wait_for_timeout(15000)
# Captura 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()
Nota: rodar em modo headless=False requer um display. Em servidores headless, use xvfb ou configure flags de stealth adequadas. O modo headless puro frequentemente é detectado por navigator.webdriver e outras sondagens.
Passo 3: Reutilizar cf_clearance em Requisições Subsequentes
Após obter o cf_clearance, você pode reutilizá-lo em requisições HTTP subsequentes — desde que use o mesmo IP (mesma sessão sticky) e o mesmo User-Agent.
import requests
proxies = {
"http": "http://user-session-abc123:pass@gate.proxyhat.com:8080",
"https": "http://user-session-abc123:pass@gate.proxyhat.com:8080"
}
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",
"Cookie": f"cf_clearance={cf_clearance}"
}
response = requests.get(
"https://exemplo-protegido.com/api/dados",
headers=headers,
proxies=proxies
)
print(f"Status: {response.status_code}")
print(f"Conteúdo: {response.text[:500]}")
Atenção: Esta abordagem com requests funciona apenas se o site não revalidar o JA4 em cada requisição. Alguns sites protegidos pelo Cloudflare verificam o JA4 em todas as requisições, não apenas no desafio inicial. Nesse caso, você precisará usar uma biblioteca como curl-impersonate ou continuar usando o navegador para todas as requisições.
Passo 4: Renovar cf_clearance Antes da Expiração
O cf_clearance tem um TTL finito. Monitore o tempo de expiração e renove antes que ele expire. Uma estratégia comum é renovar a cada 20-25 minutos se o TTL for de 30 minutos.
import time
class TurnstileSession:
def __init__(self, proxy_session_id, target_url):
self.session_id = proxy_session_id
self.target_url = target_url
self.cf_clearance = None
self.user_agent = None
self.last_renewal = 0
self.renewal_interval = 1200 # 20 minutos
def renew(self):
# Executa o navegador para resolver o desafio
# Atualiza self.cf_clearance, self.user_agent
self.last_renewal = time.time()
def get(self, url):
if time.time() - self.last_renewal > self.renewal_interval:
self.renew()
# Faz a requisição com cf_clearance + proxy sticky
pass
Erros Comuns e Casos de Borda
1. Rotacionar IP Após Obter cf_clearance
O erro mais frequente. Você obtém o cookie com um IP, depois troca o IP da sessão proxy, e o cookie é rejeitado. Solução: use a mesma sessão sticky (-session-abc123) para todo o ciclo de vida do cookie.
2. Usar User-Agent Diferente do Navegador Que Resolveu o Desafio
O cf_clearance é vinculado ao User-Agent + IP. Se o Playwright resolveu o desafio com Chrome 120 no Windows, todas as requisições subsequentes devem usar exatamente esse User-Agent. Mudar de Chrome/120 para Chrome/121 pode invalidar o cookie.
3. Ignorar o JA4 em Requisições Subsequentes
Alguns sites do Cloudflare verificam o JA4 em cada requisição, não apenas no desafio. Se você usa requests (Python) para reutilizar o cf_clearance, o JA4 do Python não corresponde ao JA4 do Chrome que resolveu o desafio. Solução: use curl-impersonate ou tls-client para produzir um JA4 de navegador real.
4. Usar Proxies Datacenter para Resolver o Desafio
IPs de datacenter têm reputação baixa. Mesmo com um navegador perfeito, o Cloudflare pode emitir um desafio mais difícil ou bloquear diretamente. Use sempre proxies residenciais para resolver desafios Turnstile.
5. Não Tratar o Desafio Managed como Assíncrono
O desafio do Turnstile não é síncrono. O JavaScript pode levar de 2 a 15 segundos para resolver a prova de trabalho e coletar os sinais. Se seu script não aguardar tempo suficiente, ele capturará um cf_clearance vazio ou inválido.
Configuração no ProxyHat e Links Internos
O ProxyHat oferece proxies residenciais, móveis e datacenter com suporte a sessões sticky, geolocalização por país e cidade, e rotação sob demanda. Para acessar sites protegidos por Turnstile, recomendamos:
- Proxies residenciais para resolver desafios Turnstile — reputação alta e IPs de provedores legítimos.
- Sessões sticky (
-session-ID) para manter o mesmo IP durante todo o ciclo de vida docf_clearance. - Geolocalização para garantir coerência entre o IP e o idioma da página. Veja localizações disponíveis.
Consulte nossa página de preços para planos de proxies residenciais. Para casos de uso de scraping em geral, veja web scraping e SERP tracking. A documentação técnica completa está em docs.proxyhat.com.
Quando Isso É Apropriado
Nem todo uso de proxies e bypass de Turnstile é legítimo. A linha entre automação legítima e acesso não autorizado é definida por:
- Autorização: você tem permissão explícita do proprietário do site, ou está acessando dados públicos sem autenticação.
- Finalidade: pesquisa de segurança, monitoramento de preços públicos, coleta de dados públicos para análise, QA automatizado de seus próprios sites.
- Respeito a termos de serviço: se o site proíbe explicitamente scraping automático nos seus ToS, consulte um advogado antes de prosseguir. O CFAA dos EUA e o GDPR europeu têm implicações sérias para acesso não autorizado.
- Rate limiting responsável: não sobrecarregue o servidor. Limite a taxa de requisições a um nível razoável (ex: 1-2 requisições por segundo).
Nunca use estas técnicas para: abuso de credenciais, fraude de tickets/sneakers, ataques DDoS, evasão de banimentos, ou qualquer atividade que viole leis locais ou termos de serviço.
Key Takeaways
- O
cf_clearanceé vinculado estritamente a User-Agent + IP. Mudar qualquer um dos dois invalida o cookie.- O JA4 é o sinal mais discriminatório — mais que o User-Agent. Uma conexão Python com UA Chrome é detectada instantaneamente pelo JA4.
- Proxies residenciais sticky são essenciais: reputação alta do IP + IP fixo por sessão = desafio resolvido uma vez, reutilizado por toda a sessão.
- Use um navegador real (Playwright/Puppeteer) para resolver o desafio e capture o
cf_clearancepara reutilização.- O HTTP/2 SETTINGS frame é um fingerprint independente do JA4 — ambos precisam corresponder ao navegador alvo.
- Renove o
cf_clearanceantes da expiração (tipicamente 20-25 min se o TTL for 30 min).- Use apenas para automação legítima e acesso a dados públicos. O CFAA e o GDPR se aplicam.






