darvis / livewire-honeypot
Lightweight honeypot and time-trap spam protection for Livewire and Laravel forms, without CAPTCHAs.
Requires
- php: ^8.2
- laravel/framework: ^11.0|^12.0|^13.0
- livewire/livewire: ^3.0|^4.0
Requires (Dev)
- larastan/larastan: ^3.0
- laravel/pint: ^1.0
- orchestra/testbench: ^9.0|^10.0|^11.0
- pestphp/pest: ^3.0|^4.0
- pestphp/pest-plugin-laravel: ^3.0|^4.0
- phpunit/phpunit: ^11.0|^12.0|^13.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
darvis/livewire-honeypot stops automated form spam in Livewire components and plain Laravel forms without a CAPTCHA. It adds a hidden bait field that only bots fill in, and refuses a form that is submitted within a few seconds of loading. No cookies, no JavaScript, no third-party service.
Features
- Hidden bait field with a generated name such as
referral_3f9a, a neutral label and ignore attributes for password managers, so browser autofill does not block real visitors - Time trap: a minimum time between loading and submitting, 5 seconds by default
- A start time the client cannot change: locked properties in Livewire, a token signed with
APP_KEYin plain forms - One Blade component,
<x-honeypot />, for Livewire and plain forms; it also shows the error message - Livewire class components, single-file and multi-file components, and form objects
SpamBlockedevent to log or count blocked submissions- Works with a strict Content Security Policy through a nonce
- English, Dutch, German, French and Spanish messages
Requirements
- PHP 8.2 or higher
- Laravel 11, 12 or 13
- Livewire 3 or 4 (Composer installs it with the package, also when you only protect plain forms)
Installation
composer require darvis/livewire-honeypot
There is nothing to publish and no migration to run. The application needs an APP_KEY. See Installation for a way to check that it works.
Quick start
app/Livewire/ContactForm.php:
<?php namespace App\Livewire; use Darvis\LivewireHoneypot\Traits\HasHoneypot; use Livewire\Component; class ContactForm extends Component { use HasHoneypot; public string $email = ''; public function submit(): void { $this->validate(['email' => 'required|email']); $this->validateHoneypot(); // Process the form here. $this->reset('email'); $this->resetHoneypot(); } }
resources/views/livewire/contact-form.blade.php:
<form wire:submit="submit"> <input type="email" wire:model="email"> <x-honeypot /> <button type="submit">Send</button> </form>
Submit within five seconds, or with the hidden field filled in, and the form shows a validation error instead of running the rest of submit(). A form that posts to a controller works too: see Plain forms and controllers.
Documentation
Full documentation: https://arviddejong.github.io/livewire-honeypot/
- Installation: requirements, the steps, and how to check that it works
- Livewire forms: a complete contact form, single-file and multi-file components, form objects
- Plain forms and controllers: a Blade form with a controller, expiry, key rotation, JavaScript forms
- Configuration and events: the settings, translations, Content Security Policy, the
SpamBlockedevent - Testing your forms: test a protected component or controller in your application
- How it works: the checks, why the field is hidden this way, and what a honeypot does not stop
- Troubleshooting: real visitors are blocked, nothing is blocked, and every error message
- Compared to alternatives: spatie/laravel-honeypot and CAPTCHA services
- Your honeypot may be blocking real visitors: the autofill problem
- Honeypot autofill test: test your browser and check your own form
- FAQ: short answers
Laravel Boost
The package ships a Laravel Boost guideline and skill. Run php artisan boost:install, or php artisan boost:update --discover in a project that already uses Boost.
Testing
composer test # Pest composer lint # Pint, check only; composer format fixes composer analyse # Larastan
Changelog
See CHANGELOG.md.
Contributing
See CONTRIBUTING.md.
Security
Found a way around the honeypot? Report it privately, as described in SECURITY.md.
License
MIT. See LICENSE.