hCaptcha Setup for Website Form Protection
hCaptcha — reCAPTCHA alternative focused on privacy. Doesn't transfer user data to Google, complies with GDPR. Used by Cloudflare and other major platforms.
Differences from reCAPTCHA
- No Google account required for operation
- Website owners receive compensation for tasks (optional)
- Similar API — migration from reCAPTCHA takes hours
- Versions: Checkbox (explicit test), Invisible (background analysis), Enterprise (extended analytics)
Registration
Get keys from hcaptcha.com: sitekey and secret.
Checkbox Integration
<script src="https://js.hcaptcha.com/1/api.js" async defer></script>
<form method="POST" action="/contact">
<input type="text" name="email" required>
<div class="h-captcha" data-sitekey="YOUR_SITE_KEY"></div>
<button type="submit">Submit</button>
</form>
Invisible hCaptcha
<script src="https://js.hcaptcha.com/1/api.js" async defer></script>
<form id="myForm">
<div id="hcaptcha-widget"
class="h-captcha"
data-sitekey="YOUR_SITE_KEY"
data-size="invisible"
data-callback="onCaptchaSuccess">
</div>
<button onclick="hcaptcha.execute()">Submit</button>
</form>
<script>
function onCaptchaSuccess(token) {
document.getElementById('myForm').submit();
}
</script>
Server Verification (Laravel)
// app/Rules/HcaptchaRule.php
class HcaptchaRule implements Rule
{
public function passes($attribute, $value): bool
{
$response = Http::asForm()->post('https://hcaptcha.com/siteverify', [
'secret' => config('services.hcaptcha.secret'),
'response' => $value,
'remoteip' => request()->ip(),
]);
return $response->json('success') === true;
}
public function message(): string
{
return 'hCaptcha verification failed.';
}
}
// In controller
$request->validate([
'email' => 'required|email',
'h-captcha-response' => ['required', new HcaptchaRule],
]);
React Component
import HCaptcha from '@hcaptcha/react-hcaptcha';
function Form() {
const captchaRef = useRef(null);
const [captchaToken, setCaptchaToken] = useState(null);
return (
<form onSubmit={handleSubmit}>
<HCaptcha
ref={captchaRef}
sitekey={process.env.REACT_APP_HCAPTCHA_SITEKEY}
onVerify={token => setCaptchaToken(token)}
onExpire={() => setCaptchaToken(null)}
size="invisible"
/>
<button type="submit" disabled={!captchaToken}>
Submit
</button>
</form>
);
}
Implementation Timeline
4–8 hours for integration including server verification and error handling.







