This skill should be used when the user asks to \"add turnstile\", \"implement bot protection\", \"validate turnstile token\", \"fix turnstile error\", \"setup captcha alternative\", or encounters error codes 100*/300*/600*, CSP errors, or token validation failures. Provides
Installs just this skill. Get the whole plugin for auto-invocation.
⚡ How it fires
How this skill gets triggered: by you, by Claude, or both.
Fires itselfClaude auto-loads it when your prompt matches the work.
You can call itInvoke it directly when you want it.
Slash command/cloudflare-turnstile
👁️ Context preview
The summary Claude sees to decide when to auto-load this skill.
This skill should be used when the user asks to \"add turnstile\", \"implement bot protection\", \"validate turnstile token\", \"fix turnstile error\", \"setup captcha alternative\", or encounters error codes 100*/300*/600*, CSP errors, or token validation failures. Provides
📊 Stats
Stars194
Forks29
LanguageTypeScript
LicenseMIT
📦 Ships with claude-skills
</> SKILL.md
cloudflare-turnstile.SKILL.md
---name: cloudflare-turnstile
description: "This skill should be used when the user asks to \"add turnstile\", \"implement bot protection\", \"validate turnstile token\", \"fix turnstile error\", \"setup captcha alternative\", or encounters error codes 100*/300*/600*, CSP errors, or token validation failures. Provides CAPTCHA-alternative protection for Cloudflare Workers, React, Next.js, and Hono."
license: MIT
metadata:
version: "1.1.0"
last_verified: "2025-11-26"
react_turnstile_version: "1.3.1"
turnstile_types_version: "1.2.3"
errors_prevented: 12
templates_included: 7
references_included: 8
keywords:
- turnstile
- captcha
- bot protection
- cloudflare challenge
- siteverify
- recaptcha alternative
- spam prevention
- form protection
- cf-turnstile
- turnstile widget
- token validation
- managed challenge
- invisible challenge
- "@marsidev/react-turnstile"
- hono turnstile
- workers turnstile
---# Cloudflare Turnstile
✅ **Use dummy keys for testing** - Test sitekey: `1x00000000000000000000AA`
✅ **Set reasonable timeouts** - Don't wait indefinitely for validation
✅ **Validate action/hostname** - Check additional fields when specified
✅ **Rotate keys periodically** - Use dashboard or API to rotate secrets
✅ **Monitor analytics** - Track solve rates and failures
✅ **Validate token AFTER form submission** - Verify tokens after user completes form, not before. Premature validation creates security vulnerabilities where attackers obtain valid tokens then bypass protection
### Never Do
❌ **Skip server validation** - Client-side only = security vulnerability
❌ **Proxy api.js script** - Must load from Cloudflare CDN
❌ **Reuse tokens** - Each token is single-use only
❌ **Use GET requests** - Siteverify only accepts POST
❌ **Expose secret key** - Keep secrets in backend environment only
❌ **Trust client-side validation** - Tokens can be forged
❌ **Cache api.js** - Future updates will break your integration
❌ **Use production keys in tests** - Use dummy keys instead
**Why It Happens**: Each token can only be validated once
**Prevention**: Templates document single-use constraint and token refresh patterns
---
## Configuration
**Wrangler (Workers)**: Load `templates/wrangler-turnstile-config.jsonc` for complete configuration. Key settings: `vars` for public sitekey (safe to commit), `secrets` for private secret key (use `wrangler secret put TURNSTILE_SECRET_KEY`).
**CSP Directives** (if using Content Security Policy):
**Hono + Cloudflare Workers**: Server-side validation in Workers API routes with Hono framework. Load `references/common-patterns.md` #pattern-1 when building Workers endpoints requiring bot protection.
**React + Next.js**: Client-side forms with @marsidev/react-turnstile integration. Load `references/common-patterns.md` #pattern-2 when integrating Turnstile with React/Next.js applications.
**E2E Testing**: Automated testing with dummy keys (Playwright, Cypress, Jest). Load `references/common-patterns.md` #pattern-3 when writing E2E tests or setting up CI/CD pipelines.
**Widget Lifecycle**: Programmatic widget control for SPAs (render, reset, remove, getToken). Load `references/common-patterns.md` #pattern-4 when building SPAs requiring explicit widget management.
**`references/testing-guide.md`**: Setting up E2E tests (Playwright, Cypress), local development with dummy keys, or CI/CD pipeline integration.
**`references/react-integration.md`**: Integrating with React, Next.js, or troubleshooting @marsidev/react-turnstile issues (Jest mocking, SSR, hooks).
**`references/common-patterns.md`**: Building Hono Workers routes, React forms, E2E tests, or widget lifecycle management (explicit rendering).
**`references/advanced-topics.md`**: Implementing pre-clearance for SPAs, custom actions/cdata, retry strategies, or multi-widget pages.
**`references/setup-checklist.md`**: Preparing for deployment, verifying complete setup, or ensuring production readiness (14-point checklist).
**`references/migration-guide.md`**: Migrating from reCAPTCHA (v2) or hCaptcha to Turnstile, including compat mode, API differences, and POST-only Siteverify requirement.
**`references/mobile-implementation.md`**: WebView integration for iOS, Android, React Native, and Flutter, including User Agent consistency and storage persistence requirements.
**Solution**: Add your domain (including localhost for dev) to widget's allowed domains in Cloudflare Dashboard. For local dev, use dummy test sitekey `1x00000000000000000000AA` instead.
### Problem: Error 300030 - Widget crashes for legitimate users
**Solution**: Implement error callback with retry logic. This is a known Cloudflare-side issue (2025). Fallback to alternative verification if retries fail.
**Solution**: Document in error message that users should disable Safari's "Hide IP address" setting (Safari → Settings → Privacy → Hide IP address → Off)
### Problem: Next.js + Jest tests failing with @marsidev/react-turnstile
**Solution**: Mock the Turnstile component in Jest setup: