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.
Overview
The most basic usage of React Turnstile involves importing the component and providing your Cloudflare sitekey. This guide covers common usage patterns and best practices.
Simple Implementation
Here’s the simplest way to add Turnstile to your React component:
import { Turnstile } from '@marsidev/react-turnstile'
function MyForm () {
return (
< form >
< input type = "email" placeholder = "Email" />
< Turnstile siteKey = "1x00000000000000000000AA" />
< button type = "submit" > Submit </ button >
</ form >
)
}
Replace 1x00000000000000000000AA with your actual Cloudflare Turnstile sitekey. You can obtain one from the Cloudflare Dashboard .
Handling Success Callback
Capture the verification token when the challenge is successfully completed:
import { Turnstile } from '@marsidev/react-turnstile'
import { useState } from 'react'
function MyForm () {
const [ token , setToken ] = useState < string >()
return (
< form >
< input type = "email" placeholder = "Email" />
< Turnstile
siteKey = "1x00000000000000000000AA"
onSuccess = { ( token ) => {
console . log ( 'Verification successful! Token:' , token )
setToken ( token )
} }
/>
< button type = "submit" disabled = { ! token } >
Submit
</ button >
</ form >
)
}
Here’s a complete example with form submission and error handling:
import { Turnstile } from '@marsidev/react-turnstile'
import { useState } from 'react'
function ContactForm () {
const [ token , setToken ] = useState < string >()
const [ status , setStatus ] = useState < 'idle' | 'submitting' | 'success' | 'error' >( 'idle' )
const handleSubmit = async ( e : React . FormEvent < HTMLFormElement >) => {
e . preventDefault ()
if ( ! token ) {
alert ( 'Please complete the verification' )
return
}
setStatus ( 'submitting' )
try {
const formData = new FormData ( e . currentTarget )
const response = await fetch ( '/api/contact' , {
method: 'POST' ,
headers: { 'Content-Type' : 'application/json' },
body: JSON . stringify ({
email: formData . get ( 'email' ),
message: formData . get ( 'message' ),
turnstileToken: token
})
})
if ( response . ok ) {
setStatus ( 'success' )
} else {
setStatus ( 'error' )
}
} catch ( error ) {
setStatus ( 'error' )
}
}
return (
< form onSubmit = { handleSubmit } >
< input
type = "email"
name = "email"
placeholder = "Email"
required
/>
< textarea
name = "message"
placeholder = "Message"
required
/>
< Turnstile
siteKey = "1x00000000000000000000AA"
onSuccess = { setToken }
onError = { () => setToken ( undefined ) }
onExpire = { () => setToken ( undefined ) }
/>
< button type = "submit" disabled = { ! token || status === 'submitting' } >
{ status === 'submitting' ? 'Submitting...' : 'Submit' }
</ button >
{ status === 'success' && < p > Form submitted successfully! </ p > }
{ status === 'error' && < p > Error submitting form. Please try again. </ p > }
</ form >
)
}
Theme
Customize the widget appearance:
< Turnstile
siteKey = "1x00000000000000000000AA"
options = { {
theme: 'dark' // or 'light', 'auto'
} }
/>
Size
Control the widget size:
< Turnstile
siteKey = "1x00000000000000000000AA"
options = { {
size: 'compact' // or 'normal', 'flexible'
} }
/>
Language
Set a specific language:
< Turnstile
siteKey = "1x00000000000000000000AA"
options = { {
language: 'es' // Spanish
} }
/>
Lifecycle Callbacks
React to various widget events:
< Turnstile
siteKey = "1x00000000000000000000AA"
onSuccess = { ( token ) => console . log ( 'Success:' , token ) }
onError = { ( error ) => console . error ( 'Error:' , error ) }
onExpire = { () => console . log ( 'Token expired' ) }
onBeforeInteractive = { () => console . log ( 'Before interactive' ) }
onAfterInteractive = { () => console . log ( 'After interactive' ) }
onUnsupported = { () => console . log ( 'Browser not supported' ) }
onTimeout = { () => console . log ( 'Widget timed out' ) }
/>
Next Steps
Multiple Widgets Use multiple widgets on a single page
Interact with Widget Control the widget programmatically
Server Validation Validate tokens on your server
Component Props Explore all available props