Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling errors with reCAPTCHA v3

I have reCAPTCHA v3 set up on my page:

<script src="https://www.google.com/recaptcha/api.js?render=MY_KEY"></script>

If internet connectivity becomes unavailable or unreliable, reCAPTCHA will insert this HTML at the bottom of my page:

<div>
  <div>
    Could not connect to the reCAPTCHA service. Please check your internet connection and reload to get a reCAPTCHA challenge.
  </div>
</div>

I would much rather handle this error in my JavaScript so I can display it to the user in a better way. However, the documentation for v3 doesn't indicate how to do this.

Any thoughts on how to catch this error?

like image 691
Brad Avatar asked Nov 07 '25 23:11

Brad


2 Answers

The year is 2025, five years after the initial post. reCAPTCHA v3 still adds error messages to the <body> tag. Hello Google!

To reproduce the issue, follow these steps:

  1. Load reCAPTCHA v3 as described in the documentation:
    https://www.google.com/recaptcha/api.js?render=your_reCAPTCHA_site_key.
  2. Call grecaptcha.execute('your_reCAPTCHA_site_key', {action: 'submit'}). It succeeds as expected.
  3. Disable your network connection (e.g., turn off the Ethernet adapter).
  4. Call grecaptcha.execute('your_reCAPTCHA_site_key', {action: 'submit'}) again. After 20 seconds, it appends an error message directly to the <body> tag.

After troubleshooting, I came across this section of the documentation:

How can I customize reCAPTCHA v3?
The JavaScript API available for Invisible reCAPTCHA also works for v3. Simply use the JavaScript API to explicitly render reCAPTCHA with a v3 site key to access options such as repositioning the badge or changing the theme.
When rendering reCAPTCHA v3 with this method, remember to set the size parameter to invisible and use the client ID returned by grecaptcha.render when calling grecaptcha.execute instead of the site key.

I decided to test this alternative approach. Here's what I tried:

  1. Load the script as described in the Invisible reCAPTCHA documentation:
    https://www.google.com/recaptcha/api.js?render=explicit&onload=my_function.
  2. Render the widget using:
    const widget_id = grecaptcha.render(container, {
      sitekey: 'your_reCAPTCHA_V3_site_key',
      size: 'invisible',
      'error-callback': () => console.error('reCAPTCHA error'),
    });
    
  3. Call grecaptcha.execute(widget_id, {action: 'submit'}). It succeeds.
  4. Disable the network connection (e.g., turn off the Ethernet adapter).
  5. Call grecaptcha.execute(widget_id, {action: 'submit'}). This time, it returns a token and does not add an error message to the <body> tag. Phew!
  6. As expected, sending the token to the Google backend (https://www.google.com/recaptcha/api/siteverify) results in:
    {
      "success": false,
      "error-codes": ["browser-error"]
    }
    

Additional Observations:

  • If the code is used with a reCAPTCHA v3 siteKey, the 'error-callback' is not called when an error occurs.
  • If the code is used with a reCAPTCHA v2 siteKey, the 'error-callback' is called as expected.
like image 183
Milen Yordanov Avatar answered Nov 12 '25 02:11

Milen Yordanov


You can put an onerror handler in the script tag itself:

<script src="https://www.google.com/recaptcha/api.js?render=MY_KEY" onerror="error_handler()">

But I think what you want is more along the lines of what reCAPTCHA v2 offers:

widgetId = grecaptcha.render('example1', {
    'sitekey' : 'your_site_key',
    'theme' : 'light',
    'error-callback' : error_handler()
});

I doubt that works but there is another way. You just need to monitor the DOM for changes since you know that when there is an error Google will add a div to your page. You can do that with MutationObserver.

var m = new MutationObserver(function (mutationRecords) {
    this.disconnect();
    error_handler();
});
m.observe(document.body, {childList: true});

{childList: true} tells the MutationObserver to detect nodes added to the DOM and passes them to the callback function as the parameter mutationRecords (which contains array of MutationRecord objects). From there it's up to you what to do next.

This should at least be enough to get you started!

like image 22
PHP Guru Avatar answered Nov 12 '25 02:11

PHP Guru



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!