<form> tags and POST endpoints,
and once yours is on a list it stays there — most spam arriving at a small site’s contact form
is automated, indiscriminate, and has nothing to do with your business.
The instinct is to make submitting harder. That is the wrong trade: every extra step costs you
real enquiries too, and the bots are scripts that do not mind a puzzle. What works is filtering
server-side, after the submission arrives — so the visitor experience never changes and the
bot never learns why it failed.
Crunchforms runs three checks on every submission, on every plan including Free. None of
them is gated behind a paid tier.
Pick your layer
Honeypot field
A hidden field a human never sees and a bot fills in anyway. One line of markup, no
third-party script, nothing for visitors to do. Start here.
Cloudflare Turnstile
Invisible bot detection. Most visitors are never challenged; Crunchforms validates the
token server-side before the submission is stored.
reCAPTCHA v3
Score-based, no visitor interaction. You set the threshold per form and Crunchforms
enforces it.
Which one should you use?
Just getting started, or a low-traffic site
Just getting started, or a low-traffic site
Honeypot alone. It takes one hidden input and one setting, loads no third-party script,
and stops the majority of drive-by spam — which is the bulk of what a small site receives.
Nothing to configure with an external provider, and no privacy notice implications.
Spam is still getting through
Spam is still getting through
Add Turnstile on top of the honeypot. The two are independent checks and both run, so
a bot that has learned to skip your hidden field still has a token to produce. Turnstile is
invisible to most visitors, so this costs you almost nothing in conversion.
You want a tunable threshold, or already use Google's stack
You want a tunable threshold, or already use Google's stack
reCAPTCHA v3. It returns a score from 0.0 to 1.0 and you choose the cutoff per form, so
you can start permissive and tighten it while watching what gets through. Turnstile is a
pass/fail verdict by comparison — simpler, but less adjustable.
Can I use more than one at a time?
Can I use more than one at a time?
Yes. All three run on every submission and each can reject independently, so enabling two
or three is genuinely additive rather than redundant.
What happens to a rejected submission
The checks run before the submission is stored, so a rejected one never appears in your dashboard and never triggers a notification email. It counts against a separate blocked- submission tally rather than your monthly quota, so spam cannot burn through your plan limit. What the sender sees depends on the form’s response type:Redirect forms
Redirect forms
The visitor goes to the form’s failure URL, or gets a bare
400 if none is set. No detail
about which check rejected them is exposed.JSON forms
JSON forms
The response body carries a generic
status of "Invalid Submission" plus an errors
array naming the specific check that fired — for example "turnstile validation failed".
That detail is what makes a failing integration debuggable, so keep it in mind if you
surface raw error text in your own UI: show your own message to visitors rather than
passing the array straight through.How to see what was blocked
The bot never learns why it failed. You do. Open a form and look above the Inbox / Archived tabs — the same panel also sits inside Spam protection on the form’s settings page. It shows:- how many submissions were blocked this month, and the running total since the form was created
- a breakdown by reason, as a bar and a legend
- when the last block arrived
What the reasons mean
One submission can trip two checks at once — a bot that fills the honeypot and sends no
captcha token counts once in the total and once against each reason, so the reasons add up to
slightly more than the total on a form catching a lot of traffic.
This is a tally, not an inbox. Crunchforms does not keep rejected submissions where you
can read them: a blocked submission is spam by definition, and storing the payloads and IP
addresses of everyone your form turned away is not something we hand back to you. You get the
counts and the reasons.
When a captcha starts rejecting everyone
A mistyped secret key does not announce itself. The form keeps returning a failure to every visitor, real ones included, and from the outside it just looks like nobody is getting in touch. That is the case this panel exists for. If your captcha is blocking almost everything, blocks are still arriving, and nothing has been accepted for a week, the panel says so and points at the setting to check:Nothing is getting through to this form — 40 of the 42 submissions blocked this month were rejected by reCAPTCHA (95%), and nothing has been accepted since Jul 21. If you were expecting submissions, check the secret key and threshold in Spam protection — a wrong key rejects real visitors too.It reports what it can see and leaves the conclusion to you, deliberately. A quiet month on a low-traffic form with a working captcha produces the same four readings as a broken key, and nothing in the numbers tells them apart — only you know whether you were expecting to hear from anyone. If you were not, the panel is describing a normal month. A healthy form looks different: the honeypot doing most of the work, a captcha catching the rest, and submissions still arriving. That mix is the protection working — it is the only evidence you get that switching it on achieved anything.
Related
Form configuration
Response types, notification emails, and the per-form settings these checks live in
What is a form backend?
Why a static site needs somewhere to send form submissions in the first place
Need Help?
Get Support
Send us a note