This document discusses best practices for loading the reCAPTCHA script tag. This information is applicable to both reCAPTCHA v2 and v3.
Loading reCAPTCHA asynchronously
All versions of the reCAPTCHA can be loaded asynchronously. Loading reCAPTCHA asynchronously does not impact its ability to identify suspicious traffic. Due to the performance benefits of asynchronous scripts, loading reCAPTCHA asynchronously is generally recommended.
<script async src="https://www.google.com/recaptcha/api.js">
When loading reCAPTCHA asynchronously, keep in mind that reCAPTCHA cannot be used until it has finished loading. For example, the following code would likely break:
<script async src="https://www.google.com/recaptcha/api.js"></script>
<script>
// If reCAPTCHA is still loading, grecaptcha will be undefined.
grecaptcha.ready(function(){
grecaptcha.render("container", {
sitekey: "ABC-123"
});
});
</script>
In some situations, adjusting script ordering can be enough to prevent race
conditions. Alternatively, you can prevent race conditions by including the
following code snippet on pages that load reCAPTCHA. If you are using
grecaptcha.ready()
to wrap API calls, add the following code snippet to ensure
that reCAPTCHA can be called at any time.
<script async src="https://www.google.com/recaptcha/api.js"></script>
<script>
// How this code snippet works:
// This logic overwrites the default behavior of `grecaptcha.ready()` to
// ensure that it can be safely called at any time. When `grecaptcha.ready()`
// is called before reCAPTCHA is loaded, the callback function that is passed
// by `grecaptcha.ready()` is enqueued for execution after reCAPTCHA is
// loaded.
if(typeof grecaptcha === 'undefined') {
grecaptcha = {};
}
grecaptcha.ready = function(cb){
if(typeof grecaptcha === 'undefined') {
// window.__grecaptcha_cfg is a global variable that stores reCAPTCHA's
// configuration. By default, any functions listed in its 'fns' property
// are automatically executed when reCAPTCHA loads.
const c = '___grecaptcha_cfg';
window[c] = window[c] || {};
(window[c]['fns'] = window[c]['fns']||[]).push(cb);
} else {
cb();
}
}
// Usage
grecaptcha.ready(function(){
grecaptcha.render("container", {
sitekey: "ABC-123"
});
});
</script>
As an alternative, sites that use the v2 API may find it useful to use
the onload
callback; the onload
callback is executed when reCAPTCHA finishes
loading. The onload
callback should be defined before loading the reCAPTCHA
script.
<script>
const onloadCallback = function() {
console.log("reCAPTCHA has loaded!");
grecaptcha.reset();
};
</script>
<script async src="https://www.google.com/recaptcha/api.js?onload=onloadCallback”></script>
If loading reCAPTCHA asynchronously is not an option, including preconnect
resource hints for reCAPTCHA is strongly recommended. This will minimize the
amount of time that the script download blocks the parser.
Using resource hints
Including the following resource hints in the <head>
of the document will
reduce the amount of time that it takes to deliver the resources used by
reCAPTCHA. The preconnect
resource hint instructs the browser to establish an
early connection with a third-party origin.
<link rel="preconnect" href="https://www.google.com">
<link rel="preconnect" href="https://www.gstatic.com" crossorigin>
Lazy Loading
Generally speaking, the more context that reCAPTCHA has about a page, the better informed it is to determine whether user actions are legitimate. This is particularly true when using versions of reCAPTCHA that don’t rely on user challenges. Thus, waiting to load reCAPTCHA until a specific restricted action occurs (for example, form submission) is generally not recommended.