Get Your First reCAPTCHA Working
This quickstart guide will get you from zero to a working reCAPTCHA v3 integration in just a few minutes. We’ll use the recommended useGoogleReCaptcha hook approach.
Install the package
Install react-google-recaptcha-v3 using your preferred package manager: npm install react-google-recaptcha-v3
This library requires React 16.3 or higher. Check your package.json to ensure compatibility.
Get your reCAPTCHA site key
Visit the Google reCAPTCHA admin console
Click the + button to register a new site
Enter a label for your site (e.g., “My React App”)
Select reCAPTCHA v3 as the type
Add your domain(s) - use localhost for development
Accept the terms of service
Click Submit
Copy your Site Key (you’ll need this in the next step)
Make sure you select reCAPTCHA v3 , not v2. The two versions are not compatible.
Add the provider to your app
Wrap your application with GoogleReCaptchaProvider at the root level. This loads the reCAPTCHA script and provides access to the verification function throughout your app. import React from 'react' ;
import { GoogleReCaptchaProvider } from 'react-google-recaptcha-v3' ;
import LoginForm from './LoginForm' ;
function App () {
return (
< GoogleReCaptchaProvider reCaptchaKey = "YOUR_RECAPTCHA_SITE_KEY" >
< div className = "app" >
< h1 > My Application </ h1 >
< LoginForm />
</ div >
</ GoogleReCaptchaProvider >
);
}
export default App ;
Store your site key in an environment variable (e.g., REACT_APP_RECAPTCHA_SITE_KEY or VITE_RECAPTCHA_SITE_KEY) rather than hardcoding it.
Execute reCAPTCHA on user actions
Use the useGoogleReCaptcha hook to verify user actions. Here’s a complete login form example: import React , { useState , useCallback } from 'react' ;
import { useGoogleReCaptcha } from 'react-google-recaptcha-v3' ;
function LoginForm () {
const { executeRecaptcha } = useGoogleReCaptcha ();
const [ email , setEmail ] = useState ( '' );
const [ password , setPassword ] = useState ( '' );
const [ loading , setLoading ] = useState ( false );
const [ message , setMessage ] = useState ( '' );
const handleSubmit = useCallback ( async ( e : React . FormEvent ) => {
e . preventDefault ();
// Check if executeRecaptcha is available
if ( ! executeRecaptcha ) {
setMessage ( 'reCAPTCHA not yet loaded' );
return ;
}
setLoading ( true );
setMessage ( '' );
try {
// Execute reCAPTCHA with action name 'login'
const token = await executeRecaptcha ( 'login' );
// Send token to your backend for verification
const response = await fetch ( '/api/login' , {
method: 'POST' ,
headers: { 'Content-Type' : 'application/json' },
body: JSON . stringify ({
email ,
password ,
recaptchaToken: token
})
});
const data = await response . json ();
if ( response . ok ) {
setMessage ( 'Login successful!' );
// Redirect or update app state
} else {
setMessage ( data . error || 'Login failed' );
}
} catch ( error ) {
setMessage ( 'An error occurred. Please try again.' );
console . error ( 'Login error:' , error );
} finally {
setLoading ( false );
}
}, [ executeRecaptcha , email , password ]);
return (
< form onSubmit = { handleSubmit } >
< div >
< label htmlFor = "email" > Email: </ label >
< input
id = "email"
type = "email"
value = { email }
onChange = { ( e ) => setEmail ( e . target . value ) }
required
/>
</ div >
< div >
< label htmlFor = "password" > Password: </ label >
< input
id = "password"
type = "password"
value = { password }
onChange = { ( e ) => setPassword ( e . target . value ) }
required
/>
</ div >
< button type = "submit" disabled = { loading } >
{ loading ? 'Logging in...' : 'Log In' }
</ button >
{ message && < p > { message } </ p > }
</ form >
);
}
export default LoginForm ;
The action parameter (e.g., 'login') helps you understand which actions generated which scores in the reCAPTCHA admin console analytics.
Verify the token on your backend
Critical: Always verify reCAPTCHA tokens on your backend. Here’s an example using Node.js/Express:const express = require ( 'express' );
const fetch = require ( 'node-fetch' );
const app = express ();
app . use ( express . json ());
const RECAPTCHA_SECRET_KEY = process . env . RECAPTCHA_SECRET_KEY ;
app . post ( '/api/login' , async ( req , res ) => {
const { email , password , recaptchaToken } = req . body ;
// Verify reCAPTCHA token with Google
const verifyUrl = `https://www.google.com/recaptcha/api/siteverify` ;
const verifyResponse = await fetch ( verifyUrl , {
method: 'POST' ,
headers: { 'Content-Type' : 'application/x-www-form-urlencoded' },
body: `secret= ${ RECAPTCHA_SECRET_KEY } &response= ${ recaptchaToken } `
});
const verifyData = await verifyResponse . json ();
// Check if verification was successful
if ( ! verifyData . success ) {
return res . status ( 400 ). json ({ error: 'reCAPTCHA verification failed' });
}
// Check the score (0.0 to 1.0, higher is better)
if ( verifyData . score < 0.5 ) {
return res . status ( 400 ). json ({
error: 'Suspicious activity detected' ,
score: verifyData . score
});
}
// Proceed with login logic
// ... authenticate user with email/password ...
res . json ({ success: true , message: 'Login successful' });
});
app . listen ( 3000 , () => console . log ( 'Server running on port 3000' ));
Never expose your reCAPTCHA secret key in client-side code! Store it securely in environment variables on your server.
Test Your Integration
After completing the steps above, test your integration:
Open your app in a browser and navigate to your login form
Fill out the form and click submit
Check the network tab in your browser’s developer tools - you should see a request to recaptcha/api.js
Verify your backend receives and validates the token
Visit the reCAPTCHA admin console to view analytics and scores
During development, you may see lower scores. reCAPTCHA learns over time and considers factors like browsing history and mouse movements.
Understanding Scores
reCAPTCHA v3 returns a score between 0.0 and 1.0:
1.0 - Very likely a legitimate user
0.5 - Neutral (recommended threshold)
0.0 - Very likely a bot
You can adjust the threshold based on your needs. For example:
0.7+ for high-security actions (password changes, payments)
0.5+ for medium-security actions (login, contact forms)
0.3+ for low-risk actions (newsletter signup)
Common Pitfalls
executeRecaptcha is undefined
This happens when the reCAPTCHA script hasn’t loaded yet. Always check if executeRecaptcha is available before calling it: if ( ! executeRecaptcha ) {
console . log ( 'Execute recaptcha not yet available' );
return ;
}
Infinite loop with inline functions
Using inline functions for callbacks can cause infinite renders. Use useCallback: // ❌ Bad - inline function
const handleVerify = async ( token ) => { ... };
// ✅ Good - memoized with useCallback
const handleVerify = useCallback ( async ( token ) => { ... }, [ dependencies ]);
Make sure you’re using a v3 site key , not v2. They are not interchangeable. Check your key in the reCAPTCHA admin console.
Next Steps
Components Learn about all available components and their props
Guides Explore advanced features like Enterprise and custom containers
Examples Browse more real-world usage examples
API Reference Dive into the complete API documentation
Need Help?