Introdução: o que você vai aprender neste guia

O Cloudflare Turnstile é aquele pequeno widget com um círculo girando e o texto "Verifying", que aparece cada vez mais no lugar do velho captcha com imagens. Ele está em formulários de cadastro, em carrinhos de lojas online, em landing pages e em áreas de login de serviços. O visitante comum quase nem nota. Mas para o profissional de marketing, o afiliado ou o desenvolvedor que trabalha com proxy móvel e abre dezenas de sites por dia, ele vira um enigma. Por que em um perfil a verificação passa em um segundo e em outro o widget trava, pede para marcar uma caixa ou mostra um código de erro?

Neste guia vamos destrinchar o Cloudflare Turnstile por dois ângulos. Do lado do dono do site — você vai colocar o widget na página com as próprias mãos, configurar a verificação no servidor e aprender a ler as estatísticas. Do lado do visitante — você vai entender exatamente quais sinais o Turnstile coleta, o que ele vê sobre o seu navegador, a sua rede e o seu proxy, e por que ele toma esta ou aquela decisão. Esse conhecimento é útil tanto para quem protege formulários contra bots quanto para quem quer que seus perfis de trabalho pareçam usuários comuns aos olhos da verificação.

Para quem é este guia

  • Para donos de negócio e profissionais de marketing que sofrem com spam em formulários e cadastros falsos que estragam as métricas e consomem orçamento.
  • Para desenvolvedores que precisam integrar o Turnstile em um formulário de forma rápida e sem erros, e validar o token corretamente no servidor.
  • Para afiliados e especialistas em multcontas que trabalham com proxy móvel e querem entender o que o Turnstile enxerga na conexão deles.

O que você precisa saber antes

Não exige conhecimento especial. Basta entender o que é uma página HTML, saber abrir o console do desenvolvedor no navegador e ter pelo menos uma experiência mínima com alguma linguagem no servidor — PHP, Node.js ou Python. Se você não tem servidor, ainda assim vai conseguir fazer boa parte do guia: dá para integrar e testar o widget em uma página local.

Quanto tempo vai levar

O percurso completo leva cerca de uma hora e meia a duas horas. O cadastro e a criação do widget levam de 10 a 15 minutos, a integração na página, 20 minutos, a verificação no servidor, de 30 a 40 minutos, e os testes e o diagnóstico, mais 30 minutos. As partes teóricas podem ser lidas em qualquer ordem e consultadas conforme a necessidade.

Preparação inicial: ferramentas e acessos

Antes de começar, reúna tudo o que vai precisar. Isso evita pausas no meio do processo.

Ferramentas e acessos necessários

  • Conta na Cloudflare. Gratuita. O cadastro é feito com e-mail e leva alguns minutos. Não é obrigatório transferir o domínio para a Cloudflare — o Turnstile funciona em qualquer site, onde quer que ele esteja hospedado.
  • Site ou página de teste. Serve qualquer página HTML com formulário. Para experimentos locais, basta um arquivo no computador aberto por meio de um servidor local simples.
  • Ambiente de servidor. Qualquer hospedagem com PHP, ou Node.js ou Python na sua máquina. É necessário para a segunda metade do guia — a validação do token.
  • Navegador atualizado. Chrome, Firefox, Edge ou Safari em versão atual, com as ferramentas de desenvolvedor abertas.
  • Proxy móvel com troca de IP. Vai ser útil no trecho de diagnóstico, para observar como o widget reage a redes diferentes e à rotação de endereços.

Requisitos de sistema

O Turnstile é leve. O widget funciona em qualquer navegador que suporte JavaScript moderno e carrega o código dele a partir do domínio challenges.cloudflare.com. Se na sua rede ou nas extensões do navegador esse domínio estiver bloqueado, o widget não carrega — leve isso em conta nos testes. Para a verificação no servidor é preciso poder fazer requisições HTTPS de saída.

O que preparar antes de começar

  1. Crie um arquivo de texto para anotações. Nele você vai guardar o site key, o nome do widget, a lista de hostnames e os resultados dos testes.
  2. Abra a página com o formulário que você quer proteger e salve uma cópia com a data marcada. Esta é a sua reserva.
  3. Se você já tem um handler no servidor para o formulário, faça uma cópia dele também. Vamos adicionar o código de validação nele.
  4. Confirme que o seu servidor local ou de produção entrega a página por HTTPS ou via localhost. O Turnstile funciona em HTTP comum, mas em site de produção você vai precisar de HTTPS de qualquer forma.

