Spam protection
Most forms don't need to make a visitor prove they're human. Form Plume layers a few lightweight, invisible checks that catch almost all bot traffic on their own.
Add a honeypot and a time-trap token and you're covered for the vast majority of forms. Everything else here is either automatic or for the rare form that gets targeted by an actual person.
If you want an extra layer, or your form already uses one, add CAPTCHA. Form Plume supports Cloudflare Turnstile, hCaptcha, and Google reCAPTCHA.
Honeypot
Add a hidden input named _gotcha to your form:
<input
type="text"
name="_gotcha"
tabindex="-1"
autocomplete="off"
style="position:absolute; left:-9999px"
>Real visitors never see or fill this in, it's off-screen and skipped in tab order. Bots that blindly fill every input on the page usually fill it in anyway.
If _gotcha arrives non-empty, Form Plume responds exactly as if the
submission succeeded, so the bot gets no signal that anything went wrong.
The submission itself is dropped before it reaches your inbox or triggers a
webhook.
Time-trap token
Bots that skip the honeypot trick still tend to submit fast, often under a second after the page loads. A time-trap token catches that.
Fetch a token right before you render the form:
const res = await fetch("https://api.formplume.com/f/{public_slug}/time-trap");
const { field, token } = await res.json();
// field === "_fp_ts"Then put it in a hidden field named by the response:
<input type="hidden" name="_fp_ts" value="TOKEN_GOES_HERE">The token is signed (HMAC-SHA256) and encodes when it was issued, so the
server can check timing without keeping any session state. A submission
comes back validation_failed if the token is:
- Used less than 3 seconds after it was issued, too fast for a human to have actually read the form
- Older than an hour (see
expires_in_secondsin the response) - Reused, each token is good for one submission only
Rotating the signing secret on your end doesn't break anything mid-flight. Tokens issued before the rotation keep working for a grace period.
Rate limiting
Rate limiting is on by default, no setup needed:
| Window | Limit |
|---|---|
| Strict | 1 submission every 30 seconds |
| Burst | 20 submissions every 10 minutes |
Limits are keyed per form, per submitter (IP address plus user agent), so one visitor hammering refresh can't take a form down for everyone else.
Going over either limit returns 429 Too Many Requests with a
Retry-After header telling you how long to wait. Both windows are
configurable per form if the defaults don't fit your traffic.
Email hygiene
Configure this per form under Settings → Spam. Email hygiene checks that the submitter's email field looks real: valid syntax, a domain you haven't blocked, and optionally a working mail server (MX record) and no disposable addresses.
Failed checks can either flag the submission (it still arrives, marked
for the spam scorer) or block it outright with email_rejected. Flagging
is available on every plan; blocking, MX checks, and disposable-address
blocking are Pro features.
Blocked keywords
Blocked keywords let you add words or phrases under Settings → Spam → Blocked keywords, one per
line. Any submission containing one of them anywhere in its content goes
straight to the spam folder, no matter what the spam score says. Matching is
case-insensitive and works on multi-word phrases like backlink packages.
Quarantined submissions land in the spam folder rather than being deleted, so a false positive is always recoverable, and marking it "not spam" also trains your form's filter.
CAPTCHA, if you need it
For the small number of forms that attract targeted, human-operated spam rather than simple bots, you can add CAPTCHA verification as an extra layer. Create keys with the provider of your choice, then your page renders the widget with the site key and Form Plume verifies the submitted token with the encrypted secret key before accepting the submission.
The secret key is private. Paste it into Form Plume settings, but never put it in your HTML, JavaScript bundle, or public repository.
| Provider | Best for | Token field | Plan |
|---|---|---|---|
| hCaptcha | Free, challenge-based CAPTCHA with broad support | h-captcha-response | Free |
| Cloudflare Turnstile | Privacy-friendly, low-friction checks | cf-turnstile-response | Pro |
| Google reCAPTCHA v2 | Checkbox or invisible challenge flows | g-recaptcha-response | Pro |
| Google reCAPTCHA v3 | Invisible, score-based risk checks | g-recaptcha-response | Pro |
Each provider has its own setup guide with the full widget snippet, token field, and verification details:
- Cloudflare Turnstile, privacy-friendly and often puzzle-free (Pro)
- hCaptcha, the free-plan option with broad support
- Google reCAPTCHA, covering both the v2 checkbox flow and invisible v3 scoring (Pro)
What to actually turn on
Honeypot and the time-trap token together stop the overwhelming majority of automated spam for the cost of two extra fields and zero user-facing friction. Rate limiting and email hygiene run regardless of what you choose.
Reach for CAPTCHA only if you're still seeing spam after that, it's usually a sign of a human spammer, not a script. Blocked keywords are a quick lever too if the spam always mentions the same things.