Documentation Index Fetch the complete documentation index at: https://mintlify.com/marsidev/react-turnstile/llms.txt
Use this file to discover all available pages before exploring further.
This guide covers common issues you might encounter when using React Turnstile and how to resolve them.
Common Issues
Problem The Cloudflare Turnstile script fails to load. Solutions Check network connectivity
Ensure your application can reach https://challenges.cloudflare.com.Disable ad blockers
Some ad blockers prevent the Turnstile script from loading. Whitelist your site or disable the blocker.Check Content Security Policy
Add Cloudflare domains to your CSP:Content-Security-Policy:
script-src 'self' https://challenges.cloudflare.com;
frame-src 'self' https://challenges.cloudflare.com;
Handle script errors < Turnstile
siteKey = "your-site-key"
scriptOptions = { {
onError : () => {
console . error ( 'Failed to load Turnstile script' )
// Show fallback UI
}
} }
/>
Use manual injection
If automatic injection fails, inject the script manually:import Script from 'next/script'
import { Turnstile , SCRIPT_URL , DEFAULT_SCRIPT_ID } from '@marsidev/react-turnstile'
<>
< Script id = { DEFAULT_SCRIPT_ID } src = { SCRIPT_URL } />
< Turnstile siteKey = "your-site-key" injectScript = { false } />
</>
Problem Server-side validation returns success: false. Solutions Check secret key
Ensure you’re using the correct secret key on the server:const secret = process . env . TURNSTILE_SECRET_KEY
Token expiration
Tokens expire after a few minutes. Validate immediately after receiving:const handleSuccess = async ( token : string ) => {
// Validate immediately
const response = await fetch ( '/api/verify' , {
method: 'POST' ,
body: JSON . stringify ({ token }),
})
}
Token reuse
Each token can only be validated once. If you need a new token, reset the widget:const turnstileRef = useRef < TurnstileInstance >( null )
// After failed validation
turnstileRef . current ?. reset ()
Check error codes const data : TurnstileServerValidationResponse = await response . json ()
if ( ! data . success ) {
console . error ( 'Error codes:' , data [ 'error-codes' ])
// Handle specific errors:
// - 'missing-input-response': No token provided
// - 'invalid-input-response': Invalid or expired token
// - 'timeout-or-duplicate': Token already used
}
Verify hostname
By default, Cloudflare validates the hostname. Ensure requests come from the configured domain.
Hydration errors in Next.js
Problem React hydration mismatch warnings in Next.js. Solutions Use ‘use client’ directive 'use client'
import { Turnstile } from '@marsidev/react-turnstile'
export default function Form () {
return < Turnstile siteKey = "your-site-key" />
}
Render only on client import { useEffect , useState } from 'react'
export default function TurnstileWrapper () {
const [ isClient , setIsClient ] = useState ( false )
useEffect (() => {
setIsClient ( true )
}, [])
if ( ! isClient ) return null
return < Turnstile siteKey = "your-site-key" />
}
Use dynamic import with no SSR import dynamic from 'next/dynamic'
const Turnstile = dynamic (
() => import ( '@marsidev/react-turnstile' ). then ( mod => mod . Turnstile ),
{ ssr: false }
)
Widget not resetting properly
Multiple widgets conflict
CSP policy blocks Turnstile
Problem Content Security Policy prevents Turnstile from loading. Solutions Add Cloudflare domains to CSP Content-Security-Policy:
default-src 'self';
script-src 'self' https://challenges.cloudflare.com;
frame-src 'self' https://challenges.cloudflare.com;
connect-src 'self' https://challenges.cloudflare.com;
style-src 'self' 'unsafe-inline' https://challenges.cloudflare.com;
Next.js configuration // next.config.js
module . exports = {
async headers () {
return [
{
source: '/(.*)' ,
headers: [
{
key: 'Content-Security-Policy' ,
value: [
"default-src 'self'" ,
"script-src 'self' https://challenges.cloudflare.com" ,
"frame-src 'self' https://challenges.cloudflare.com" ,
"connect-src 'self' https://challenges.cloudflare.com" ,
"style-src 'self' 'unsafe-inline' https://challenges.cloudflare.com" ,
]. join ( '; ' )
}
]
}
]
}
}
Use nonce for inline scripts const nonce = generateNonce () // Your nonce generation
< Turnstile
siteKey = "your-site-key"
scriptOptions = { { nonce } }
/>
Problem TypeScript compilation errors when using React Turnstile. Solutions Import types correctly import { Turnstile , type TurnstileInstance , type TurnstileProps } from '@marsidev/react-turnstile'
Type the ref properly import { useRef } from 'react'
import type { TurnstileInstance } from '@marsidev/react-turnstile'
const turnstileRef = useRef < TurnstileInstance >( null )
Update TypeScript config
Ensure your tsconfig.json includes:{
"compilerOptions" : {
"moduleResolution" : "bundler" ,
"esModuleInterop" : true
}
}
Widget appears then disappears
Race condition on script load
Problem Widget sometimes fails to render due to timing issues. Solution This issue was fixed in v1.4.1. Update to the latest version: npm install @marsidev/react-turnstile@latest
The library now polls for window.turnstile to handle race conditions automatically.
Error Messages
Client-Side Errors
Cloudflare Turnstile may call onError with these error codes:
110100 : Invalid siteKey
110200 : Invalid domain
110300 : Network error
110400 : Timeout
110500 : Internal error
110600 : Challenge failed
const handleError = ( errorCode : string ) => {
const messages : Record < string , string > = {
'110100' : 'Invalid site key configured' ,
'110200' : 'Domain not authorized for this site key' ,
'110300' : 'Network connection failed' ,
'110400' : 'Challenge timeout - please try again' ,
'110500' : 'Internal error - please try again' ,
'110600' : 'Challenge verification failed' ,
}
alert ( messages [ errorCode ] || 'An error occurred' )
}
< Turnstile siteKey = "your-site-key" onError = { handleError } />
Server-Side Errors
Validation API returns these error codes in error-codes array:
missing-input-secret : Server didn’t send secret key
invalid-input-secret : Secret key is invalid
missing-input-response : Token wasn’t provided
invalid-input-response : Token is invalid or expired
timeout-or-duplicate : Token was already validated
internal-error : Cloudflare server error
Still Having Issues?
If you’re still experiencing problems:
Check the GitHub Issues for similar problems
Review the Cloudflare Turnstile documentation
Open a new issue with:
React Turnstile version
Framework and version (Next.js, React, etc.)
Browser and version
Minimal reproduction code
Error messages and console logs