⚠️ Atenção: A chave secreta do widget não pode ficar no HTML, no JavaScript da página nem em repositório público. Ela vive só no servidor. Se você publicou por engano, reemita a chave imediatamente no painel da Cloudflare — a antiga deixa de funcionar.

Conceitos básicos: como o Cloudflare Turnstile é estruturado

Para os próximos passos ficarem claros, vamos ver os termos principais em linguagem simples.

Termos-chave

  • Widget — o bloco que o visitante vê. Tecnicamente é um iframe carregado do domínio da Cloudflare e embutido na sua página.
  • Site key — o identificador público do widget. Ele entra no HTML e é visível para todos. Com base nele a Cloudflare sabe qual widget renderizar e para quais domínios ele está liberado.
  • Secret key — a chave privada. É com ela que o seu servidor confirma que o token recebido é legítimo. Nunca sai do servidor.
  • Token — a string que o widget emite após a verificação bem-sucedida. Ela é inserida em um campo oculto do formulário e vai para o seu servidor junto com os demais dados.
  • Siteverify — o endpoint da Cloudflare para onde o servidor envia o token junto com a chave secreta e recebe a resposta: sucesso ou não.
  • Modo do widget — a forma de exibição: gerenciado (Managed), não interativo (Non-interactive) ou invisível (Invisible). A diferença está explicada abaixo.
  • Hostname — o domínio em que o widget pode ser usado. Se o domínio não estiver na lista, o widget vai falhar com erro.

O funcionamento em quatro frases

  1. A página carrega o script do Turnstile e o widget dispara silenciosamente uma bateria de verificações no navegador.
  2. A Cloudflare reúne os resultados, avalia tudo junto com os dados da rede e decide: liberar de imediato, mostrar uma caixa de confirmação ou negar.
  3. Em caso de sucesso, o widget gera um token de uso único e o insere no formulário.
  4. O seu servidor recebe o formulário, envia o token ao siteverify e só processa a solicitação em caso de resposta positiva.

O que o Turnstile verifica — panorama geral

Aqui é importante entender o essencial. O Cloudflare Turnstile não avalia "humanidade" por meio de quebra-cabeças com imagens. Ele mede a coerência do ambiente: o quanto navegador, rede e comportamento formam um quadro plausível. Os principais grupos de sinais:

  • Ambiente do navegador. O script executa uma série de pequenas tarefas em JavaScript e checa se o ambiente se comporta como um navegador de verdade: como os objetos da janela são estruturados, como os gráficos são renderizados, se há indícios de automação e se o User-Agent declarado bate com as capacidades reais da engine.
  • Prova de trabalho. O widget pede ao navegador um pequeno cálculo. Para uma pessoa são frações de segundo; para um bot que abre milhares de páginas, é uma carga considerável.
  • Sinais de rede. Reputação do endereço IP e do sistema autônomo de onde vem a requisição, compatibilidade entre as características da rede e o navegador declarado, e histórico de requisições desse endereço em toda a rede da Cloudflare.
  • Tokens de confiança do dispositivo. Em dispositivos Apple e em alguns outros ecossistemas, o Turnstile pode pedir ao sistema operacional uma confirmação de que ali existe um dispositivo real — e a verificação passa sem nenhum cálculo.
  • Comportamento na página. Momento em que o widget aparece, instante do envio do formulário e naturalidade das ações no modo gerenciado.

O que o Turnstile não faz: não coleta dados para perfilamento publicitário, não rastreia o usuário entre sites por meio de cookies de terceiros e nunca mostra quebra-cabeças com imagens. Isso importa tanto do ponto de vista da lei de proteção de dados quanto da conversão — os visitantes não vão embora por causa de um captcha irritante.

Os três modos do widget

  • Managed — o modo padrão. O widget fica visível, gira o indicador e, em caso de dúvida, mostra uma caixa para clicar. Serve para a maioria dos formulários.
  • Non-interactive — o widget fica visível, mas nunca exige ação. Ou passa sozinho, ou retorna erro. Bom para páginas em que cliques extras não são aceitáveis.
  • Invisible — o widget nem é renderizado. A verificação acontece em segundo plano. Prático para botões e formulários em que você não quer mexer no layout, mas exige tratamento cuidadoso de erros.

Passo 1: Entenda o que exatamente o Turnstile vê do seu lado

Objetivo desta etapa: antes de configurar qualquer coisa, você precisa entender quais dados sobre o seu ambiente o widget recebe. Essa é a base do diagnóstico nos próximos passos e do trabalho consciente com proxy móvel.

