Reader Stacks

Adding Google reCAPTCHA to a Laravel Form

A direct reCAPTCHA v3 integration — verify the token server-side against Google's API yourself, rather than depending on a third-party wrapper package that may or may not still be maintained.

Adding Google reCAPTCHA to a Laravel Form

reCAPTCHA blocks a large share of automated form spam without an explicit challenge (reCAPTCHA v3 scores requests invisibly rather than showing a checkbox or image puzzle). It can be integrated with a small amount of direct code rather than depending on a third-party Laravel wrapper package — worth knowing since community CAPTCHA packages come and go, and the underlying API call is simple enough not to need one.

1. Get keys and add the script

Register the site at Google's reCAPTCHA admin console to get a site key and secret key. Add the script and hidden token field to the form:

<script src="https://www.google.com/recaptcha/api.js?render={{ config('services.recaptcha.site_key') }}"></script>
<form method="POST" action="/contact">
    @csrf
    <input type="hidden" name="recaptcha_token" id="recaptcha_token">
    <!-- other fields -->
</form>
<script>
document.querySelector('form').addEventListener('submit', function (e) {
    e.preventDefault();
    grecaptcha.execute('{{ config('services.recaptcha.site_key') }}', {action: 'submit'}).then(function (token) {
        document.getElementById('recaptcha_token').value = token;
        e.target.submit();
    });
});
</script>

2. Verify the token server-side

public function store(Request $request)
{
    $response = Http::asForm()->post('https://www.google.com/recaptcha/api/siteverify', [
        'secret' => config('services.recaptcha.secret_key'),
        'response' => $request->recaptcha_token,
    ]);

    if (! $response->json('success') || $response->json('score', 0) < 0.5) {
        return back()->withErrors(['recaptcha' => 'Verification failed, please try again.']);
    }

    // proceed with normal form handling
}

The score (0.0 to 1.0) reflects how likely Google thinks the request is human — 0.5 is a reasonable starting threshold, but tune it based on how much spam actually gets through versus how many real users get incorrectly blocked.

3. Add keys to config

// config/services.php
'recaptcha' => [
    'site_key' => env('RECAPTCHA_SITE_KEY'),
    'secret_key' => env('RECAPTCHA_SECRET_KEY'),
],

Why verify server-side at all

The client-side score check can't be trusted — a request forged directly against your endpoint (bypassing the browser entirely) never runs the JavaScript challenge at all. The server-side call to siteverify against Google's API is the actual security boundary; the frontend script only generates the token to send it.

Topics: Forms & Validation