Introducción: qué obtendrás con esta guía

Cloudflare Turnstile es ese pequeño widget con el círculo girando y el texto «Verifying» que cada vez aparece más en lugar del clásico captcha con imágenes. Está en formularios de registro, en carritos de tiendas online, en landings y en paneles de usuario de distintos servicios. Un visitante común casi ni lo nota. Pero para un marketero, un afiliado o un desarrollador que trabaja con proxies móviles y abre decenas de sitios al día, se vuelve un enigma. ¿Por qué en un perfil la verificación pasa en un segundo y en otro el widget se queda pensando, pide marcar una casilla o lanza un código de error?

En esta guía analizaremos Cloudflare Turnstile desde dos lados. Del lado del dueño del sitio: integrarás el widget en una página con tus propias manos, configurarás la verificación del servidor y aprenderás a leer las estadísticas. Del lado del visitante: entenderás qué señales recopila exactamente Turnstile, qué ve sobre tu navegador, tu red y tu proxy, y por qué toma una decisión u otra. Este conocimiento es igual de útil tanto para quien protege sus formularios de los bots como para quien quiere que sus perfiles de trabajo se vean ante la verificación como usuarios comunes.

Para quién es esta guía

  • Para dueños de negocios y marketeros que ven cómo las solicitudes spam y los registros falsos les arruinan las estadísticas y les consumen el presupuesto.
  • Para desarrolladores que necesitan integrar Turnstile en un formulario de forma rápida y sin errores, y verificar correctamente el token en el servidor.
  • Para afiliados y especialistas en multacuentas que trabajan con proxies móviles y quieren entender qué ve Turnstile cuando se conectan.

Qué conviene saber de antemano

No se requieren conocimientos especiales. Basta con entender qué es una página HTML, saber abrir la consola de desarrollador en el navegador y tener al menos una experiencia mínima con algún lenguaje del lado del servidor: PHP, Node.js, Python. Si no tienes parte de servidor, igual podrás recorrer la mayor parte de la guía: el widget se puede integrar y probar en una página local.

Cuánto tiempo tomará

El recorrido completo: alrededor de una hora y media a dos horas. El registro y la creación del widget toman 10-15 minutos, la integración en la página 20 minutos, la verificación del servidor 30-40 minutos, y las pruebas y el diagnóstico otros 30 minutos. Las secciones teóricas se pueden leer en cualquier orden y retomar cuando lo necesites.

Preparación previa: herramientas y accesos

Antes de empezar, reúne todo lo necesario. Así evitarás pausas a mitad del proceso.

Herramientas y accesos necesarios

  • Cuenta de Cloudflare. Gratuita. Se registra con un correo electrónico en un par de minutos. No es obligatorio migrar el dominio a Cloudflare: Turnstile funciona en cualquier sitio, donde sea que esté alojado.
  • Sitio o página de prueba. Sirve cualquier página HTML con un formulario. Para experimentos locales basta con un archivo en tu computadora abierto a través de un servidor local simple.
  • Entorno de servidor. Cualquier hosting con PHP, o Node.js o Python en tu máquina. Se necesita para la segunda mitad de la guía: la verificación del token.
  • Navegador moderno. Chrome, Firefox, Edge o Safari en versión actual con las herramientas de desarrollador abiertas.
  • Proxy móvil con capacidad de cambiar IP. Hará falta en la sección de diagnóstico para ver cómo reacciona el widget ante distintas redes y la rotación de direcciones.

Requisitos del sistema

Turnstile no es exigente. El widget funciona en cualquier navegador que soporte JavaScript moderno y carga su código desde el dominio challenges.cloudflare.com. Si en tu red o en las extensiones del navegador ese dominio está bloqueado, el widget no cargará: tenlo en cuenta al hacer las pruebas. Para la verificación del servidor se necesita la capacidad de hacer solicitudes HTTPS salientes.

Qué preparar antes de empezar

  1. Crea un archivo de texto para notas. Ahí anotarás el site key, el nombre del widget, la lista de hostnames y los resultados de las pruebas.
  2. Abre la página con el formulario que quieres proteger y guarda una copia con la fecha marcada. Ese es tu respaldo.
  3. Si tienes un procesador del formulario en el servidor, guarda también una copia de él. Le agregaremos el código de verificación.
  4. Comprueba que tu servidor local o de producción entregue la página por HTTPS o a través de localhost. Turnstile funciona también por HTTP normal, pero en el sitio de producción igual necesitas HTTPS.

