An ordered fix list — starting with the changes you can make in ten minutes and ending at the point where per-trick defences stop being enough.
Contact form spam is the most common form of the problem because contact forms are the most common form. They are public, they are usually the oldest form on the site, and they almost always post to a human inbox — which means every junk submission costs someone attention rather than just database rows.
This is the applied version of our guide to stopping form spam without a CAPTCHA. That one explains the methods; this one tells you what to do first.
The fix depends on the source, and there are three quite different ones. Spending ten minutes here saves you implementing the wrong thing.
| What you see | Likely source | What works |
|---|---|---|
| Bursts of identical or near-identical messages, seconds apart | Scripted bot working a list | Timing checks, rate limiting, behavioural detection |
| Varied, semi-plausible messages with a link, arriving steadily | Commercial form-filling tool | Behavioural detection; honeypots and keyword rules will not hold |
| Genuinely human-written pitches, slow and irregular | Paid form-fillers or cold outreach | Content filtering, rate limits, and an unsubscribe-style policy line |
Look at the timestamps on the last twenty junk submissions. If several arrived within the same second, or all land at exactly the top of the hour, you are looking at automation and everything below applies. If they are scattered irregularly across days, you may have a human problem, which bot detection cannot fix.
Do these regardless of what else you decide. None of them touch your visitors.
type="hidden", not name="honeypot", and hidden from
assistive technology too with aria-hidden="true" and
tabindex="-1" so a screen reader user does not fill it in and get
silently rejected. See
honeypot vs CAPTCHA for how far this gets
you.
For a lot of small sites, that is the end of the story. Measure for a fortnight before doing anything more.
Rewriting your field names. It breaks scripts hard-coded to your old markup, so volume drops for a few weeks and then returns. Free to try, but do not mistake the dip for a fix.
Removing the form and publishing an email address. This moves the filtering into your inbox and throws away every signal a form gives you, while losing the enquiries from people who will not open a mail client.
Long keyword blocklists. Spam text mutates faster than you can maintain rules, and the false positives are expensive — a real prospect writing about "SEO services" should not be binned. Keep a short list for the human-written spam and review what it catches.
Adding a CAPTCHA on top of protection you already have. Two form gates give you the friction of one and the accuracy of neither, because each sees only part of the submission and real people still get stopped by the weaker one. Network -level protection at your CDN is a different layer and is fine to keep running.
If junk is still arriving after timing checks, rate limits and a honeypot, you are no longer facing opportunistic traffic. Commercial form-filling tools render your page, execute your JavaScript, skip fields that look like traps and pace themselves under your rate limits. Nothing on a per-trick list beats them for long, because each trick is a single rule that can be read and routed around.
That is the point to move to behavioural detection: scoring how the submission was composed — interaction, cadence, field order, timing — rather than testing one property of it. There are many signals, they update as automation changes, and a bot has to defeat all of them at once.
SpamKill is that layer as a hosted service: two versions of every form, one clean for people and one obfuscated for automated fillers, scored on behaviour rather than content at 99.9% accuracy across more than 100M+ submissions screened for 1,500+ businesses. Your visitors see nothing, the rare flagged person verifies in one step and continues, and anything held is recoverable rather than deleted. Plans start from $29/month with a 30-day free trial, no credit card.
Whatever you implement, track blocked versus passed as a ratio over time, and watch the conversion rate on the form itself. A filter that quietly rejects real enquiries looks identical to a filter that works — right up until a customer tells you they tried to reach you three times. If you cannot inspect what you rejected, you cannot know your false-positive rate.
Almost always because it was discovered, not because anything changed on your side. Automated crawlers index forms continuously, and once an address or endpoint lands on a list it gets retried for months. A redesign that changed your field names can also reset a filter that was quietly working.
Briefly, sometimes. Renaming fields breaks scripts hard-coded to your old markup, so volume can drop for a few weeks. It is not a fix — generic form-fillers read the rendered form and adapt — but it costs nothing and it does tell you something useful: if renaming helps a lot, you are facing cheap automation rather than anything targeted.
It moves the problem rather than solving it. A published address gets harvested and then you are filtering in your inbox instead, without any of the signals a form gives you. It also costs you the genuine enquiries from people who will fill in a form but will not open a mail client.
Only if you genuinely do no business there, and even then treat it as a blunt instrument. Geographic blocking stops a share of automated traffic cheaply, but it also silently turns away travelling customers and anyone on a VPN. Use it to reduce noise, never as your only defence.
There is no useful benchmark — it depends entirely on your traffic, how long the form has existed, and whether your address is on a list. The number that matters is the ratio of blocked to passed submissions and whether it is trending in the right direction after a change.
Paste your real form HTML into the Form Transformer and get the protected version back. No signup, no card, nothing to install.
Open the Form Transformer