Como observar o funcionamento do widget com os próprios olhos

  1. Abra qualquer site que use o Cloudflare Turnstile. Esses widgets são fáceis de reconhecer pelo logotipo da Cloudflare no canto inferior direito do bloco e pelos links "Privacy" e "Terms".
  2. Aperte F12 ou clique com o botão direito — "Inspecionar" — para abrir as ferramentas de desenvolvedor.
  3. Vá até a aba "Network" (Rede) e recarregue a página.
  4. No filtro, digite challenges.cloudflare.com. Você verá várias requisições: o carregamento do api.js, o carregamento do iframe do widget e uma ou mais requisições POST — é aí que vão os resultados das verificações.
  5. Abra a aba "Elements" (Elementos) e localize o bloco com a classe cf-turnstile. Dentro dele, após a verificação bem-sucedida, vai aparecer um campo input oculto com o nome cf-turnstile-response e uma string longa como valor. Esse é o token.

Dica: O conteúdo das requisições POST é criptografado e ofuscado, não adianta tentar lê-lo. Olhe para outra coisa: quantas requisições saíram, quanto tempo a verificação levou e se o status do widget virou "Success". Esse é o seu indicador externo de confiança.

O que o Turnstile vê sobre o seu navegador

O widget executa JavaScript direto na sua janela, então ele tem acesso a tudo o que qualquer script da página tem: versão da engine, APIs instaladas, dimensões da tela, fuso horário, idiomas de interface, particularidades da renderização de gráficos e fontes, e o comportamento de funções que costumam ser sobrescritas em navegadores automatizados. Ele não lê os seus arquivos nem entra em outras abas. Mas percebe muito bem quando o navegador declara uma coisa e faz outra. Por exemplo, o User-Agent diz "Chrome no Android", mas o ambiente não tem eventos de toque e tem APIs que não existem em celulares.

O que o Turnstile vê sobre a sua rede

Aqui começa a parte mais interessante para quem trabalha com proxy móvel. Todas as requisições do widget vão para os servidores da Cloudflare, ou seja, a Cloudflare vê o seu endereço IP externo, o sistema autônomo dele (isto é, a operadora), o país, além de características de baixo nível da conexão — como exatamente o seu cliente estabelece a conexão segura. Essas características variam entre navegadores, e a Cloudflare as compara com o User-Agent declarado.

As operadoras móveis distribuem endereços de grandes pools compartilhados; centenas de assinantes reais usam o mesmo endereço ao mesmo tempo. Por isso esses endereços têm, por si sós, reputação neutra ou boa — bloqueá-los significaria bloquear pessoas reais. Mas a reputação é só um dos sinais. Se de um endereço móvel chega um navegador cuja impressão digital de rede é de um script de desktop, com fuso horário de outro continente e sinais de automação, o quadro deixa de fazer sentido e o widget muda para o modo interativo ou nega.

O que o Turnstile vê sobre o seu comportamento

No modo gerenciado, o widget presta atenção em quão rápido o formulário é enviado depois do carregamento, se o usuário interagiu com a página e se o clique na caixa parece natural. Nos modos invisível e não interativo, o componente comportamental é mínimo — a decisão se baseia em ambiente e rede.

✅ Verificação: Nesta etapa você deve conseguir abrir a aba Network, filtrar as requisições para challenges.cloudflare.com, ver o campo oculto cf-turnstile-response e explicar com suas palavras os três grupos de sinais: navegador, rede e comportamento. Se conseguiu, siga para a criação do seu widget.

Problemas possíveis

  • Não aparece nenhuma requisição para challenges.cloudflare.com. Provavelmente o domínio está sendo bloqueado por uma extensão do navegador ou por um filtro corporativo. Desative os bloqueadores durante os testes.
  • O widget fica travado no estado de verificação para sempre. Confira a data e a hora do sistema no computador: uma diferença grande em relação ao horário real quebra a verificação.

Passo 2: Crie o widget no painel da Cloudflare

