Google recently released a new way to prevent spam: the invisible reCaptcha. The HubSpot product team is introducing this new tool on all forms in our product soon, because it'll help customers generate more legitimate leads. Want to give it a try? You only need a few steps to add invisible reCaptcha to your website.

What is Invisible reCaptcha?

You're probably already familiar with reCaptcha, the checkbox you sometimes have to click on before you can submit a form on a website. If the algorithm thinks that you're a human, it will validate the reCaptcha without any further action on your part. If not, it'll serve up a bunch of images that you'll have to categorize before you can continue.

Tough on bots, easy on humans

So what's invisible reCaptcha? Well, it's actually exactly the same - it just doesn't have a checkbox. In fact, you won't see the field at all. Like with a traditional reCaptcha, an additional challenge will sometimes appear if it thinks you're not a human, but with invisible reCaptcha, this happens when you submit the form (and the submission will really be sent once you validate the image test) instead of when you tick the checkbox.

You can give it a try here to see the full behavior.

So is it really invisible? Not completely. As Google captures user information from your website, you'll need to warn your users by displaying their Privacy policy and Terms and conditions. This visual is implemented by Google, but there are a few options available (see the section on personalization below).



Installing invisible reCaptcha from scratch

Let's add invisible reCaptcha to a website.

First, we need to register on this page to get an API key. Choose 'Register a new website', then click on 'invisible reCaptcha'. Entering a domain isn't necessary, but it can help prevent someone from using your key, so we'd recommend entering it if you know where your reCaptcha will live. If you don't want to put a domain, don't forget to uncheck the option in advanced settings.