⚠️ Atención: La clave secreta del widget no se puede guardar en el HTML, en el JavaScript de la página ni en un repositorio público. Vive solo en el servidor. Si por accidente la publicaste, reemite la clave de inmediato en el panel de Cloudflare: la antigua dejará de funcionar.

Conceptos básicos: cómo está construido Cloudflare Turnstile

Para que los siguientes pasos sean comprensibles, repasemos los términos clave en lenguaje simple.

Términos clave

  • Widget — el bloque que ve el visitante. Técnicamente es un iframe cargado desde el dominio de Cloudflare e integrado en tu página.
  • Site key — el identificador público del widget. Se inserta en el HTML y es visible para todos. Con él, Cloudflare entiende qué widget dibujar y para qué dominios está permitido.
  • Secret key — la clave privada. Con ella tu servidor confirma que el token recibido es auténtico. Nunca sale del servidor.
  • Token — la cadena que el widget entrega tras una verificación exitosa. Se coloca en un campo oculto del formulario y viaja a tu servidor junto con el resto de los datos.
  • Siteverify — el endpoint de Cloudflare al que el servidor envía el token junto con la clave secreta y recibe la respuesta: éxito o no.
  • Modo del widget — la forma de mostrarse: gestionado (Managed), no interactivo (Non-interactive) o invisible (Invisible). La diferencia se describe más abajo.
  • Hostname — el dominio en el que se permite usar el widget. Si el dominio no está indicado, el widget se negará a funcionar con error.

El principio de funcionamiento en cuatro frases

  1. La página carga el script de Turnstile y el widget lanza silenciosamente una serie de verificaciones en el navegador.
  2. Cloudflare recopila los resultados, los evalúa junto con los datos de la red y decide: dejar pasar de inmediato, mostrar una casilla para confirmar o rechazar.
  3. Si tiene éxito, el widget genera un token de un solo uso y lo inserta en el formulario.
  4. Tu servidor recibe el formulario, envía el token a siteverify y solo con una respuesta positiva procesa la solicitud.

Qué verifica Turnstile — panorama general

Aquí es importante entender lo principal. Cloudflare Turnstile no evalúa la «humanidad» a través de acertijos con imágenes. Evalúa la coherencia del entorno: hasta qué punto el navegador, la red y el comportamiento encajan en una imagen verosímil. Los principales grupos de señales son:

  • Entorno del navegador. El script ejecuta una serie de pequeñas tareas JavaScript y comprueba que el entorno se comporta como un navegador real: cómo están construidos los objetos de la ventana, cómo se renderiza la gráfica, si hay indicios de automatización, si el User-Agent declarado coincide con las capacidades reales del motor.
  • Prueba de trabajo. El widget pide al navegador que haga un pequeño cálculo. Para una persona son fracciones de segundo; para un bot que abre miles de páginas, es una carga notable.
  • Señales de red. La reputación de la dirección IP y del sistema autónomo desde el que llega la solicitud, la correspondencia entre las características de red y el navegador declarado, el historial de solicitudes desde esa dirección en toda la red de Cloudflare.
  • Tokens de confianza del dispositivo. En dispositivos Apple y en algunos otros ecosistemas, Turnstile puede pedirle al sistema operativo que confirme que se trata de un dispositivo real, y entonces la verificación pasa sin ningún cálculo.
  • Comportamiento en la página. El momento en que aparece el widget, el momento en que se envía el formulario, la naturalidad de las acciones en el modo gestionado.

Lo que Turnstile no hace: no recopila datos para perfilado publicitario, no rastrea al usuario entre sitios mediante cookies de terceros y nunca muestra rompecabezas con imágenes. Esto es importante tanto desde el punto de vista de la ley de protección de datos personales como desde el punto de vista de la conversión: los visitantes no se van por un captcha molesto.

Tres modos del widget

  • Managed — el modo por defecto. El widget es visible, gira el indicador y, si duda, muestra una casilla que hay que marcar. Sirve para la mayoría de los formularios.
  • Non-interactive — el widget es visible, pero nunca exige acciones. O pasa solo, o lanza un error. Es bueno para páginas donde no se pueden permitir clics adicionales.
  • Invisible — el widget no se dibuja en absoluto. La verificación ocurre en segundo plano. Es cómodo para botones y formularios donde no quieres cambiar el diseño, pero exige un manejo cuidadoso de los errores.

