lazycaptcha/laravel

Laravel integration for LazyCaptcha — drop-in CAPTCHA protection for forms, with validation rule, middleware, Blade component, and facade.

Maintainers

Package info

github.com/lazycaptcha/laravel

Homepage

pkg:composer/lazycaptcha/laravel

Statistics

Installs: 2

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.0 2026-04-17 19:03 UTC

This package is auto-updated.

Last update: 2026-04-17 19:11:45 UTC


README

Drop-in LazyCaptcha integration for Laravel apps. Adds a Blade component, validation rule, middleware, and facade — so protecting a form is one line of HTML and one line of validation.

License: MIT Latest Stable Version

Installation

composer require lazycaptcha/laravel

The service provider and facade auto-register via Laravel package discovery.

Publish the config (optional):

php artisan vendor:publish --tag=lazycaptcha-config

Add your keys to .env:

LAZYCAPTCHA_SITE_KEY=your-site-key-uuid
LAZYCAPTCHA_SECRET_KEY=your-secret-hex
LAZYCAPTCHA_URL=https://yoursite.com    # optional, defaults to https://lazycaptcha.com

Usage

1. Render the widget in a form

The simplest path — drop the Blade component anywhere:

<form method="POST" action="{{ route('contact.send') }}">
    @csrf

    <input type="email" name="email" required>
    <textarea name="message" required></textarea>

    <x-lazycaptcha />

    <button type="submit">Send</button>
</form>

The component reads the site key from your config. You can override per-form:

<x-lazycaptcha sitekey="ANOTHER_SITE_KEY" type="image_puzzle" theme="dark" />

There's also a Blade directive if you prefer:

@lazycaptcha
{{-- or --}}
@lazycaptcha('SITE_KEY')

2. Verify on submit — pick one of three styles

Option A: Validation rule (recommended)

public function store(Request $request)
{
    $validated = $request->validate([
        'email' => 'required|email',
        'message' => 'required|string|max:1000',
        'lazycaptcha-token' => 'required|lazycaptcha',
    ]);

    // ... process the validated data
}

For Laravel 10+ rule objects with a minimum risk score:

use LazyCaptcha\Laravel\Rules\ValidLazyCaptcha;

$request->validate([
    'lazycaptcha-token' => ['required', new ValidLazyCaptcha(minScore: 0.5)],
]);

Option B: Middleware

Register the alias in bootstrap/app.php:

->withMiddleware(function (Middleware $middleware) {
    $middleware->alias([
        'lazycaptcha' => \LazyCaptcha\Laravel\Http\Middleware\VerifyLazyCaptcha::class,
    ]);
})

Apply it to routes:

Route::post('/contact', [ContactController::class, 'store'])
    ->middleware('lazycaptcha');

The verification result is attached to the request:

$result = $request->attributes->get('lazycaptcha');
// ['success' => true, 'score' => 0.87, 'hostname' => '...', 'challenge_ts' => '...']

Option C: Facade

use LazyCaptcha;

if (! LazyCaptcha::check($request->input('lazycaptcha-token'), $request->ip())) {
    abort(422, 'Captcha failed');
}

// Or get the full response
$result = LazyCaptcha::verify($request->input('lazycaptcha-token'), $request->ip());
if (! $result['success']) {
    return back()->withErrors(['captcha' => $result['error']]);
}

Configuration

Full config reference (config/lazycaptcha.php):

Key Env Default Description
site_key LAZYCAPTCHA_SITE_KEY Required. Public site key.
secret_key LAZYCAPTCHA_SECRET_KEY Required. Secret key (server-side only).
base_url LAZYCAPTCHA_URL https://lazycaptcha.com Your LazyCaptcha instance URL.
timeout LAZYCAPTCHA_TIMEOUT 5 HTTP timeout in seconds.
type LAZYCAPTCHA_TYPE auto Default challenge type.
theme LAZYCAPTCHA_THEME light Widget theme.
token_field lazycaptcha-token Form field name (don't change unless you know why).
send_remote_ip true Forward client IP to verification API.

Testing

When testing forms that use the captcha, you'll typically want to skip verification. Mock the facade:

use LazyCaptcha\Laravel\Facades\LazyCaptcha;

LazyCaptcha::shouldReceive('check')->andReturn(true);
LazyCaptcha::shouldReceive('verify')->andReturn(['success' => true, 'score' => 1.0]);

$this->post('/contact', ['email' => 'a@b.c', 'message' => 'hi', 'lazycaptcha-token' => 'fake'])
    ->assertRedirect('/');

Compatibility

  • Laravel 10, 11, 12, 13
  • PHP 8.2+

License

MIT