You will get two keys: a public one, which will be used for the front end call, and a private one, for back end verification (which you shouldn't share).

Front end steps

Now we can really start. First, we'll need to include Google's script:

This code contains all the logic for reCaptcha. Then, we can simply bind the captcha to a button:

That's the biggest change compared to a traditional Google reCaptcha: the challenge is now deeply linked to the submission. Let's take a closer look at what we just wrote. The class "g-recaptcha" is required, since it tells Google JavaScript where to look for reCaptcha's information. Also, don't forget to add your own key as an attribute and change the action to send your form to your endpoint. We now have to make our own "onSubmit" function to handle reCaptcha's response.

This function will just submit the form, but you can add any validation you want at this point. Keep in mind that everything here will be executed after the person completes the reCaptcha.

At HubSpot, we approached this problem a bit differently. We needed our form validation to happen before we displayed any potential reCaptcha to the visitor. For example, if the email address isn't formatted correctly, or if a required field is absent, we want to handle that first, which is why we didn't bind reCaptcha directly to the submit button.

Fortunately for us, Google offers a second option, which enables us to treat the invisible reCaptcha as a part of our form:

As you can see, the reCaptcha is now in its own <div> and isn't attached to our submit button anymore. The challenge won't appear when the user clicks on this button, but instead whenever you tell it to by calling this function:

This gives you perfect freedom on the order in which you decide to run functions. For example, you can call one of your endpoints first, wait for its response, then show the reCaptcha test after. But there are tons of other possible use cases, and you can time the challenge in whatever way works best for your situation.

We should note that the "execute" function call works perfectly when there's only one reCaptcha rendered on the page. But as soon as you have two of them (invisible or not), they become unusable. Think about it - how would the Google script know which challenge you want to render? The one linked to your first form? Or the second one? Therefore, if you have multiple reCaptchas on a page, you need a way to identify which is which.

So here's the solution we chose to implement at HubSpot, because we needed to give customers the ability to put several forms on their pages, with or without reCaptcha. This solution also similar to the way you'd implement a normal reCaptcha, so it might be the easiest solution if you're swapping your traditional reCaptchas for invisible reCaptchas.

We add a loading function to the Google script call:

We also must be careful not to forget the last parameter, because you'll need it to make several reCaptchas work at the same time.

Now let's create our loading function:

There are other parameters we could add to this render function, but we'll touch on them later (see the personalization section). You can see that the rendering function returns an ID - it's important to save this. For example, if you code in ReactJS (like we do at HubSpot), this can be an attribute of the state of your component. But whatever language you use, saving it is the important part. Once you do that, every reCaptcha will have a unique ID, known both by our program and by Google.

We can then call our challenge by writing:

And that's it! Note that you can also reset a reCaptcha (to force your user to complete it again) by calling:

In short, these are the steps you need to implement a solution for multiple reCaptchas on your front end:

  1. Call the Google reCaptcha script
  2. Implement a loading function, that saves the widgetId of your reCaptcha (and that's also where you have the ability to customize it - see the personalization section)
  3. Call the execute function whenever you need it (for example, after form validation)
  4. Catch the response in a callback function and submit your form

Now that our front end is ready, let's check the visitor's response.

Backend verification

Once we receive our form submission in our backend service, we have to check that the given reCaptcha response is correct.

First, how is the response passed to our service? In most cases, an attribute "g-recaptcha-response" is added as parameter, and sent through the POST request at submission time.

If you'd like to pass the response manually, you can call this function:

In any case, you'll receive a response that's a long string of letters and numbers.

Then we'll call Google API to check this response:


Method: POST

Body parameters:

  • response: the reCaptcha's response we got on the submission
  • secret: the secret key we were given by the Google admin captcha interface
  • remoteip: the user's IP address (optional)


The API's response will look like this:

  "success": true|false,
  "challenge_ts": timestamp,
  "hostname": string,
  "error-codes": [...]

The most important part is the "success" parameter, which gives you the necessary information to accept or reject the submission. As for the other information in the response, the "challenge_ts" is the time when the reCaptcha challenge was rendered (ISO format yyyy-MM-dd'T'HH:mm:ssZZ), and the "hostname" shows the website where the reCaptcha was solved.

In short, all you need to do is:

  1. Call Google's API with your private key and the reCaptcha response
  2. Check the "success" attribute of the API's response


Now that we have invisible reCaptcha working on our website, let's see what options we have to customize it.

If we go back to our rendering function: addition to the "sitekey" and "callback", there are a few other parameters we can add to this call.


This might be the most important customization you might want to do. The badge is the visual that displays Google's terms and conditions. In normal reCaptchas, this is the field containing the checkbox.

There are three different badge options that Google offers for invisible reCaptcha:

  1. bottomright (default)
  2. bottomleft
  3. inline

The "inline" parameter will render the object as close to a normal field as possible.



The two other options are very discreet. They render the badge on a bottom corner of your page (left or right, depending on which option you choose). The badge follows your screen as you scroll and an animation shows the full badge (see above) on hover.

Screen Shot 2017-07-25 at 3.22.11 PM

Just be careful that this badge doesn't cover up anything important on your website! Because we don't know what type of content our customers might have on their pages, and because we use the bottom corners of a webpage for HubSpot's lead flows feature, we chose to keep the badge inline for our customers.

It's also helpful to place the badge inline if you want to apply your own CSS to it. But do remember that you agreed to show Google's Terms and conditions when you registered for an API key - so don't hide it, please. And while it is possible to make the badge disappear completely with CSS, we wouldn't recommend it.


You can also change the type of challenge that will show up:

  1. image (default)
  2. audio


Screen Shot 2017-07-25 at 3.42.18 PM

 Screen Shot 2017-07-25 at 3.42.26 PM-1

Image reCaptcha

Audio reCaptcha

Whichever you choose, reCaptcha will show an icon so that users can switch between types, so that the challenge is accessible for everyone.


This option can be useful if other elements on your page use tabindex and you want to make the navigation easier. The default value is "0", but you can change it so that your user can focus on the challenge after a certain amount of "tab" hits.

Note that the three parameters above also use the "data-" prefix if you use a <div> to render your invisible reCaptcha.


By default, Google's algorithm detects the user's language and applies it to the reCaptcha, but if you'd like, you could override it. To do that, you can add the parameter ("hl") when introducing Google Javascript:

For example, here it's overriding the language reCaptcha's language to French. The full list of languages and their codes is available here.

In conclusion

Invisible reCaptcha has worked quite well for us so far. After extensive testing, it doesn't seem less reliable than its predecessor, and it's one less click needed to change a simple website visitor into a lead in our users' databases. And as you can see, the implementation isn't painful as long as you have good documentation. You can also check Google developer's guide for a more thorough explanation of invisible reCaptcha. We hope that this quick tutorial helps you put an invisible reCaptcha on your website in no time. If you happen to have any questions, let us know in the comments.


Recommended Articles

Join our subscribers

Sign up here and we'll keep you updated on the latest in product, UX, and engineering from HubSpot.

Subscribe to the newsletter