Paso 1: Entendemos qué ve exactamente Turnstile de tu lado

Objetivo de esta etapa: antes de configurar nada, debes entender qué datos sobre tu entorno recibe el widget. Esta es la base para el diagnóstico en los siguientes pasos y para trabajar conscientemente con proxies móviles.

Cómo ver el funcionamiento del widget con tus propios ojos

  1. Abre cualquier sitio donde esté Cloudflare Turnstile. Estos widgets se reconocen fácilmente por el logotipo de Cloudflare en la esquina inferior derecha del bloque y los enlaces «Privacy» y «Terms».
  2. Presiona F12 o haz clic derecho — «Inspeccionar» para abrir las herramientas de desarrollador.
  3. Ve a la pestaña «Network» (Red) y recarga la página.
  4. En la barra de filtros escribe challenges.cloudflare.com. Verás varias solicitudes: la carga de api.js, la carga del propio iframe del widget y una o varias solicitudes POST: eso es el envío de los resultados de las verificaciones.
  5. Abre la pestaña «Elements» (Elementos) y busca el bloque con la clase cf-turnstile. Dentro de él, tras una verificación exitosa, aparecerá un campo input oculto con el nombre cf-turnstile-response y una cadena larga como valor. Ese es el token.

Consejo: El contenido de las solicitudes POST está cifrado y ofuscado, leerlo no sirve de nada. Fíjate en otra cosa: cuántas solicitudes salieron, cuánto tiempo tomó la verificación y si el estado del widget cambió a «Success». Ese es tu indicador externo de confianza.

Qué ve Turnstile sobre tu navegador

El widget ejecuta JavaScript directamente en tu ventana, por lo que tiene acceso a todo lo que tiene cualquier script de la página: la versión del motor, las API instaladas, el tamaño de la pantalla, la zona horaria, los idiomas de la interfaz, las particularidades del renderizado de gráficos y fuentes, el comportamiento de funciones que en navegadores automatizados suelen estar sobrescritas. No lee tus archivos ni se mete en otras pestañas. Pero detecta perfectamente cuando el navegador declara una cosa y hace otra. Por ejemplo, el User-Agent dice «Chrome en Android», pero en el entorno no hay eventos táctiles y sí hay API que no existen en dispositivos móviles.

Qué ve Turnstile sobre tu red

Aquí empieza lo más interesante para quienes trabajan con proxies móviles. Todas las solicitudes del widget van a los servidores de Cloudflare, y por lo tanto Cloudflare ve tu dirección IP externa, su sistema autónomo (es decir, el operador), el país, y también las características de bajo nivel de la conexión: cómo exactamente tu cliente establece la conexión segura. Estas características son distintas en cada navegador, y Cloudflare las compara con el User-Agent declarado.

Los operadores móviles entregan direcciones de grandes pools compartidos; detrás de una misma dirección hay simultáneamente cientos de abonados reales. Por eso esas direcciones de por sí tienen una reputación neutral o buena: bloquearlas significaría bloquear a personas reales. Pero la reputación es solo una de las señales. Si desde una dirección móvil llega un navegador cuyo huella de red es la de un script de escritorio, con zona horaria de otro continente y señales de automatización, la imagen deja de cuadrar y el widget pasa al modo interactivo o rechaza.

Qué ve Turnstile sobre tu comportamiento

En el modo gestionado, el widget presta atención a qué tan rápido se envía el formulario tras la carga, si el usuario interactuó con la página, si el clic en la casilla se ve natural. En los modos invisible y no interactivo, el componente conductual es mínimo: la decisión se toma según el entorno y la red.

✅ Verificación: En esta etapa debes poder abrir la pestaña Network, filtrar las solicitudes hacia challenges.cloudflare.com, ver el campo oculto cf-turnstile-response y explicar con tus palabras los tres grupos de señales: navegador, red, comportamiento. Si lo lograste, pasa a crear tu propio widget.

Posibles problemas

  • No hay ninguna solicitud hacia challenges.cloudflare.com. Lo más probable es que una extensión del navegador o un filtro corporativo esté bloqueando el dominio. Desactiva los bloqueadores durante las pruebas.
  • El widget se queda en estado de verificación infinitamente. Revisa la hora del sistema en tu computadora: una gran desviación respecto a la hora real rompe la verificación.

Paso 2: Creamos el widget en el panel de Cloudflare

