All docs
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

Step 1 - Create an hCaptcha site

  1. Sign in at https://dashboard.hcaptcha.com.
  2. SitesNew Site.
  3. Name: Formspring - <form name> (one per form, or one shared across forms - your call).
  4. Hostnames: list the domains where the form embed runs. Wildcards via *.formspring.io work.
  5. Difficulty: Auto (recommended) - adapts to the visitor's risk score. Always Challenge is too disruptive for forms.
  6. 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:

  1. Open your form → SettingsSpam & abuse (or wherever the form's captcha settings live in your install).
  2. Enable hCaptcha.
  3. Paste the Site Key and Secret Key.
  4. 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: forms table 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.phphcaptcha.verify_url (default https://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