Objetivo desta etapa: obter o par de chaves — site key e secret key — e configurar corretamente a lista de domínios e o modo de funcionamento.

  1. Abra o painel da Cloudflare e entre na sua conta. Se não tiver conta, clique em "Sign up", informe e-mail e senha e confirme o e-mail.
  2. No menu da esquerda, encontre o item Turnstile. Se você tem várias contas, escolha a certa primeiro na página inicial.
  3. Clique no botão azul Add widget (Adicionar widget).
  4. No campo Widget name, digite um nome claro, por exemplo "Landing de leads — principal". O nome só você vê, mas com uma dezena de widgets ele salva você da confusão.
  5. No bloco Hostname management, clique em Add hostnames e informe os domínios em que o widget vai funcionar. Digite sem protocolo e sem caminho: exemplo.com.br, e não https://exemplo.com.br/formulario. Subdomínios devem ser adicionados separadamente, ou informe o domínio raiz — assim os subdomínios também ficam liberados.
  6. Para testes locais, adicione localhost à lista. Isso é oficialmente suportado e não atrapalha a produção.
  7. No bloco Widget Mode, escolha o modo. Na primeira vez, use Managed — assim você vê todos os estados do widget, inclusive o interativo.
  8. Deixe a opção Pre-clearance desligada por enquanto. Ela só é necessária se o site estiver atrás do proxy da Cloudflare, e vamos falar dela na seção avançada.
  9. Clique em Create.
  10. Na tela seguinte você verá dois campos: Site Key e Secret Key. Copie os dois para o arquivo de anotações. A chave secreta pode ser consultada depois nas configurações do widget, mas é mais prático salvar na hora.

Dica: Crie logo dois widgets — um para o domínio de produção, outro com o nome "Teste" e o hostname localhost. Assim você experimenta modos e configurações sem mexer nas estatísticas do widget de trabalho.

Como é um resultado correto

Na lista do Turnstile vai aparecer um cartão com o nome do widget, o modo dele e a lista de hostnames. O site key começa com "0x" e tem cerca de 24 caracteres; o secret key também começa com "0x", mas é mais longo. Se a chave parecer diferente, você provavelmente copiou o campo errado.

✅ Verificação: No seu arquivo de anotações estão registrados o site key, o secret key, o nome do widget, a lista de hostnames e o modo escolhido. No painel da Cloudflare o widget aparece na lista com status ativo.

Problemas possíveis

  • O botão Create está inativo. Nenhum hostname foi adicionado ou foi digitado com erro (protocolo, barra, espaço).
  • Não encontro o item Turnstile no menu. Você está dentro das configurações de um domínio específico. Volte para o nível da conta — o Turnstile fica lá, não dentro de uma zona.

Passo 3: Integre o widget na página com o formulário

Objetivo desta etapa: o widget aparece na sua página, passa pela verificação e insere o token no formulário.

Inclua o script

  1. Abra o arquivo HTML da página com o formulário no editor.
  2. Dentro da tag head ou antes do fechamento da tag body, adicione a linha de inclusão do script:
<script src='https://challenges.cloudflare.com/turnstile/v0/api.js' async defer></script>

Os atributos async e defer fazem com que a página não espere o carregamento do script. O widget aparece um pouco depois, mas o usuário não sente atraso no carregamento do conteúdo.

Posicione o contêiner do widget

  1. Localize o formulário que você está protegendo. Normalmente é uma tag form com campos de nome, e-mail e telefone.
  2. Logo antes do botão de envio, insira um bloco vazio com a classe cf-turnstile e o seu site key:
<form action='/submit.php' method='POST'> <input type='text' name='name' placeholder='Seu nome'> <input type='email' name='email' placeholder='E-mail'> <div class='cf-turnstile' data-sitekey='SEU_SITE_KEY' data-theme='light'></div> <button type='submit'>Enviar</button> </form>
  1. Substitua SEU_SITE_KEY pela chave do arquivo de anotações. A chave secreta não pode entrar aqui.
  2. Salve o arquivo e abra a página no navegador via localhost.

O que você deve ver

Um ou dois segundos após o carregamento, no lugar do bloco aparece um widget de cerca de 300 por 65 pixels. Primeiro ele mostra o indicador de carregamento e o texto "Verifying"; depois, um check verde e "Success". Se a Cloudflare decidir reverificar o ambiente, aparece uma caixa com o texto "Verify you are human" — clique nela e, em instantes, o widget mostra sucesso.

Abra as ferramentas de desenvolvedor, aba Elements, e expanda o bloco cf-turnstile. Dentro dele apareceu um campo input oculto com o nome cf-turnstile-response. O valor dele é um token longo. É ele que vai para o servidor quando o formulário for enviado.

Atributos úteis do contêiner

  • data-theme — light, dark ou auto. O auto se adapta ao tema do sistema do usuário.
  • data-size — normal, compact ou flexible. O flexible estica o widget pela largura do contêiner — prático para layout mobile.
  • data-language — código do idioma, por exemplo pt-BR. Por padrão o widget usa o idioma do navegador.
  • data-action — um rótulo curto, por exemplo login ou checkout. Ele volta na resposta do siteverify e ajuda a diferenciar formulários nas estatísticas.
  • data-callback — nome da função JavaScript chamada após o sucesso. O token chega nela.
  • data-error-callback — função que recebe o código de erro, caso algo dê errado.
  • data-refresh-expired — o que fazer quando o token expira: auto pede um novo sozinho, manual mostra um botão de atualização e never não faz nada.