Objetivo de esta etapa: obtener un par de claves —site key y secret key— y configurar correctamente la lista de dominios y el modo de funcionamiento.

  1. Abre el panel de control de Cloudflare e inicia sesión en tu cuenta. Si no tienes cuenta, haz clic en «Sign up», ingresa tu correo y contraseña, y confirma el mensaje.
  2. En el menú izquierdo busca la opción Turnstile. Si tienes varias cuentas, primero selecciona la correcta en la página principal.
  3. Haz clic en el botón azul Add widget (Agregar widget).
  4. En el campo Widget name escribe un nombre claro, por ejemplo «Landing solicitudes — principal». El nombre solo lo ves tú, pero con una decena de widgets te salvará de confusiones.
  5. En el bloque Hostname management haz clic en Add hostnames e ingresa los dominios donde funcionará el widget. Escríbelos sin protocolo y sin ruta: ejemplo.com, no https://ejemplo.com/formulario. Los subdominios hay que agregarlos por separado o indicar el dominio raíz, para que los subdominios también queden permitidos.
  6. Para las pruebas locales agrega a la lista localhost. Esto está oficialmente soportado y no interfiere con el uso en producción.
  7. En el bloque Widget Mode elige el modo. Para la primera vez toma Managed: así verás todos los estados del widget, incluido el interactivo.
  8. La opción Pre-clearance déjala desactivada por ahora. Solo se necesita si el sitio está proxeado a través de Cloudflare, y hablaremos de ella en la sección avanzada.
  9. Haz clic en Create.
  10. En la siguiente pantalla verás dos campos: Site Key y Secret Key. Copia ambos en tu archivo de notas. La clave secreta se puede consultar después en la configuración del widget, pero es más cómodo guardarla de inmediato.

Consejo: Crea de una vez dos widgets: uno para el dominio de producción y otro con el nombre «Prueba» y el hostname localhost. Así experimentarás con modos y configuraciones sin tocar las estadísticas del widget de trabajo.

Cómo se ve el resultado correcto

En la lista de Turnstile aparecerá una tarjeta con el nombre del widget, su modo y la lista de hostnames. El site key empieza con «0x» y tiene unos 24 caracteres; el secret key también empieza con «0x», pero es más largo. Si la clave se ve distinta, lo más probable es que hayas copiado el campo equivocado.

✅ Verificación: En tu archivo de notas están anotados el site key, el secret key, el nombre del widget, la lista de hostnames y el modo elegido. En el panel de Cloudflare el widget aparece en la lista con estado activo.

Posibles problemas

  • El botón Create está inactivo. No se agregó ningún hostname o se ingresó con error (protocolo, barra, espacio).
  • No encuentras la opción Turnstile en el menú. Estás dentro de la configuración de un dominio específico. Vuelve al nivel de la cuenta: Turnstile vive ahí, no dentro de la zona.

Paso 3: Integramos el widget en la página con el formulario

Objetivo de esta etapa: el widget se muestra en tu página, pasa la verificación e inserta el token en el formulario.

Conectamos el script

  1. Abre el archivo HTML de la página con el formulario en tu editor.
  2. Dentro de la etiqueta head o antes de la etiqueta body de cierre agrega la línea de conexión del script:
<script src='https://challenges.cloudflare.com/turnstile/v0/api.js' async defer></script>

Los atributos async y defer permiten que la página no espere la carga del script. El widget aparecerá un poco más tarde, pero el usuario no verá demoras en la carga del contenido.

Colocamos el contenedor del widget

  1. Encuentra el formulario que vas a proteger. Normalmente es una etiqueta form con campos de nombre, correo y teléfono.
  2. Justo antes del botón de envío inserta un bloque vacío con la clase cf-turnstile y tu site key:
<form action='/submit.php' method='POST'> <input type='text' name='name' placeholder='Tu nombre'> <input type='email' name='email' placeholder='Correo'> <div class='cf-turnstile' data-sitekey='TU_SITE_KEY' data-theme='light'></div> <button type='submit'>Enviar</button> </form>
  1. Reemplaza TU_SITE_KEY por la clave de tu archivo de notas. La clave secreta no se puede insertar aquí.
  2. Guarda el archivo y abre la página en el navegador a través de localhost.

Qué deberías ver

Uno o dos segundos después de la carga, en el lugar del bloque aparecerá un widget de aproximadamente 300 por 65 píxeles. Primero muestra el indicador de carga y el texto «Verifying», luego una palomita verde y «Success». Si Cloudflare decidió revalidar el entorno, aparecerá una casilla con el texto «Verify you are human»: márcala y en un instante el widget mostrará éxito.

