Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Comprehensive Cloudflare platform skill covering Workers, D1, R2, KV, AI, Durable Objects, and security.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/turnstile/README.md
1# Cloudflare Turnstile Implementation Skill Reference23Expert guidance for implementing Cloudflare Turnstile - a smart CAPTCHA alternative that protects websites from bots without showing traditional CAPTCHA puzzles.45## Overview67Turnstile is a user-friendly CAPTCHA alternative that runs challenges in the background without user interaction. It validates visitors automatically using signals like browser behavior, device fingerprinting, and machine learning.89## Widget Types1011| Type | Interaction | Use Case |12|------|-------------|----------|13| **Managed** (default) | Shows checkbox when needed | Forms, logins - balance UX and security |14| **Non-Interactive** | Invisible, runs automatically | Frictionless UX, low-risk actions |15| **Invisible** | Hidden, triggered programmatically | Pre-clearance, API calls, headless |1617## Quick Start1819### Implicit Rendering (HTML-based)20```html21<!-- 1. Add script -->22<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>2324<!-- 2. Add widget to form -->25<form action="/submit" method="POST">26<div class="cf-turnstile" data-sitekey="YOUR_SITE_KEY"></div>27<button type="submit">Submit</button>28</form>29```3031### Explicit Rendering (JavaScript-based)32```html33<div id="turnstile-container"></div>34<script src="https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit"></script>35<script>36window.turnstile.render('#turnstile-container', {37sitekey: 'YOUR_SITE_KEY',38callback: (token) => console.log('Token:', token)39});40</script>41```4243### Server Validation (Required)44```javascript45// Cloudflare Workers46export default {47async fetch(request) {48const formData = await request.formData();49const token = formData.get('cf-turnstile-response');5051const result = await fetch('https://challenges.cloudflare.com/turnstile/v0/siteverify', {52method: 'POST',53headers: { 'Content-Type': 'application/json' },54body: JSON.stringify({55secret: env.TURNSTILE_SECRET,56response: token,57remoteip: request.headers.get('CF-Connecting-IP')58})59});6061const validation = await result.json();62if (!validation.success) {63return new Response('Invalid CAPTCHA', { status: 400 });64}65// Process form...66}67}68```6970## Testing Keys7172**Critical for development/testing:**7374| Type | Key | Behavior |75|------|-----|----------|76| **Site Key (Always Passes)** | `1x00000000000000000000AA` | Widget succeeds, token validates |77| **Site Key (Always Blocks)** | `2x00000000000000000000AB` | Widget fails visibly |78| **Site Key (Force Challenge)** | `3x00000000000000000000FF` | Always shows interactive challenge |79| **Secret Key (Testing)** | `1x0000000000000000000000000000000AA` | Validates test tokens |8081**Note:** Test keys work on `localhost` and any domain. Do NOT use in production.8283## Key Constraints8485- **Token expiry:** 5 minutes after generation86- **Single-use:** Each token can only be validated once87- **Server validation required:** Client-side checks are insufficient8889## Reading Order90911. **[configuration.md](configuration.md)** - Setup, widget options, script loading922. **[api.md](api.md)** - JavaScript API, siteverify endpoints, TypeScript types933. **[patterns.md](patterns.md)** - Form integration, framework examples, validation patterns944. **[gotchas.md](gotchas.md)** - Common errors, debugging, limitations9596## See Also9798- [Cloudflare Turnstile Docs](https://developers.cloudflare.com/turnstile/)99- [Dashboard](https://dash.cloudflare.com/?to=/:account/turnstile)100