Manual Script Loading
By default, react-google-recaptcha automatically loads the Google reCAPTCHA script. For advanced use cases where you need full control over script loading, you can import the named export ReCAPTCHA and manage the script yourself.
import { ReCAPTCHA } from "react-google-recaptcha" ;
import ReactDOM from "react-dom" ;
const grecaptchaObject = window . grecaptcha ; // You must provide access to the google grecaptcha object.
ReactDOM . render (
< ReCAPTCHA
ref = { ( r ) => this . recaptcha = r }
sitekey = "Your client site key"
grecaptcha = { grecaptchaObject }
/> ,
document . body
);
When using the named export, you are responsible for:
Loading the reCAPTCHA script manually
Ensuring the grecaptcha object is available before rendering the component
Setting render=explicit in the script URL
When to Use Manual Loading
Multiple reCAPTCHA instances
Manual loading gives you more control when you need multiple reCAPTCHA widgets on the same page with different configurations.
Custom script loading strategy
You may want to use your own script loading solution for better performance or integration with your build system.
Server-side rendering (SSR)
Manual loading can help avoid issues with SSR frameworks where the script needs to load at a specific time.
Global recaptchaOptions
You can configure global options that affect how the reCAPTCHA script is loaded by setting window.recaptchaOptions before the component mounts.
window . recaptchaOptions = {
useRecaptchaNet: true ,
enterprise: true ,
};
These options must be set before the react-google-recaptcha component is first rendered.
useRecaptchaNet
If google.com is blocked in certain regions, you can use recaptcha.net as an alternative domain.
window . recaptchaOptions = {
useRecaptchaNet: true ,
};
This changes the script URL from:
https://www.google.com/recaptcha/api.js
to:
https://recaptcha.net/recaptcha/api.js
This is particularly useful for users in regions where Google services are restricted.
enterprise
If you’re using Google Enterprise reCAPTCHA, set this option to true:
window . recaptchaOptions = {
enterprise: true ,
};
See the Enterprise reCAPTCHA guide for more details.
Combined Example
window . recaptchaOptions = {
useRecaptchaNet: true ,
enterprise: true ,
};
This configuration uses the enterprise API via the recaptcha.net domain.
CSP Nonce Support
If your application uses Content Security Policy (CSP) headers, you can provide a nonce value for the dynamically loaded script:
window . recaptchaOptions = {
nonce: document . querySelector ( 'meta[name="csp-nonce"]' ). getAttribute ( 'content' ),
};
Complete CSP Example
<! DOCTYPE html >
< html >
< head >
< meta name = "csp-nonce" content = "random-nonce-value-12345" />
< meta http-equiv = "Content-Security-Policy"
content = "script-src 'self' 'nonce-random-nonce-value-12345' https://www.google.com https://www.gstatic.com;" />
< script >
window . recaptchaOptions = {
nonce: document . querySelector ( 'meta[name="csp-nonce"]' ). getAttribute ( 'content' ),
};
</ script >
</ head >
< body >
< div id = "root" ></ div >
< script src = "/bundle.js" ></ script >
</ body >
</ html >
The nonce value should be randomly generated on each page load and must match the nonce in your CSP header.
Language Configuration (hl parameter)
The hl prop allows you to display the reCAPTCHA widget in different languages:
< ReCAPTCHA
sitekey = "Your client site key"
onChange = { onChange }
hl = "fr"
/>
This displays the reCAPTCHA interface in French.
Common Language Codes
// English
< ReCAPTCHA sitekey = "key" hl = "en" />
// Spanish
< ReCAPTCHA sitekey = "key" hl = "es" />
// German
< ReCAPTCHA sitekey = "key" hl = "de" />
// Japanese
< ReCAPTCHA sitekey = "key" hl = "ja" />
// Chinese (Simplified)
< ReCAPTCHA sitekey = "key" hl = "zh-CN" />
Secure Token (stoken parameter)
The stoken parameter allows the reCAPTCHA to be used from different domains. This is useful for multi-domain applications.
< ReCAPTCHA
sitekey = "Your client site key"
onChange = { onChange }
stoken = "secure_token_value_here"
/>
Isolated Mode
The isolated prop creates a separate ID space for this reCAPTCHA instance, preventing interference with other reCAPTCHA installations on the same page.
< ReCAPTCHA
sitekey = "Your client site key"
onChange = { onChange }
isolated = { true }
/>
When to Use Isolated Mode
Plugin or widget development
If you’re building a plugin that will be embedded in third-party sites, use isolated mode to avoid conflicts with existing reCAPTCHA implementations.
Multiple independent forms
When you have multiple forms on a page that should function completely independently.
The default value is false. Only enable isolated mode when necessary, as it adds overhead.
Async Script Loading Callback
The asyncScriptOnLoad callback is invoked when the Google reCAPTCHA script has finished loading:
function onScriptLoad () {
console . log ( "reCAPTCHA script loaded successfully" );
}
< ReCAPTCHA
sitekey = "Your client site key"
onChange = { onChange }
asyncScriptOnLoad = { onScriptLoad }
/>
This is useful for tracking when the script loads or for performing initialization that depends on the reCAPTCHA script being available.
Complete Advanced Example
Here’s a complete example combining multiple advanced features:
import React from "react" ;
import ReCAPTCHA from "react-google-recaptcha" ;
// Set global options before component mounts
if ( typeof window !== 'undefined' ) {
window . recaptchaOptions = {
useRecaptchaNet: true ,
enterprise: false ,
nonce: document . querySelector ( 'meta[name="csp-nonce"]' )?. getAttribute ( 'content' ),
};
}
function AdvancedForm () {
const recaptchaRef = React . useRef ();
const handleScriptLoad = () => {
console . log ( "reCAPTCHA script loaded" );
};
const handleChange = ( token ) => {
console . log ( "Token:" , token );
};
const handleSubmit = async ( e ) => {
e . preventDefault ();
const token = recaptchaRef . current . getValue ();
if ( ! token ) {
alert ( "Please complete the reCAPTCHA" );
return ;
}
// Submit form
await fetch ( '/api/submit' , {
method: 'POST' ,
body: JSON . stringify ({ token })
});
recaptchaRef . current . reset ();
};
return (
< form onSubmit = { handleSubmit } >
< ReCAPTCHA
ref = { recaptchaRef }
sitekey = "Your client site key"
onChange = { handleChange }
asyncScriptOnLoad = { handleScriptLoad }
hl = "en"
theme = "dark"
size = "normal"
isolated = { false }
tabindex = { 0 }
/>
< button type = "submit" > Submit </ button >
</ form >
);
}
export default AdvancedForm ;
Styling the Container
The component accepts any additional props that will be passed to the container div, allowing you to add custom styling:
< ReCAPTCHA
sitekey = "Your client site key"
onChange = { onChange }
className = "my-recaptcha"
style = { { display: 'inline-block' , marginTop: '20px' } }
id = "custom-recaptcha"
/>
All props not specifically used by reCAPTCHA are passed through to the container div, giving you full control over styling and attributes.