Abre las herramientas de desarrollador, la pestaña Elements, y despliega el bloque cf-turnstile. Dentro apareció un campo input oculto con el nombre cf-turnstile-response. Su valor es un token largo. Ese es el que llegará al servidor al enviar el formulario.

Atributos útiles del contenedor

  • data-theme — light, dark o auto. Auto se adapta al tema del sistema del usuario.
  • data-size — normal, compact o flexible. Flexible estira el widget al ancho del contenedor: útil para maquetación móvil.
  • data-language — código de idioma, por ejemplo es. Por defecto el widget toma el idioma del navegador.
  • data-action — una etiqueta corta, por ejemplo login o checkout. Volverá en la respuesta de siteverify y ayudará a distinguir formularios en las estadísticas.
  • data-callback — el nombre de la función JavaScript que se llamará tras el éxito. En ella llegará el token.
  • data-error-callback — la función que recibirá el código de error si algo salió mal.
  • data-refresh-expired — qué hacer cuando el token caduca: auto lo vuelve a solicitar solo, manual muestra un botón de actualización, never no hace nada.

Consejo: Agrega de inmediato data-error-callback e imprime el código de error en la consola. Los códigos de Turnstile son informativos: la serie 110xxx indica problemas con la clave o el dominio, la 300xxx un fallo de ejecución en el navegador, la 600xxx que la verificación no se superó. Sin esto estarás adivinando por qué el widget calla.

Camino alternativo: renderizado explícito mediante JavaScript

Si trabajas con un framework o quieres controlar el momento en que aparece el widget, reemplaza el renderizado implícito por el explícito. Agrega a la dirección del script el parámetro render=explicit y llama a turnstile.render con los parámetros necesarios:

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

Esta forma permite redibujar el widget tras un error con el método turnstile.reset y obtener el token actual con el método turnstile.getResponse.

✅ Verificación: El widget se muestra en la página, muestra «Success», en el DOM existe el campo cf-turnstile-response con el token, en la consola no hay errores. Intenta recargar la página tres o cuatro veces: cada vez debe aparecer un token nuevo.

Posibles problemas

  • El widget muestra el error 110200. El dominio desde el que se abre la página no está agregado a los hostnames del widget. Comprueba que lo abres exactamente por localhost y no por 127.0.0.1 o file://: son hostnames distintos.
  • El widget no aparece, la consola está vacía. El script no cargó. Revisa la dirección del script en busca de errores de escritura y de bloqueadores.
  • El widget rompe la maquetación. Usa data-size='flexible' o envuelve el bloque en un contenedor del ancho necesario.

Paso 4: Configuramos la verificación del token en el servidor

Objetivo de esta etapa: el servidor rechaza cualquier envío de formulario sin un token válido. Este es el paso más importante: sin él, el widget queda solo como adorno, porque un bot puede enviar la solicitud POST directamente, saltándose la página.

Cómo está construida la solicitud a siteverify

Tu servidor envía una solicitud POST a la dirección https://challenges.cloudflare.com/turnstile/v0/siteverify con los campos:

  • secret — tu clave secreta;
  • response — el token del campo cf-turnstile-response;
  • remoteip — la IP del visitante, opcional pero útil;
  • idempotency_key — un identificador único opcional de la solicitud, del que hablaremos en la sección avanzada.

La respuesta llega en JSON. Los campos clave son:

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

El token vive 300 segundos y es de un solo uso. Verificar el mismo token de nuevo devolverá el error timeout-or-duplicate.

Ejemplo en PHP

  1. Abre el archivo procesador del formulario, por ejemplo submit.php.
  2. Al inicio, antes de cualquier trabajo con los datos del formulario, agrega el bloque de verificación:
<?php $token = $_POST['cf-turnstile-response'] ?? ''; if ($token === '') { http_response_code(400); exit('Verificación no superada: no hay 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('Verificación no superada: ' . implode(',', $result['error-codes'] ?? ['no-response'])); } 

Sobre el autor

Roman Melnikov

Roman Melnikov

Technical Writer and System Administrator

Experiencia laboral: 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.
Formación académica: Bauman Moscow State Technical University. Information Systems and Technologies
Especialización:
Technical Documentation DevOps System Administration Linux Docker and Kubernetes CI/CD Infrastructure Automation Cloud Technologies System Monitoring Bash and Python Scripting

Comparte el artículo: