The most effective way to stop contact form spam is to layer invisible checks — a honeypot field, a time-to-submit check, content filtering and rate limiting — and add a captcha only if spam still gets through. This blocks the vast majority of bots without making real visitors solve puzzles. FormSubmit applies these layers on every plan; here's how to use each one.
Layer 1: the honeypot
Bots tend to fill every field they find. A honeypot is an input that's hidden from people, so any value in it means a bot:
<input type="text" name="_gotcha" style="display:none" tabindex="-1" autocomplete="off">FormSubmit silently discards honeypot submissions and returns a normal success response, so the bot doesn't learn it was caught. tabindex="-1" keeps keyboard users out; autocomplete="off" stops browsers autofilling it.
Layer 2: time-to-submit
Humans take several seconds to fill a form; bots take milliseconds. Record when the form rendered:
<input type="hidden" name="_ts" id="fs-ts">
<script>document.getElementById("fs-ts").value = Date.now();</script>Submissions faster than your threshold (default 2 seconds, configurable) are scored as spam. Every JavaScript export from the form generator includes this.
Layer 3: content filtering
FormSubmit scores the content itself: number of links, HTML/BBCode links, known spam phrases, URLs in name fields and all-caps text. Choose low, medium or high sensitivity per form. Add your own blocked keywords for recurring pitches ("SEO services", "guest post", a competitor's name).
Suspicious submissions go to a Spam folder instead of your inbox; they don't trigger emails or integrations and don't count toward your quota. Review it occasionally and mark false positives as not spam. If real messages aren't arriving at all, see contact form not sending email.
Layer 4: rate limits and duplicates
Each IP can submit to a form at most 20 times a minute, and identical submissions within 10 minutes are flagged. Nothing to configure.
Layer 5: domain allowlist
Add your domain to the form's allowlist so browser-based submissions from other sites are rejected. It won't stop a determined script (headers can be forged) but it cuts off a lot of drive-by abuse.
Layer 6: captcha (only if needed)
If a form is specifically targeted, add a captcha. FormSubmit supports Cloudflare Turnstile, reCAPTCHA v2/v3 and hCaptcha with your own keys. Prefer invisible options — Turnstile or reCAPTCHA v3 — to protect conversion rates. For step-by-step setup, see how to add hCaptcha to an HTML form, which also covers Turnstile and reCAPTCHA.
What not to do
- Don't publish your email address in a
mailto:link or form action — scrapers harvest it. With FormSubmit your address never appears in your HTML. - Don't rely on JavaScript-only validation — bots post directly to endpoints.
- Don't put a captcha on every form by default — start invisible, escalate only when needed.