Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Honey Laravel Package

lukeraymonddowning/honey

A simple Laravel honeypot package that protects forms from spam bots without CAPTCHAs. Add a hidden field, and Honey silently rejects submissions that fill it, keeping forms user-friendly and spam-free.

Deep Wiki
Context7

Getting Started

Install the package and wire it up in three commands:

composer require lukeraymonddowning/honey
php artisan vendor:publish --tag=honey-config

The published config/honey.php is where every knob lives: honeypot, reCAPTCHA, IP blocking, and the minimum-time-on-page rule. Read this file first — it tells you what the package will and won't do before you touch a form.

Add protection to a form with the Blade directive:

<form method="POST" action="/contact">
    @honey
    @csrf
    <input name="email">
    <button type="submit">Send</button>
</form>

Then guard the controller. Either apply the middleware (->middleware('honey')) for blanket protection, or call the facade yourself:

use Lukeraymonddowning\Honey\Facades\Honey;

public function store(Request $request)
{
    if (Honey::check()->isSpam()) {
        abort(403, 'Spam detected.');
    }
    // ...
}

First use case: a public contact form or newsletter signup. That's where honeypot + reCAPTCHA v3 pays for itself with almost no effort.

Implementation Patterns

Middleware for boilerplate, facade for fine control. Slap the honey middleware on every public POST route and forget about it. Drop to Honey::check() when you need to redirect, log, score, or show a specific message instead of a blunt abort.

Response object is your instrumentation point. Honey::check() returns a response with isSpam(), hasBeenBlocked(), isBlocked(), and failedFor(). Use failedFor() to log which technique caught the request (honeypot, recaptcha, min-time) — that's how you tune thresholds over time.

FormRequest integration. Put the check inside a FormRequest's authorize() or a withValidator() callback so validation and spam rejection are colocated with the rules for that endpoint.

reCAPTCHA v3 is score-based. Configure recaptcha.site_key, secret_key, and minimum_score in the config. The @honey directive renders the script tag that generates the token. For long forms (surveys, multi-step wizards), regenerate the token on submit — tokens expire after roughly two minutes.

Livewire needs the trait, not the middleware. Livewire submits over AJAX after the initial page load, so route middleware only fires on the first request. Use Honey::check() inside the component's submit handler, or the package's Livewire trait if you're on a version that ships one.

Layer with rate limiting. Honey catches bots, throttle catches abuse. Route::post('/contact', ...)->middleware(['honey', 'throttle:10,1']) is a sane default.

Persist IP blocks. The default in-memory manager evaporates on every deploy and every queue worker restart. For anything beyond a hobby app, swap in a cache- or database-backed IpManager so blocks actually stick.

Testing. Disable honeypot/recaptcha in phpunit.xml env (HONEY_HONEYPOT_ENABLED=false, HONEY_RECAPTCHA_ENABLED=false) for the happy-path suite, then write separate tests that turn them back on to assert spam rejection.

Gotchas and Tips

Proxies break IP blocking. Behind Cloudflare, an ALB, or any reverse proxy, $request->ip() returns the edge node, not the client. Configure TrustProxies with the right HEADER_X_FORWARDED_FOR or your blocklist will quietly ban everyone — including legitimate users.

Minimum time on page false-positives. The min_time_on_page threshold is measured from page render. Password managers, browser back/forward cache, and very fast form fillers can trip it. Keep it to 1–2 seconds; anything higher punishes legitimate users more than bots.

Don't name the honeypot field in your JS. The field name is randomized per config/session — hardcoding it in frontend code defeats the point and will break on config changes. Let @honey render it.

reCAPTCHA v3 needs the script loaded before submit. If you conditionally include @honey, grecaptcha may be undefined when the token is requested. Include it unconditionally on any page that submits to a protected endpoint.

Randomize the honeypot, but know where it's stored. The randomization prevents bots from learning one field name across all sites, but it means you can't grep your codebase for it later — rely on the directive, not manual hidden inputs.

Order of checks matters for diagnostics. If honeypot fires first, reCAPTCHA never runs and you lose signal on whether the token was even valid. If you're debugging false positives, disable honeypot temporarily to isolate.

IP blocking has no allowlist by default. Add an early return for admin/internal IPs before the middleware or in a custom manager — otherwise a bot behind shared NAT can lock out an entire office.

Extension points. The IpManager contract is the cleanest override — implement a cache-backed or Redis-backed version for multi-server deployments. The reCAPTCHA client can also be swapped if you need to mock it in tests or point at a different verification endpoint.

Config caching. After php artisan config:cache, changing .env values for reCAPTCHA keys won't take effect until you recache. This burns people in staging constantly.

Fail open vs. fail closed. If the reCAPTCHA verification endpoint times out, the package's behavior depends on config. Decide deliberately: failing closed rejects real users during a Google outage; failing open lets spam through. For low-stakes forms, fail open.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core