Qué es Turnstile
Turnstile es la alternativa de Cloudflare al captcha: la documentación lo define como «Cloudflare's smart CAPTCHA alternative». Se agrega a tu formulario y decide si quien lo manda es una persona o un bot. En vez de pedir que elijas semáforos, en el modo recomendado no pide nada o, como mucho, que tildes una casilla.
No hace falta que tu web esté en Cloudflare: según la documentación, «can be embedded into any website without sending traffic through Cloudflare». Solo necesitás una cuenta de Cloudflare.
Qué incluye el plan gratis
| Dato | Plan gratis |
|---|---|
| Widgets | Hasta 20 |
| Hostnames por widget | Hasta 10 |
| Desafíos | Ilimitados |
| Otros servicios de Cloudflare | No hacen falta |
Modos del widget
| Modo | Qué hace |
|---|---|
| Managed | El recomendado. Según el riesgo, no pide nada o pide tildar una casilla. |
| Non-interactive | Otro modo disponible al crear el widget. |
| Invisible | Otro modo disponible al crear el widget. |
Cómo funciona
Turnstile tiene dos partes y necesitás las dos:
| Parte | Dónde va | Qué clave usa |
|---|---|---|
| Widget | En el HTML de tu formulario | La clave del sitio (sitekey) |
| Validación | En tu servidor, cuando recibe el formulario | La clave secreta (secret) |
El widget le da al formulario un token. Tu servidor manda ese token a Cloudflare con la clave secreta y Cloudflare le dice si es válido. Cada token vale 300 segundos y se puede validar una sola vez. La documentación es clara: «The client-side widget alone does not protect your forms».
Pasos
- Creá el widget. Entrá al panel de Cloudflare con tu cuenta, creá un widget de Turnstile con el dominio de tu web y elegí el modo (Managed es el recomendado). Te da dos claves: la del sitio y la secreta. La secreta no la pongas nunca en el HTML.
- Cargá el script. En la página del formulario agregá
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>. - Poné el widget en el formulario. Dentro del formulario agregá
<div class="cf-turnstile" data-sitekey="<YOUR-SITE-KEY>"></div>y reemplazá<YOUR-SITE-KEY>por tu clave del sitio. - Validá en el servidor. Cuando tu servidor recibe el formulario, hacé un POST a
https://challenges.cloudflare.com/turnstile/v0/siteverifycon dos parámetros:secret(tu clave secreta) yresponse(el token que mandó el formulario). Si Cloudflare dice que no es válido, rechazá el envío. - Probá las dos puntas. Mandá el formulario desde el navegador: tiene que pasar. Después mandalo sin token, por ejemplo con
curl, como haría un bot: tu servidor tiene que rechazarlo.
Claves de prueba
Cloudflare publica claves oficiales para probar sin cuenta y sin tocar tu sitio publicado.
| Tipo | Clave | Resultado |
|---|---|---|
| Sitekey | 1x00000000000000000000AA |
Siempre pasa |
| Sitekey | 2x00000000000000000000AB |
Siempre falla |
| Secret | 1x0000000000000000000000000000000AA |
La validación pasa |
| Secret | 2x0000000000000000000000000000000AA |
La validación falla |
Para probar la validación del servidor a mano:
curl -X POST https://challenges.cloudflare.com/turnstile/v0/siteverify -d secret=1x0000000000000000000000000000000AA -d response=TOKEN_DE_PRUEBA
Cuando termines de probar, cambiá las claves de prueba por las de tu widget.
Si algo falla
- Los bots siguen mandando mensajes: revisá que tu servidor llame a
siteverifyen cada envío y rechace los que no validan. Con el widget solo no alcanza. - Un envío legítimo da error al validar: el token vence a los 300 segundos y se valida una sola vez. Si el formulario quedó abierto mucho tiempo o el servidor valida dos veces el mismo token, falla.
- El widget no aparece: confirmá que el
<script>deapi.jsesté en la página y que eldivtenga la clasecf-turnstiley tu clave del sitio endata-sitekey. - Funciona en un dominio y en otro no: el widget va atado a los hostnames que cargaste al crearlo (hasta 10 por widget). Agregá el que falta.
- No sabés si el problema está en tu código o en las claves: cambiá a las claves de prueba que siempre pasan; si así anda, el problema está en tus claves o en el dominio del widget.
- Te pide tildar una casilla: es normal en modo Managed, que según el riesgo puede pedirla.