Adding Google ReCAPTCHA 3 to the Contact Form

Google’s reCAPTCHA v2

If you’ve spent any amount of time on the web in the last decade or so, you’ve no doubt clicked hundreds of “I’m not a robot” check boxes only to be asked to then select all of the images with street signs or traffic lights or fire hydrants. And I’m willing to bet that after selecting all of the correct images, you’ve sometimes then been asked to do it all over again. When the checkbox works, it’s not that big of an extra ask from your website visitor. But when it doesn’t work, it can actually be frustrating and annoying enough to risk the visitor leaving your site.

These are forms of CAPTCHAs, “Completely Automated Public Turing test to tell Computers and Humans Apart,” which is any sort of test that is intended to help a website or app separate human activity from automated activity. This sort of test is useful both on a site like TicketMaster where it should (but often doesn’t) help prevent bots from buying up all of the tickets to later scalp at elevated prices as well as on a lowly contact form like the one I have on my contact page.

For a deep dive into the history and purpose of CAPTCHAs, check out the Wikipedia article. The short of it is that website/app developers are in a never-ending, ever-escalating battle with spammers, scalpers, and other bad actors in an attempt to keep their services useful for everyone else to enjoy.

Google’s reCAPTCHA service is probably the most commonly used CAPTCHA service around these days. Instead of showing garbled text to try and trick a bot and not trick a human, it has evolved to instead look at the app user’s activity to figure out if that activity is human-like enough to allow past the form. The most popular version of Google reCAPTCHA in use right now is version 2, the “I’m not a robot” checkbox thing.

Google’s reCAPTCHA v3 is Google’s attempt to solve the human v. bot problem without the potential of annoying legitimate humans. Instead of asking the user of the app to do anything beyond just normally using the app, v3 instead generates a score, based on the user’s activity (moving the mouse, filling in the form, etc.), of how likely it is that the user is a human vs. a bot. It’s then left to the website to look at the score and decide if the submitted form should be acted upon or ignored. Same ability to weed out the bad guys without the potential of annoying the good guys!

Fortunately for us developers, adding v3 to your own website is both free and easy. The first step is to sign up for a Google Developer account at https://developers.google.com/ then head on over to the reCAPTCHA Admin Console at https://www.google.com/recaptcha/admin/ to configure the service for your website. Aside from picking v3 here, you’ll also want to specify which domains, such as “moshteitelbaum.com,” are allowed to use this and to take note of the site keys that Google generates for you.

Adding the service to the front-end is a relatively simple 3 step process:

  1. Register for a Google Developer account and configure your CAPTCHA,
  2. Add the CAPTCHA code to your front-end, and
  3. Add some code to your back-end form processor to evaluate the CAPTCHA-generated score.

Google Developer Account

Google makes a ton of services available to developers, many of them free, so you should absolutely sign up for a Google Developer account and get to playing with what they offer. It starts by heading over to https://developers.google.com/ and creating your account. Then learn more about the service, read the docs, and register a site on which you plan to use the reCAPTCHA. Specify a label, the reCAPTCHA type (v3), and the domain or domains on which this reCAPTCHA’s API keys should work. Note that Google will generate 2 API keys for this site, a public “site” key and a private “secret” key.

reCAPTCHA admin settings

Add reCAPTCHA to Your Front-End

Adding the service to your front-end requires adding/updating 3 bits of code:

  1. Load the reCAPTCHA JavaScript API by adding the following to the rest of your JavaScript (which should be at the end of the rest of your content):
  2. Write a quick callback function to submit the form, including the reCAPTCHA-generated token, when the form’s submit button is clicked:
  3. Finally, update the form submit button to include some reCAPTCHA-specific data properties: Note the data-* properties: data-sitekey is the site key that Google generated for your site, data-callback is the name of your callback function created in step 2, and data-action is the name of the action associated with the form submission. You can specify multiple actions throughout your site to use the same reCAPTCHA configuration in multiple situations (e.g., “contactFormSubmit,” “registrationFormSubmit,” etc.).

Refresh the page and you’ll know it’s working if you see the little reCAPTCHA icon floating in the bottom-right corner of the screen.

Process the Form on the Back-End

Now that the front-end is configured as above, when your user submits the form, there will be a new POST parameter,g-recaptcha-response, included along with the rest of your form parameters. This is NOT the reCAPTCHA score; instead it is a unique token, valid for only 2 minutes, that you submit to Google for verification. The response to that request includes the score.

Verification, and how you handle the result, is also pretty straight forward. Let’s look at the code and then break it down.

We start by defining our threshold for what we consider an acceptable score. The verification request returns a score between 1.0 (almost certainly a human) and 0.0 (almost certainly a bot). A good default to start with is 0.5 and then you can tweak that over time as you review your results.

Then we send our request to Google for verification via a POST request with three parameters:

  • secret - Your Google reCAPTCHA secret API Key.
  • response - The value of the g-recaptcha-response POST parameter sent from the front-end.
  • remoteip - Optionally, the submitter’s IP Address

A side note here, this is making a request of a third-party service over which you have no control and into which you have no insight. It’s Google, so it’ll probably complete pretty quickly but it may not. This could be a good time to look into handling all of this in a separate thread.

The verification request results in a response that is a JSON object:

The rest of the code is simply processing the response. Specifically, it checks 3 things: is the action the correct one that we’re expecting, was the verification successful, and did the score meet our threshold.

And that’s it. Now you know how to easily filter out the bots without annoying your humans.

2021-02-04 15:07:45