Italo Baeza
May 27 · 3 min read

In news regarding bots, I think you may know that Laravel already comes with a way to stop bots in their tracks using a throttler for failed logins. That is usually enough for any simple application, since most of the heavy application logic is under an authenticated user.

Now, let’s add some forms here and there that should work without any login and now we have a problem. How we can check that is was filled by a Human and not a Robot, apart from the “V14GR4 D1SC0UNT” text?

Enter reCAPTCHA v3.

How reCAPTCHA v3 works?

Crash course of reCAPTCHA v3.

A simple tutorial for reCAPTCHA v3 from Google itself.

reCAPTCHA v3 works behind the curtains. A JavaScript generates a key that identifies the interaction, like mouse movements or browser status. That same script sends that information to reCAPTCHA servers, which calculates the odds of being done by a human or robot, instead of using a reCAPTCHA box the user would fill manually.

Once the Request is received by your application, it uses the key received along the data to ask reCAPTCHA servers about the interaction. You can do anything with this information.

For example, if the threshold is high, you can process a form like it was nothing. If was low, you can add an additional step like sending an email to complete the processing.

You can check a demo in Google’s Appspot.

Using reCAPTCHA v3

An official PHP client for reCAPTCHA v3 is available in Packagist, so no need to create your own. Just tell Composer to install it in your project.

composer require google/recaptcha "^1.2"

There are also instructions about how to set it up, but everything can be summarized in just a few lines. You can just use the reCAPTCHA inside your Controller or (hopefully) a Middleware:

public function contactForm(Request $request)
{
// Validate...
$response = (new \ReCaptcha\ReCaptcha($secret))
->setExpectedAction('contact_form')
->verify($request->input('_recaptcha'), $request->ip());

if (!$response->isSuccess()) {
abort();
}
if ($response->getScore() < 0.6) {
return response()->view('challenge');
}
return response()->view('success');
}

The gist

First, you should have a secret to use the service. Once you got one from your Admin interface for v3, you put it as a parameter to instance a ReCaptcha class. This class is in charge of communicating with reCAPTCHA servers.

I would have preferred a PSR-18 compatible way to do it, so you could use Guzzle or any other HTTP Client of your choice, but at least they offer multiple ways to reach reCAPTCHA servers.

Then, you verify the name of the input key you are using to receive the reCAPTCHA token. You can use g_recaptcha, _recaptcha, recaptcha_token, anything from your form as long you can retrieve it.

The isSuccess() method checks if the response to reCAPTCHA is successful or not. If not, then you should drop the Request entirely since someone or something is modifying the Request.

Then, the getScore() method allows you to check if the score is above the threshold or not. When the threshold is too low, it was probably filled by a robot, so you could take some counter-measures to ensure that, if it was really a human disguised as a robot, can still process the Request. For example, you can send an email, or add a challenge like a random question.

That’s pretty much it. The other methods are for much more strict verification and analytics, that you should totally use if you expect robots in your site.


By the way, I implemented this myself. It works as a middleware so it doesn’t clutter up your Controllers. Give it a chance if you want something working out-of-the-box.

The Startup

Medium's largest active publication, followed by +502K people. Follow to join our community.

Italo Baeza

Written by

Graphic Designer. Web Developer Full Stack. Retired Tech & Gaming Editor.

The Startup

Medium's largest active publication, followed by +502K people. Follow to join our community.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade