Laravel 12 Google Recaptcha V3 Validation Example

In this laravel tutorial titled “laravel 12 google recaptcha v3 validation example”, we’ll learn how to integrate Google reCAPTCHA v3 in a Laravel 12 application for login form validation.

Google reCAPTCHA v3 is a powerful security tool that protects your Laravel applications from spam submissions and bot attacks without interrupting the user experience. Unlike reCAPTCHA v2, which requires users to solve challenges or click checkboxes, version 3 works invisibly in the background, analyzing user interactions and assigning a risk score between 0.0 and 1.0.

We’ll go step by step to set up Google reCAPTCHA v3, configure keys, and validate it in Laravel 12.

Step 1: Create a New Laravel Project

If you haven’t created a Laravel 12 application yet, use Composer to create a new project:

composer create-project laravel/laravel google-recaptcha-v3-demo

Navigate to your project directory:

cd google-recaptcha-demo

Step 2: Get Google reCAPTCHA v3 Site and Secret Keys

To use reCAPTCHA v3, you need to register your website with Google and obtain the Site Key and Secret Key.​

Follow these steps:

  • Visit the Google reCAPTCHA Admin Console
  • Sign in with your Google account
  • Fill out the registration form:
    • Label: Enter a descriptive name for your site
    • reCAPTCHA Type: Select reCAPTCHA v3
    • Domains: Add your domain(s) (e.g., localhost or 127.0.0.1 for development, yourdomain.com for production)
    • Click Submit
Laravel 12 Google Recaptcha V3 Validation Example
Create Google Recaptcha V3

After submission, Google will display your Site Key (for frontend) and Secret Key (for backend validation).​

Google Recaptcha V3 Credentials
Google Recaptcha V3 Credentials

Step 3: Add Keys to .env File

Open your .env file and add the reCAPTCHA keys you just obtained:

GOOGLE_RECAPTCHA_KEY=6Ldn6PsrAAAAANIM2EBiPtZ4T8e1qiODluv-qyqw
GOOGLE_RECAPTCHA_SECRET=6Ldm6vsrAAAAACh8SginfFNJZlrMNikQqlKczgBR

Read Also : Laravel Show Validation Error Message in Blade

Step 4: Add reCAPTCHA to Your Blade Form

Create a new file resources/views/login.blade.php with the following code:

<!DOCTYPE html>
<html>
<head>
    <title>Laravel 12 Google Recaptcha V3 Validation Example - ItStuffSolutiotions.io</title>
     <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet">
 <script src="https://www.google.com/recaptcha/api.js"></script>
</head>
<body>
       
<div class="container">
    <div class="card mt-5">
        <h3 class="card-header p-3">Laravel 12 Google Recaptcha V3 Validation Example - ItStuffSolutiotions.io</h3>
        <div class="card-body">

            @session('error')
            <div class="alert alert-danger alert-dismissible fade show" role="alert">
                    {{ session('error') }}
                </div>
            @endsession


            
            <form action="{{route('store')}}" method="POST" enctype="multipart/form-data" class="mt-2" id="loginForm">
                @csrf
                <div class="mb-3">
                     <label for="email" class="form-label">Email:</label>
                    <input class="form-control  @error('email') is-invalida @enderror"  name="email" type="email" />
                    @error('email')
                        <span class="text-danger">{{ $message }}</span>
                    @endif
                </div>

                <div class="mb-3">
                     <label for="password" class="form-label">Password:</label>
                    <input class="form-control @error('password') is-invalida @enderror"  name="password" type="password" />
                    @error('password')
                        <span class="text-danger">{{ $message }}</span>
                    @endif
                </div>

                
                    @error('g-recaptcha-response')
                        <span class="text-danger">{{ $message }}</span>
                    @endif
        
                <div class="mb-3">
                 
                <button class=" g-recaptcha btn btn-primary" 
                    data-sitekey="{{env('GOOGLE_RECAPTCHA_KEY')}}" 
                    data-callback='onSubmit' 
                    data-action='submit'>Submit</button>

                </div>
                 
             
            </form>
        </div>
    </div>  
      
</div>
 
 <script>
   function onSubmit(token) {
     document.getElementById("loginForm").submit();
   }
 </script>
       
</body>
</html>

Understanding the view:

  • Loads Bootstrap for styling.
  • Loads the Google reCAPTCHA API script, which enables reCAPTCHA functionality on the page.
  • When a user clicks on submit button:
    • Google runs background checks.
    • If human behavior looks valid, it gets a token.
    • That token is automatically sent along with the form as g-recaptcha-response.
  • When reCAPTCHA verification succeeds, Google calls onSubmit(token).
  • This function simply submits the form to your Laravel route.

Form Validation Errors: Displays validation errors for each field using Blade directives​ @error and for google recaptcha error display using @error(‘g-recaptcha-response’).

Step 5: Create Routes

Define two routes in routes/web.php – one for displaying the form (GET) and another for handling form submission (POST):

<?php
    
use Illuminate\Support\Facades\Route;
    
use App\Http\Controllers\UserController;
     
Route::get('login', [UserController::class, 'index'])->name('login')->middleware('guest');
Route::post('store', [UserController::class, 'store'])->name('store');
Route::get('home', [UserController::class, 'home'])->middleware('auth')->name('home');

Read Also : Laravel 12 Custom Validation Error Messages Example

Step 6: Create Custom Validation Rule

Laravel 12 allows you to create custom validation rules using the make:rule Artisan command. We’ll create a ReCaptcha rule to verify the reCAPTCHA token with Google’s API.

php artisan make:rule ReCaptchaValidation

This creates a new file at app/Rules/ReCaptchaValidation.php. Update it with the following code:

<?php

namespace App\Rules;

use Http;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;

class ReCaptchaValidation implements ValidationRule
{
    /**
     * Run the validation rule.
     *
     * @param  \Closure(string, ?string=): \Illuminate\Translation\PotentiallyTranslatedString  $fail
     */
    public function validate(string $attribute, mixed $value, Closure $fail): void
    {
        $response = Http::get('https://www.google.com/recaptcha/api/siteverify', [
            'secret'   => env('GOOGLE_RECAPTCHA_SECRET'),
            'response' => $value,
        ]);

         $result = $response->json();
         if(!$result['success']){
            $fail('Invalid recaptcha');
         }
    }
}

How it works:

  • The validate method sends a POST request to Google’s siteverify API endpoint using Laravel’s HTTP.
  • It passes the secret key and the reCAPTCHA response token
    If Google’s API returns success: false, the validation fails

Step 7: Create Controller

Generate a new controller to handle the Login form:

php artisan make:controller UserController
<?php
  
namespace App\Http\Controllers;
  
use Illuminate\Http\Request;
use App\Models\User;
use App\Rules\ReCaptchaValidation;


class UserController extends Controller
{
    /**
     * Display form.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        return view('login');
    }
        
    /**
     * Login users
     *
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
       $request->validate([
            'email'   => 'required|email',
            'password' => 'required',
            'g-recaptcha-response' => ['required',new ReCaptchaValidation],
        ]);

        $credentials = ['email'=>$request->email,'password'=>$request->password];

        if(auth()->attempt($credentials)){
        return redirect()->route('home')->withSuccess("Login successfully!");
       }
       return back()->with('error', 'Invalid email or password.');
    }
 
     /**
     * 
     * Dashboard
     *
     * @return \Illuminate\Http\Response
     */
    public function home(Request $request)
    {
      return view('home');
 
    }
}

Key points:

  • The index() method returns the login form view
  • The store() method validates all form fields including the reCAPTCHA token
  • The g-recaptcha-response field contains the token generated by reCAPTCHA v3
  • After successful validation, you can implement your business logic (store in database, send emails, etc.)

Step 8: Test the Application

Start your Laravel development server:

php artisan serve

Visit your application in a browser:

Fill in the form and submit it. If reCAPTCHA passes, you’ll see the success message; otherwise, it’ll show an error.

Conclusion

Implementing Google reCAPTCHA v3 in Laravel 12 provides robust protection against spam and bot attacks while maintaining a seamless user experience. By following this tutorial, you’ve learned how to:

  • Register and configure reCAPTCHA v3 API keys
  • Create custom validation rules in Laravel 12
  • Implement client-side reCAPTCHA token generation
  • Validate submissions on the server-side
  • Display validation errors in Blade templates

This implementation can be extended to any form in your Laravel application, including registration forms, login forms, feedback forms, and checkout processes. The invisible nature of reCAPTCHA v3 ensures maximum security with minimal user friction, making it an ideal choice for modern web applications.


Frequently Asked Questions (FAQs)

Q1: Why am I getting an “Invalid site key” error?

This error appears when the site key doesn’t match the domain you registered in the Google reCAPTCHA admin console.
Make sure you’re using the correct site key and that it’s configured for your current domain.

Q2: Why isn’t reCAPTCHA loading on my page?

The most common reason is that the reCAPTCHA JavaScript library isn’t properly included, or your site key is incorrect.
Ensure that the reCAPTCHA script is correctly added to your HTML and that you’re using a valid site key.

Q3: Why does validation always fail, even with correct inputs?

This usually means the secret key used for server-side verification is incorrect, or your server cannot reach Google’s reCAPTCHA API endpoint.
Double-check your secret key in your backend configuration and confirm that outbound requests to
https://www.google.com/recaptcha/api/siteverify are allowed.

Q4: How can I hide the reCAPTCHA badge without breaking functionality?

Avoid using display: none, as it can disable spam checking.
Instead, use the following CSS:
.grecaptcha-badge {
visibility: hidden;
}

This hides the badge visually but keeps reCAPTCHA active in the background.