Anticode Open builder

How to stop spam on a contact form

Most contact form spam comes from scripts that find a form, fill every field and post it, often without loading the page at all. Checks on the server stop much of it before a visitor ever sees a puzzle. Add a CAPTCHA last, if at all, because it is the only defence that costs every genuine visitor something.

Updated · By the Anticode team

First, look at the spam you're getting

Open the last twenty junk submissions and sort them. The fix depends on which kind dominates, and a fix aimed at the wrong kind only adds friction.

Link spam
Messages full of URLs, often in another language, sent at all hours. Almost always automated.
Gibberish
Random strings in the name field, a valid-looking email and nothing else. Bots testing whether the form accepts anything.
Sales pitches
Well-written offers for SEO, web design or leads. Usually typed by people, sometimes with tools. No bot check stops a human.
Floods
Dozens of posts in a few minutes from one source. A sign someone is hammering the endpoint, not browsing the site.

Defences, cheapest for visitors first

Work down this list and stop when the spam drops to a level you can delete in a minute a day. Each step costs real visitors more than the one before it.

  1. Accept posts only from your own pages. The server can refuse any submission whose Origin header isn't your site. Scripts that post straight to the form's address from elsewhere are turned away, and nobody sees anything.
  2. Limit how often one source can send. A rate limit per visitor and per form stops floods without touching ordinary use. A person writing to you sends one message, not eight in ten minutes.
  3. Validate every field on the server. Require a well-formed email, cap lengths, and reject fields that shouldn't exist. Browser maxlength and type attributes help honest visitors but are trivial to bypass, so repeat the rules where the form lands.
  4. Add a honeypot field. An extra input that people never see, hidden with CSS and skipped by screen readers, which bots tend to fill in. Any submission with a value in it is dropped quietly.
  5. Check the timing. A human takes longer than two seconds to read a form and type a message. A hidden timestamp lets the server discard posts that arrive impossibly fast, though it needs care with cached pages.
  6. Filter the content. Rules such as "more than three links" or a blocklist of phrases you keep seeing catch link spam. Send matches to a separate folder rather than deleting them, in case a real enquiry trips the rule.
  7. Then, and only then, a challenge. A CAPTCHA or a proof-of-work widget. Keep reading before you add one.

What a CAPTCHA costs

The W3C's note on the inaccessibility of CAPTCHA sets out the problem: visual and audio puzzles exclude people with sight, hearing and cognitive disabilities, and software solves many of them anyway. It points to non-interactive approaches such as heuristics and honeypots first. WCAG 2.2 also limits puzzle-style tests in sign-in steps under Accessible Authentication. A contact form isn't a sign-in step, but the reasoning carries over: a transcription puzzle stands between a person and the only way you offered them to reach you.

Script-based challenges also bring a third party onto the page. That means loading its code, allowing it in your Content-Security-Policy, and usually describing it in your privacy policy, because the provider sees the visitor's browser.

Honeypot field: doing it properly

  • Give it a plausible name, such as website or company_url, so bots want to fill it.
  • Hide it with a CSS class that moves it off screen, not type="hidden", which many bots know to skip.
  • Add tabindex="-1", autocomplete="off" and aria-hidden="true" on its wrapper, so keyboard users, password managers and screen readers leave it alone.
  • On the server, accept the post with a normal thank-you page but don't store it. Telling the bot it failed teaches it to adapt.

Mistakes that make it worse

  • Publishing your email address in plain text next to the form. Harvesters collect it and the spam simply moves to your inbox.
  • Optional fields nobody needs. Every free-text field is another place to paste links. A name, an email and a message are enough for most enquiries; the contact form fields guide goes through each one.
  • Silent filters with no review. If a real customer's message lands in a spam folder you never open, the filter has cost you more than the spam did.

How to check it's working

Count junk submissions for a week before and after each change, and note what you changed when. Then send yourself a test message from a phone and from a laptop with a password manager on, to confirm the honeypot doesn't catch real people. If genuine enquiries drop after a change, roll it back first and investigate second.

Anticode's forms and their limits

The built-in contact form has fixed fields: name, email and a message. Before publishing, Sentinel checks that every field is typed and length-capped, that each one has a label, and that the form posts to the site's own address with form-action 'self' in the policy. The first two defences above are already on: site form posts must come from the site itself, and they're rate-limited per visitor and per site. Submissions are saved and sealed at rest, and you can have them emailed to you or sent to a connector.

The limits are real. Because the fields are fixed, you can't add a honeypot or a timing field to the built-in form. Published pages run no scripts and allow no frames, so script-based CAPTCHA widgets can't run on them. A form with different fields is a custom form tied to a site function, where a formula can refuse a submission with its own message. Formulas work on numbers only, though, so they can't filter text such as links in a message; that needs a webhook function on your own endpoint. For more on what happens after a message is sent, see why form emails go to spam.

Questions people ask

Does a honeypot field stop all bots?

No. It stops the simple ones that fill every input, which are a large share of contact form spam. Bots that render the page like a browser can skip hidden fields, so pair it with server-side validation and rate limits.

Is it people or bots sending this spam?

Both. Link spam and gibberish are almost always automated. Polished sales pitches are usually written by people, and no bot check stops those; a filter on repeated phrases is the practical answer.

Will hiding my email address help?

It removes one source of inbox spam, since harvesters can't collect an address that isn't on the page. Visitors can still reach you through the form, and you can show a phone number or postal address if people need another route.

Sources

  1. W3C: Inaccessibility of CAPTCHA, checked
  2. W3C: Understanding SC 3.3.8 Accessible Authentication (Minimum), checked