Dica: Já adicione o data-error-callback e imprima o código de erro no console. Os códigos do Turnstile são informativos: a série 110xxx indica problemas com a chave ou o domínio, a 300xxx, falha de execução no navegador, e a 600xxx, que a verificação não foi aprovada. Sem isso, você vai ficar adivinhando por que o widget está calado.

Caminho alternativo: renderização explícita via JavaScript

Se você trabalha em um framework ou quer controlar o momento em que o widget aparece, troque a renderização implícita pela explícita. Adicione o parâmetro render=explicit ao endereço do script e chame turnstile.render com os parâmetros desejados:

turnstile.render('#my-widget', { sitekey: 'SEU_SITE_KEY', theme: 'auto', action: 'signup', callback: function(token) { console.log('Token recebido', token.length); } });

Essa forma permite redesenhar o widget após um erro com o método turnstile.reset e obter o token atual com turnstile.getResponse.

✅ Verificação: O widget aparece na página, mostra "Success", o campo cf-turnstile-response com o token existe no DOM e não há erros no console. Tente recarregar a página três ou quatro vezes — a cada vez deve surgir um token novo.

Problemas possíveis

  • O widget mostra erro 110200. O domínio de onde a página foi aberta não está nos hostnames do widget. Verifique se você abriu via localhost, e não via 127.0.0.1 ou file:// — são hostnames diferentes.
  • O widget não aparece e o console está vazio. O script não carregou. Confira se o endereço do script está sem erros de digitação e se não há bloqueadores ativos.
  • O widget quebra o layout. Use data-size='flexible' ou envolva o bloco em um contêiner com a largura desejada.

Passo 4: Configure a verificação do token no servidor

Objetivo desta etapa: o servidor rejeita qualquer envio de formulário sem um token válido. Esse é o passo mais importante — sem ele o widget não passa de enfeite, porque o bot pode enviar um POST direto para o handler, sem passar pela página.

Como é a requisição ao siteverify

O seu servidor faz um POST para https://challenges.cloudflare.com/turnstile/v0/siteverify com os campos:

  • secret — a sua chave secreta;
  • response — o token do campo cf-turnstile-response;
  • remoteip — o IP do visitante, opcional, mas útil;
  • idempotency_key — identificador único opcional da requisição, do qual falaremos na seção avançada.

A resposta vem em JSON. Os campos principais:

{ "success": true, "challenge_ts": "2026-03-14T10:22:31.000Z", "hostname": "exemplo.com.br", "error-codes": [], "action": "signup", "cdata": "" }

O token dura 300 segundos e é de uso único. Validar o mesmo token de novo retorna o erro timeout-or-duplicate.

Exemplo em PHP

  1. Abra o arquivo que processa o formulário, por exemplo submit.php.
  2. Logo no início, antes de qualquer manipulação dos dados do formulário, adicione o bloco de verificação:
<?php $token = $_POST['cf-turnstile-response'] ?? ''; if ($token === '') { http_response_code(400); exit('Verificação não aprovada: sem token'); } $data = [ 'secret' => getenv('TURNSTILE_SECRET'), 'response' => $token, 'remoteip' => $_SERVER['REMOTE_ADDR'] ]; $ch = curl_init('https://challenges.cloudflare.com/turnstile/v0/siteverify'); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 10); $raw = curl_exec($ch); curl_close($ch); $result = json_decode($raw, true); if (empty($result['success'])) { http_response_code(403); exit('Verificação não aprovada: ' . implode(',', $result['error-codes'] ?? ['no-response'])); } 

Sobre o autor

Roman Melnikov

Roman Melnikov

Technical Writer and System Administrator

Experiência profissional: Technical writer and DevOps engineer with 9 years of experience. Created over 50 detailed guides on system configuration and administration. His instructions helped thousands of professionals successfully solve technical tasks. Popular author on Habr and YouTube.
Formação: Bauman Moscow State Technical University. Information Systems and Technologies
Especialização:
Technical Documentation DevOps System Administration Linux Docker and Kubernetes CI/CD Infrastructure Automation Cloud Technologies System Monitoring Bash and Python Scripting

Compartilhe este artigo: