Logo de Kodflux - Plataforma de Herramientas SEO y Auditoría Web

JavaScript / Intermedio / 6 min

Verificar Cloudflare Turnstile en un Worker

Valida el token de Turnstile del lado del servidor para bloquear spam y bots en formularios sin CAPTCHAs molestos.

Turnstile reemplaza a los CAPTCHAs, pero solo protege de verdad si verificas el token en el servidor. Un atacante puede saltarse la comprobación del navegador; la validación server-side no. Este Worker recibe el cf-turnstile-response que envía tu formulario, lo valida contra la API de Cloudflare con tu secret key y solo deja pasar la petición si el token es legítimo.

Guía de Implementación Paso a Paso

  1. En el panel de Cloudflare ve a Turnstile y crea un widget para tu dominio.
  2. Copia la Site Key (para el frontend) y la Secret Key (para el Worker).
  3. Añade el widget a tu formulario en el HTML con <div class="cf-turnstile" data-sitekey="TU_SITE_KEY"></div> y el script de Turnstile.
  4. Crea un Worker en Workers & Pages → Create Worker.
  5. Pega el código de abajo y guarda.
  6. En Settings → Variables, añade una variable secreta llamada TURNSTILE_SECRET con tu Secret Key.
  7. Apunta el action de tu formulario a la ruta del Worker y despliega.
JAVASCRIPT
export default {
  async fetch(request, env) {
    if (request.method !== 'POST') {
      return new Response('Method not allowed', { status: 405 });
    }

    const body = await request.formData();
    const token = body.get('cf-turnstile-response');
    const ip = request.headers.get('CF-Connecting-IP');

    if (!token) {
      return new Response('Falta el token de Turnstile', { status: 400 });
    }

    const form = new FormData();
    form.append('secret', env.TURNSTILE_SECRET);
    form.append('response', token);
    form.append('remoteip', ip);

    const result = await fetch(
      'https://challenges.cloudflare.com/turnstile/v0/siteverify',
      { method: 'POST', body: form }
    );
    const outcome = await result.json();

    if (!outcome.success) {
      return new Response('Verificación fallida. Reintenta.', { status: 403 });
    }

    // Token válido: aquí procesas el formulario (guardar, enviar email, etc.)
    return new Response('Formulario recibido correctamente', { status: 200 });
  }
};

Nunca expongas la Secret Key en el frontend: va siempre como variable de entorno del Worker. El campo remoteip es opcional pero refuerza la validación al atar el token a la IP que lo generó.

Buscar en Kodflux