3 min read
hCaptcha integration
Adds hCaptcha to a form. Each submission is verified server-side by App\Spam\Stage\HCaptchaStage before the spam pipeline lets it through. Configured per-form rather than globally because privacy preferences and threshold tuning vary.
What you need
- An hCaptcha account at https://dashboard.hcaptcha.com (free).
- A site (the dashboard's term for one or more forms hosted on a domain).
Step 1 - Create an hCaptcha site
- Sign in at https://dashboard.hcaptcha.com.
- Sites → New Site.
- Name:
Formspring - <form name>(one per form, or one shared across forms - your call). - Hostnames: list the domains where the form embed runs. Wildcards via
*.formspring.iowork. - Difficulty:
Auto(recommended) - adapts to the visitor's risk score.Always Challengeis too disruptive for forms. - Save.
Step 2 - Copy the keys
The site page shows:
- Site Key (public): goes on the form embed (visible to visitors).
- Secret Key (private): goes on the server, used to verify the response.
Both are needed.
Step 3 - Connect in Formspring
In the dashboard:
- Open your form → Settings → Spam & abuse (or wherever the form's captcha settings live in your install).
- Enable hCaptcha.
- Paste the Site Key and Secret Key.
- Save.
The form's embed snippet now includes the hCaptcha widget. Submissions without a valid captcha response are rejected with HTTP 422.
Where the credential lives
- Per-form config:
formstable columns:hcaptcha_enabled(bool)hcaptcha_site_key(string, public)hcaptcha_secret(string, encrypted)
- Spam stage:
app/Spam/Stage/HCaptchaStage.php. - Verify URL: configurable at
config/services.php→hcaptcha.verify_url(defaulthttps://hcaptcha.com/siteverify).
Security
- The site key is public - it's embedded in the page HTML.
- The secret key is private - never exposed client-side. Formspring stores it encrypted at rest.
- Rotate by deleting the site at https://dashboard.hcaptcha.com → creating a new one → updating both keys on each form using it.
- For forms with sensitive flows (password reset, financial), pair captcha with rate limiting (already in place) and tighten the spam stage thresholds.
Privacy notes
- hCaptcha's free tier shows the visitor a privacy notice; they can't disable it. The privacy policy lives at https://hcaptcha.com/privacy.
- For GDPR strictness, hCaptcha is the better choice over reCAPTCHA - it doesn't profile users with Google's adtech graph.
- Add a privacy disclosure on the form: "This site is protected by hCaptcha and its Privacy Policy and Terms of Service apply."
Troubleshooting
| Symptom | Cause |
|---|---|
| Submissions all return 422 | The form embed doesn't include the captcha widget. Check the embed snippet contains the h-captcha div with the right data-sitekey. |
| Captcha shows but solve doesn't help | Site key on the embed doesn't match the secret on the server (mismatched site). |
Verification fails with invalid-input-secret |
Secret key wrong or unencrypted-then-re-saved with whitespace. |
Verification fails with invalid-input-response |
Token expired (default lifetime: 2 minutes). User took too long. |
hostname-mismatch |
The site's hostname list doesn't include the domain serving the form. Add it. |
Provider docs
- hCaptcha for site owners: https://docs.hcaptcha.com/
- Server-side verification: https://docs.hcaptcha.com/#verify-the-user-response-server-side
- Difficulty settings: https://docs.hcaptcha.com/configuration/#difficulty