Google has recently introduced a new update to their reCaptcha service called the Invisible reCaptcha. It’s based on the same technology as the previous version (the “no captcha reCaptcha”), but simplifies the process to remove even the checkbox step. The captcha functionality is now tied completely to the submit button.
This article will cover the process of installing the Invisible reCaptcha on your site, detailing both the front and backend functionality. JavaScript will be used on the frontend and PHP on the backend.
We’ll split this article into three parts: Requesting the reCaptcha keys, Implementing the frontend, and Implementing the backend.
Requesting the reCaptcha keys
The first and easiest step to installing reCaptcha will be to request the public and private keys from the reCaptcha website. These are used as a unique site identifier, and also to prove that the real site owner is verifying their user’s identity.
Visit the reCaptcha website and click Get reCaptcha. Select Invisible reCAPTCHA from the radio box, enter your site’s domain(s) and hit register. You’ll now be given your personalized Site Key (public key) and Secret key (private key). Do not share your Secret Key with anybody, as otherwise they will be able to impersonate you.
Implementing the Frontend
To get started in the actual implementation, we’re first going to create a very simple HTML form named form.html
.
<!-- form.html -->
<form id="contact" method="post">
<label>First <input name="first" type="text" /></label>
<label>Last <input name="last" type="text" /></label>
<button>Submit</button>
</form>
Now let’s add some reCaptcha functionality. First you’ll need to link the reCaptcha API script in the tag.
<!-- form.html -->
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
This is used to do two things:
- Prevents the submit button from immediately navigating away when clicked
- Contacts Google with relevant user metrics to determine if they’re suspicious or not
In the previous version of reCaptcha, we would normally insert a new element above the submit button to be clicked. In the Invisible reCaptcha, we integrate directly with the submit button instead.
<!-- form.html -->
<button class="g-recaptcha" data-sitekey="" data-callback="captchaSubmit">Submit</button>
You’ll need to update the data-sitekey
field with your own key from Google. Site keys are unique but are not secret, so don’t worry that this is public facing.
At this point the reCaptcha library will be loaded and will prevent the submit button from being clicked. This is where the data-callback
field comes in. A callback function is a special type of function that is executed after a certain task has finished. In this case, it’s a JavaScript function named captchaSubmit
that will be called after the button is clicked and Google’s measured the user metrics. As such, we’ll need to create a new JavaScript function with that name.
<!-- form.html -->
<script>
function captchaSubmit(data) {
document.getElementById("contact").submit();
}
</script>
This code first accepts an argument (here called data
) which carries the reCaptcha response data. You could add any client-side verification in at this point, but we’re simply going to submit the form.
Also note that getElementById("contact")
refers to the ID used by the form, so it must match your form’s ID. Ours is simply named “contact”.
With these changes, our frontend is fully functional. Once submit is clicked the script will send data to Google and then complete the form. All that’s left is visual changes and cleanup.
You might have noticed the reCaptcha badge in the lower right corner of the screen. This exists to let users know that a form is protected by reCaptcha now that the verification checkbox has been removed. It’s possible to hide this badge however by configuring it to be inline, and then modifying it with CSS.
<!-- form.html -->
<style>
.grecaptcha-badge {display: none;}
</style>
<button class="g-recaptcha" data-sitekey="" data-callback="captchaSubmit" data-badge="inline">Submit</button>
Please note that because Google collects user information to enable reCaptcha functionality, their terms of service require you to alert users to its use. If you hide the badge you’ll want to add an informational paragraph somewhere on the page instead.
Finally, let’s prepare for the next step. Add an action
attribute to your form so we can send our results to the next page.
<!-- form.html -->
<form id="contact" action="results.php" method="post">
Now with the frontend code finished, let’s put it all together. Our completed form.html
page now looks like this:
<!-- form.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Form</title>
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
<script>
function captchaSubmit(data) {
document.getElementById("contact").submit();
}
</script>
<style>
.grecaptcha-badge {display: none;}
</style>
</head>
<body>
<form id="contact" action="results.php" method="post">
<label>First <input type="text" name="first"></label><br>
<label>Last <input type="text" name="last"></label><br>
<button class="g-recaptcha" data-sitekey="" data-callback="captchaSubmit" data-badge="inline">Submit</button>
<p>Please note this form is protected by reCaptcha.</p>
</form>
</body>
</html>
Implementing the Backend
The backend is where we validate the user’s input, and decide which actions to take as a result.
We’ll start by creating a new file called results.php
. Note that the file extension should be .php, as it will require server-side code.
<!-- results.php -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Results</title>
</head>
<body>
<p>Thank you for entering the form.</p>
</body>
</html>
We’ve started with an empty template that simply thanks the user for submitting the form. Form data will be visible in the $_POST
variable, which we’ll use shortly.
Next up is processing the reCaptcha response to verify the user is human. We’ll start by setting up our variables.
// results.php
// reCaptcha info
$secret = "";
$remoteip = $_SERVER["REMOTE_ADDR"];
$url = "https://www.google.com/recaptcha/api/siteverify";
$secret
is your Secret Key from reCaptcha. As this is being entered on the server-side, this will be completely hidden from the user.$remoteip
is the user’s IP address. This is an optional field, though improves accuracy.$url
is the URL we need to query to receive our response from reCaptcha.
Next up is collecting and processing the form data. $response
will hold a reference to the user’s session, which is necessary for getting a proper response back.
// results.php
// Form info
$first = $_POST["first"];
$last = $_POST["last"];
$response = $_POST["g-recaptcha-response"];
Finally we have all the ingredients we need to query reCaptcha and verify the user’s humanity. For this purpose we’ll use a curl script.
// results.php
// Curl Request
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, array(
'secret' => $secret,
'response' => $response,
'remoteip' => $remoteip
));
$curlData = curl_exec($curl);
curl_close($curl);
$curlData
has now captured the JSON response from reCaptcha. To make sense of this response, we’ll decode the JSON into an associative array.
// results.php
// Parse data
$recaptcha = json_decode($curlData, true);
Finally we can simply read the “success” property to receive our result.
// results.php
if ($recaptcha["success"])
echo "Success!";
else
echo "Failure!";
Once again, let’s put it all together to see our (hopefully) working script.
<!-- results.php -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Results</title>
</head>
<body>
<p>Thank you for entering the form.</p>
<?php
// reCaptcha info
$secret = "";
$remoteip = $_SERVER["REMOTE_ADDR"];
$url = "https://www.google.com/recaptcha/api/siteverify";
// Form info
$first = $_POST["first"];
$last = $_POST["last"];
$response = $_POST["g-recaptcha-response"];
// Curl Request
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, array(
'secret' => $secret,
'response' => $response,
'remoteip' => $remoteip
));
$curlData = curl_exec($curl);
curl_close($curl);
// Parse data
$recaptcha = json_decode($curlData, true);
if ($recaptcha["success"])
echo "Success!";
else
echo "Failure!";
?>
</body>
</html>
Please note that this example doesn’t include error handling, such as if this page were accessed directly.
In this example we’re only printing “Success” or “Failure” based on the result of the captcha, but you can extend this to instead send an email, enable a user registration, or allow another action.
With all three pieces of the puzzle put together, we’re finished! You should now have a working implementation of Google’s Invisible reCaptcha on your form.
For more technical details or other questions, reCaptcha’s documentation can be found on Google’s Developer site.
Doesn’t work for me.
Hi J.C.,
What problem are you having exactly? You may be able to look at your Javascript console to view any errors reported.
Best of luck!
Hi there,
Thanks for the tutorial, it’s a really in-depth and concise explanation.
Unfortunately however I end up with an eternal cycle of Captcha puzzles which pop up when my button is pressed. Any idea how to get around this one?
Give it a try: http://davidfallows.net/
Thanks!
David.
Hi David!
Thanks for the kind words.
From a quick look at your site, the page is throwing a Javascript error when you press Submit (as shown in the Console). The reason is that it’s trying to bind to the form ID, but it can’t find it. It looks like you have a duplicate #contact ID. Try running
document.getElementById("contact")
in your console to see.Giving it a unique ID and then updating the script tag in the header should resolve the problem.
I’ll update the article to make this more explicit.
Cheers.
Thanks very much! I’m very busy over the next couple of days, so I’ll try again on Thursday/Friday. 🙂
Tried this, thanks for sharing! Seems to work ok-ish, only problem is I’m getting a 3×3 image grid before I can confirm the reCaptcha. Obviously not very invisible. Any reason for this?
Hi Kevin,
This occurs when Google suspects that you may be a spambot, and so they apply a higher level of scrutiny to your submission. The same occurred with the previous Checkbox method.
The reason for this is likely to be that you submitted the form many times while installing/testing it, and that behavior would look suspicious to Google. It should subside over time in that case. Another possibility is that you’re blocking information that Google uses to analyze your input (eg. Javascript, cookies), and so the only way they can verify if you’re a real user is to pop up the extra 3×3 image squares.
Hopefully that helps. I’m glad the installation itself worked for you.
Hi,
Excellent!!!
it’s working perfectly!!!!
I have two forms but the captcha only working with the first form not sure what’s happening with the second form, I curious to know how its work with multiple forms in a single page.
Thanks!
Hi, is any chance to work in multiple forms in the same page?
Works! Thankyou!
Super helpful. Thanks
Works! This is the best walkthrough I’ve found so far! Thank you!
Thanks, it’s working perfectly! 🙂
Thanks for your demo that’s very usefull !
How can I implement 2 invisible captcha on a same page ?
This worked great for me! The instructions on Google weren’t super clear to me, but this was perfect.
Indeed an excellent way of explaining the process of implementing invisible captcha. However, how on earth do I get the body section part:
First
Last
Submit
Please note this form is protected by reCaptcha.
to work with my existing form :
http://www.namibia-safari-holidays.com/en/contact.html
which directs straight to my server at one.com
I am clueless in this regard.
Many thanks
Thank you this worked for me.
From Belgium (Europe) : Thanks very much
Hi
I only need to enable a button after google recaptcha is validated. I only have basic knowledge of coding.
Pls can you help with this.
Thanks in advance.
Hi,
I tried adding the invisible Captcha code and it is not working as we still getting spam filling out our form.
https://www.followthecamino.com/blog/your-camino-training-plan/
I check the analytics Graph and it said no captchas, no Pass and No fail.
I have followed your instruction as best as I could but I am not sure what I did wrong.
Can you help me?
Just in case this helps anyone else (I was struggling to figure out why my set-up wasn’t working for hours) – I was setting this up on my local WAMP environment and I kept getting the “Failure!” error message over and over again. Turns out the reason was that I was getting a Curl SSL error that was causing the data to come back from reCaptcha as null. To fix, I added this line to the Curl request: curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);. There are other methods to fix the issue, as detailed here: https://stackoverflow.com/questions/29822686/curl-error-60-ssl-certificate-unable-to-get-local-issuer-certificate/34883260, but that was the only one I could get to work for me.
Anyway, hope that helps someone!
function onload() {
var element = document.getElementById(‘partyIdForm:searchButton’);
element.onclick = validate;
}
function onloadCallback(token) {
document.getElementById(‘partyIdForm:searchButton’).click();
}
function validate(event) {
widgetId=grecaptcha.render(document.getElementById(‘partyIdForm:searchButton’), {
‘sitekey’ : ‘6LdOL0IUAAAAABE6T7WkBPLgtnIvZhxTU9lLgPI6’,
});
event.preventDefault();
grecaptcha.execute();
}
And calling onload script each time form loads, with this invisible recaptch is working for single click of search button, which displays result in same form below search, so form is not reloaded.
After results are displayed invsible recaptcha icon is not shown.
I want to call recpatcha on every click of search
Lovely stuff, thanks for the article
What if i want to test it locally.what should be used as domain.
Right now i m using domain name as localhost but not working.
so any one can able to give solution please provide me as soon as possible
You are an angel! Thank you!
This worked for me. The issue I am facing is it works on desktop and iphones perfectly fine but on android devices when I click on submit button, nothing happens. I have to try several time to get the invisible captcha validation. When I refersh the page, it works and this is happening very intermittently. sometimes it works and sometimes it doesnt work on android. There is no specific pattern to debug. Any thoughts on this?
Awesome, I had a problem with CURL, but i figured out. Thanks a lot
You can do with an ajax call
Great!! Thank you. I was having a lot of trouble with the checkbox version, and this one (invisible) works perfectly. The only detail is that the required attribute stops working.
Excellent simple explanation! It worked great.
Nice tut, but it really sucks that its not possible to c&p parts of your code tags
You’re absolutely right. We previously used a different formatter for code tags but it conflicted with the theme and caused other problems. This version works, but I agree the copy/paste behaviour is frustrating. Sorry for the trouble!
Future edit: We’ve fixed this issue now. Thanks for reporting it!
funcionando !!!!! gracias
Thanks for the help!
One quer, How google will recognize that who is submitting the form. Human or Robot? Can you explain
Google uses a heuristical approach which analyzes information about your browser and current session to determine the likelihood of you being a bot. This is returned to the site owner who can then reject you on that premise.