A modern, zero-config Symfony bundle for hCaptcha: server-side verification, Twig widget, Form Type and Validation Constraint — ready in under a minute.
HcaptchaVerifier returning a rich HcaptchaResponse value object
(success, errorCodes, hostname, score for Enterprise, …)HcaptchaType) with auto-attached validator#[Hcaptcha]) for any DTO/propertyhcaptcha_script(), hcaptcha_widget(), hcaptcha_invisible_widget()enabled: false) — no HTTP call, always succeedscomposer require ethsam/easy-hcaptcha
Then in .env:
HCAPTCHA_SITE_KEY=your_public_site_key
HCAPTCHA_SECRET_KEY=your_secret_key
And in config/packages/easy_hcaptcha.yaml:
easy_hcaptcha:
site_key: '%env(HCAPTCHA_SITE_KEY)%'
secret_key: '%env(HCAPTCHA_SECRET_KEY)%'
{# templates/contact.html.twig #}
<head>{{ hcaptcha_script() }}</head>
<form method="post">
{{ hcaptcha_widget() }}
<button>Send</button>
</form>
// In your controller — pick your favourite style:
// 1) Form Type (recommended — auto-validated)
$form = $this->createFormBuilder()
->add('email', EmailType::class)
->add('captcha', HcaptchaType::class)
->getForm();
// 2) Validation Constraint on a DTO
class ContactDto {
#[\Ethsam\EasyHcaptcha\Validator\Constraint\Hcaptcha]
public ?string $captchaToken = null;
}
// 3) Manual call (full control)
public function submit(Request $r, HcaptchaVerifierInterface $verifier): Response
{
$result = $verifier->verify($r->request->get('h-captcha-response'), $r->getClientIp());
if (!$result->isSuccess()) {
return $this->redirectToRoute('contact');
}
// ...
}
Full documentation in three languages:
In config/packages/test/easy_hcaptcha.yaml:
easy_hcaptcha:
enabled: false # verifier returns success without any network call
Pull requests welcome. Run the test suite locally:
composer install
vendor/bin/phpunit
See CHANGELOG.md for a detailed history of releases.
Released under the MIT License — see the file for details.
Originally authored by Samuel ETHEVE.
How can I help you explore Laravel packages today?