Qué es Cloudflare Turnstile
Cloudflare Turnstile es un sistema de verificación que sustituye a los CAPTCHA tradicionales. En lugar de mostrar desafíos visuales, ejecuta una serie de comprobaciones JavaScript en el navegador (proof-of-work, pruebas de espacio, detección de comportamientos humanos) y decide si el visitante es humano o bot sin pedirle interacción.
Turnstile tiene tres modos de widget: gestionado (el recomendado, decide automáticamente si muestra un checkbox o no), no interactivo (el visitante nunca interactúa con el widget) e invisible (el widget es completamente oculto). También es compatible con WCAG 2.2 AAA, lo que lo hace accesible para personas con discapacidad. Y no hace falta que tu web pase por la red CDN de Cloudflare: funciona en cualquier sitio, sea cual sea el hosting.
Según Cloudflare, Turnstile gestiona más de 50 millones de verificaciones diarias y su tasa de resolución sin interacción supera el 99% en sitios de bajo riesgo.
Por qué cambiar de Google reCAPTCHA a Turnstile
Si llevas tiempo usando Google reCAPTCHA, quizá te preguntes si merece la pena cambiar. Hay varias razones para planteárselo:
| Característica | Google reCAPTCHA v2/v3 | Cloudflare Turnstile |
|---|---|---|
| Interacción del usuario | puzzles visuales o seguimiento de comportamiento | sin interacción en la mayoría de casos |
| Privacidad | recopila datos de navegación y los comparte con Google | centrado en privacidad, sin tracking publicitario |
| Dependencia | vinculado al ecosistema Google | funciona sin depender de Google |
| Coste | gratis hasta cierto volumen | gratis para los primeros 100.000 dominios, luego planes de pago |
| Accesibilidad | WCAG 2.1 AA (con problemas conocidos) | WCAG 2.2 AAA |
| Rendimiento | impacta en velocidad de carga | script más ligero, menor impacto |
La principal ventaja de Turnstile es la experiencia del usuario. Los visitantes no tienen que resolver ningún puzzle, y en la mayoría de los casos ni siquiera ven el widget. Menos fricción en formularios de contacto, registros y compras se traduce en más conversiones y menos abandonos.
En cuanto a privacidad, Google reCAPTCHA recopila información de navegación para sus propios fines publicitarios. Turnstile no utiliza los datos de verificación con fines de publicidad.
Cómo crear un widget de Turnstile en Cloudflare
Antes de añadir Turnstile a tu web, necesitas crear un widget en el panel de Cloudflare:
- Crear una cuenta en Cloudflare: Si no tienes una, regístrate en dash.cloudflare.com. Es gratis.
- Acceder a Turnstile: Desde el panel, ve a la sección «Turnstile» en el menú lateral.
- Crear un widget: Pulsa «Add site» y rellena los datos: un nombre descriptivo (por ejemplo, «Formulario de contacto»), los dominios donde lo vas a usar y el modo de widget (gestionado, no interactivo o invisible).
- Guardar las claves: Al crear el widget, Cloudflare te da dos claves: la sitekey (clave pública, va en el HTML) y la secret key (clave privada, va en el servidor para validar el token). Guárdalas en un lugar seguro.
La sitekey se usa en el lado cliente para mostrar el widget. La secret key se usa en el servidor para verificar que el token es válido. Nunca la expongas en tu código frontend.
Implementar Turnstile en una web estándar (HTML + PHP)
La implementación tiene dos partes: el widget en tu HTML y la validación del token en PHP. Vamos a ver ambas.
Paso 1: Añadir el script y el widget al formulario
Incluye el script de Turnstile en tu página HTML y coloca el widget dentro del formulario. Vamos a usar el renderizado implícito, el más sencillo para páginas estáticas:
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Formulario de contacto</title>
<!-- Script de Turnstile -->
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
</head>
<body>
<h1>Contacto</h1>
<form action="procesar.php" method="POST">
<label for="nombre">Nombre:</label>
<input type="text" id="nombre" name="nombre" required>
<label for="email">Email:</label>
<input type="email" id="email" name="email" required>
<label for="mensaje">Mensaje:</label>
<textarea id="mensaje" name="mensaje" required></textarea>
<!-- Widget de Turnstile -->
<div class="cf-turnstile" data-sitekey="TU_SITEKEY_AQUI"></div>
<button type="submit">Enviar</button>
</form>
</body>
</html>El <div class="cf-turnstile"> se coloca dentro del formulario. Al enviarlo, Turnstile añade automáticamente un campo oculto llamado cf-turnstile-response con el token de verificación. No tienes que hacer nada extra en el HTML.
Puedes personalizar el widget con atributos data-:
data-theme="light|dark|auto": aspecto visual del widget.data-size="normal|compact|flexible": tamaño del widget.data-callback="nombreFuncion": función JavaScript que se ejecuta al completar la verificación.data-error-callback="nombreFuncion": función que se ejecuta si hay error.
Paso 2: Validar el token en PHP (lado servidor)
Lo anterior solo muestra el widget y genera un token. Para que la protección funcione, tu servidor tiene que verificar ese token con la API de Cloudflare. Sin esta verificación, cualquiera puede enviar un formulario sin pasar por Turnstile.
Crea un archivo procesar.php:
<?php
// Tu secret key de Turnstile (NUNCA expongas esta clave en el frontend)
$secret_key = 'TU_SECRET_KEY_AQUI';
// Recoger el token enviado por el formulario
$token = $_POST['cf-turnstile-response'] ?? '';
// IP del visitante (opcional pero recomendado)
$remoteip = $_SERVER['HTTP_CF_CONNECTING_IP']
?? $_SERVER['HTTP_X_FORWARDED_FOR']
?? $_SERVER['REMOTE_ADDR'];
// Llamar a la API de verificación de Cloudflare
$url = 'https://challenges.cloudflare.com/turnstile/v0/siteverify';
$data = [
'secret' => $secret_key,
'response' => $token,
'remoteip' => $remoteip
];
$options = [
'http' => [
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'POST',
'content' => http_build_query($data)
]
];
$context = stream_context_create($options);
$response = file_get_contents($url, false, $context);
$result = json_decode($response, true);
if ($result['success']) {
// Token válido: procesar el formulario
echo "Formulario enviado correctamente.";
// Aquí va tu lógica: guardar en base de datos, enviar email, etc.
} else {
// Token inválido: rechazar el envío
echo "Verificación fallida. Inténtalo de nuevo.";
error_log('Turnstile error: ' . implode(', ', $result['error-codes']));
}
?>Este código envía el token y tu secret key al endpoint de Cloudflare. Si la respuesta es "success": true, el token es válido y puedes procesar el formulario. Si no, rechazas el envío.
Puntos a tener en cuenta:
- Los tokens expiran a los 5 minutos (300 segundos). Cada token se puede usar una sola vez.
- La validación del lado servidor es obligatoria. Si solo pones el widget en el HTML sin validar en el servidor, cualquier bot puede saltarse la protección.
- Nunca pongas la secret key en tu código JavaScript. Tiene que quedarse en el servidor, siempre.
Validar el token en Node.js
Si tu backend está en Node.js, la lógica de validación es la misma: enviar el token y la secret key al endpoint de Cloudflare y comprobar la respuesta. Aquí tienes un ejemplo con Express:
const express = require('express');
const app = express();
app.use(express.urlencoded({ extended: true }));
const SECRET_KEY = 'TU_SECRET_KEY_AQUI';
async function validarTurnstile(token, remoteip) {
const params = new URLSearchParams();
params.append('secret', SECRET_KEY);
params.append('response', token);
if (remoteip) params.append('remoteip', remoteip);
const respuesta = await fetch(
'https://challenges.cloudflare.com/turnstile/v0/siteverify',
{
method: 'POST',
body: params
}
);
return await respuesta.json();
}
app.post('/contacto', async (req, res) => {
const token = req.body['cf-turnstile-response'];
const ip = req.headers['cf-connecting-ip']
|| req.headers['x-forwarded-for']
|| req.socket.remoteAddress;
const resultado = await validarTurnstile(token, ip);
if (resultado.success) {
// Token válido: procesar el formulario
res.send('Formulario enviado correctamente.');
} else {
// Token inválido: rechazar el envío
console.error('Turnstile error:', resultado['error-codes']);
res.status(400).send('Verificación fallida. Inténtalo de nuevo.');
}
});
app.listen(3000);Al igual que en PHP, la secret key debe guardarse en una variable de entorno, no en el código fuente. Puedes usar process.env.TURNSTILE_SECRET_KEY en lugar de la constante directa.
Si todo a funcionado bien, verás el icono (modo gestionado) de CloudFlare similar a este:
Tienes la información completa de implementación en el sitio web de CloudFlare.
Ejemplo con callbacks (opcional)
Si quieres más control, puedes usar callbacks para habilitar o deshabilitar el botón de envío:
<div
class="cf-turnstile"
data-sitekey="TU_SITEKEY_AQUI"
data-callback="onTurnstileSuccess"
data-error-callback="onTurnstileError"
data-expired-callback="onTurnstileExpired"
></div>
<button type="submit" id="btn-enviar" disabled>Enviar</button>
<script>
function onTurnstileSuccess(token) {
document.getElementById('btn-enviar').disabled = false;
}
function onTurnstileError(code) {
document.getElementById('btn-enviar').disabled = true;
}
function onTurnstileExpired() {
document.getElementById('btn-enviar').disabled = true;
}
</script>Así el botón de envío solo se activa cuando Turnstile verifica correctamente al visitante, y se desactiva si hay error o si el token expira.
Implementar Turnstile en WordPress
Si tu web usa WordPress, no necesitas tocar nada de código. Hay plugins que integran Turnstile en unos minutos.
Plugin recomendado: Simple Cloudflare Turnstile
El plugin Simple Cloudflare Turnstile (por Elliot Sowersby / RelyWP) es la opción más usada, con más de 100.000 instalaciones activas. Es gratis y compatible con los principales plugins de formularios:
- Contact Form 7
- WooCommerce (login, registro, checkout)
- WordPress Login y Registro
- WPForms
- Elementor Forms
- Forminator
- Comentarios de WordPress
Pasos para instalar y configurar el plugin
- Instala el plugin: Ve a «Plugins > Añadir nuevo» en tu panel de WordPress y busca «Simple Cloudflare Turnstile». Instálalo y actívalo.
- Configura las claves: Ve a «Ajustes > Cloudflare Turnstile». Introduce tu Site Key y tu Secret Key (las que obtuviste al crear el widget en Cloudflare).
- Selecciona dónde activarlo: El plugin te permite elegir en qué formularios aparece Turnstile: login, registro, comentarios, recuperación de contraseña, WooCommerce, etc.
- Elige el modo del widget: Puedes seleccionar entre managed, non-interactive o invisible. El modo managed suele ser la mejor opción para la mayoría de webs.
- Guarda los cambios: Pulsa «Save Changes» y ya está.
No hace falta tocar PHP ni JavaScript. El plugin inserta el script y valida el token de forma automática.
Puedes descargarlo en su repositorio de WordPress.
Otras opciones para WordPress
Si usas plugins de formularios específicos, hay integraciones directas:
- Contact Form 7: El plugin «Contact Form 7 Captcha» permite usar Turnstile en CF7.
- Gravity Forms: «Enable Turnstile (Cloudflare) for Gravity Forms» añade soporte específico.
- WooCommerce: «Login Security Captcha» protege formularios de login, registro y checkout con Turnstile o reCAPTCHA.
- Shield Security: Incluye protección anti-bots con Turnstile entre sus funciones de seguridad.
- LiteSpeed Cache: Si usas LiteSpeed como servidor (como en k3bone), el plugin LiteSpeed Cache también tiene integración con Turnstile en sus ajustes de seguridad.
Buenas prácticas
Al implementar Turnstile, ten en cuenta estos puntos:
- Valida siempre el token en el servidor. El widget en el HTML es solo la mitad de la protección. Sin validación en el servidor, Turnstile no sirve de nada.
- Usa el modo managed/gestionado a menos que tengas una razón concreta para elegir otro. Es el que mejor equilibra seguridad y experiencia de usuario.
- Rota las claves de forma periódica. Desde el panel de Cloudflare puedes generar nuevas secret keys y revocar las antiguas.
- Restringe los dominios en la configuración del widget. Solo añade los dominios donde vayas a usar Turnstile.
- Separa entornos: usa widgets diferentes para desarrollo, staging y producción.
- Los tokens expiran a los 5 minutos. Si un usuario tarda más en completar el formulario, el token caduca y hay que volver a generarlo con
turnstile.reset().
Si vienes de Google reCAPTCHA, la migración es directa: Turnstile se integra dondequiera que tengas el script de reCAPTCHA. Puedes consultar la guía oficial de migración en la documentación de Cloudflare.
Preguntas frecuentes sobre Cloudflare Turnstile
¿Es Cloudflare Turnstile gratis?
Sí, Turnstile es gratis para los primeros 100.000 dominios. Cloudflare ofrece un plan gratuito que cubre la mayoría de casos de uso. Para volúmenes más altos o necesidades empresariales, hay planes de pago. Consulta los detalles en la página de planes de Turnstile.
¿Necesito usar Cloudflare como CDN para usar Turnstile?
No. Turnstile funciona por separado. Puedes usarlo en cualquier web, uses o no la red CDN de Cloudflare. No hace falta cambiar de hosting ni de proveedor DNS.
¿Turnstile funciona en sitios sin HTTPS?
No. Turnstile solo funciona en páginas servidas con HTTPS. Otros protocolos como file:// tampoco son compatibles.
¿Cómo sé si Turnstile está funcionando?
Puedes usar las claves de test que proporciona Cloudflare para verificar la integración sin desafíos reales. La sitekey de test es 1x0000000000000000000000000000000AA y la secret key de test es 1x0000000000000000000000000000000AA. Una vez en producción, revisa los datos en la sección «Turnstile Analytics» del panel de Cloudflare.
¿Puedo usar Turnstile en aplicaciones móviles?
Sí, Cloudflare tiene guías para integrar Turnstile en aplicaciones iOS y Android a través de WebView. Consulta la documentación sobre implementación móvil.
Si tu web sigue usando Google reCAPTCHA y quieres mejorar la experiencia de tus visitantes, Turnstile es la alternativa que estabas buscando. Podemos ayudarte con la integración en tu proyecto, tanto si es una web a medida como si usa WordPress. Contacta con nosotros si necesitas ayuda con la configuración.

