What actually protects a form: CAPTCHA, honeypot, time trap, CSRF
Most contact forms rely on a single trick against spam, and many of those tricks only stop the simplest bots. What each protection layer stops, what it costs, and which combination makes sense.
Spam through contact forms rarely comes from a person typing by hand. Mostly it is software that finds forms, fills in every field and sends the result – thousands of times. Several defences exist, and they work at very different points. Knowing what each one really does helps you avoid two mistakes: a form with no real protection, and a form guarded so heavily that real people give up.
- Honeypot: simple bots that fill in every field
- Time trap: scripts that submit instantly after loading
- CAPTCHA: most generic automation
- CSRF token: requests sent straight to the endpoint
- Rate limit: floods from a single source
- Proof-of-work: cheap mass submissions, without tracking or puzzles
- Server-side checks: everything that bypasses the browser
- Targeted bots skip it; if badly hidden, screen readers announce it
- Bots that wait; without a server-side signature it is easy to forge
- A hurdle for everyone, accessibility barriers, often third-party; solving services exist
- Bots that load the page first get a valid token too
- Spam spread across many IP addresses
- A determined sender with computing power; needs JavaScript
- Nothing alone – but without them every other layer is decoration
Honeypot and time trap: invisible filters
A honeypot is an extra field people never see, such as a field called “website” hidden with CSS. Simple bots fill in every field, so a filled-in honeypot signals automation and the server can quietly discard the message. Bots written for your site, or ones that render the page like a browser, skip it. Hide it properly: a field merely moved off screen may be announced by screen readers, reached with the Tab key or filled in by autofill. Use aria-hidden, tabindex -1 and autocomplete off, plus a neutral label asking anyone who lands there to leave it empty.
A time trap records when the form was delivered and rejects submissions that arrive implausibly fast. People need a few seconds to read and type; many scripts send within a fraction of a second. The timestamp must be checked on the server and protected against tampering, for example signed or kept in the session – a plain hidden time field is simply rewritten by the bot. Keep the threshold low, since autofill makes real people fast too. Bots that simply wait get through: a time trap is a filter, not a wall.
CAPTCHA: effective, but not free
A CAPTCHA asks for proof that no bot is at work – from image puzzles to checks that run in the background; common services include reCAPTCHA, hCaptcha, Cloudflare Turnstile and Friendly Captcha. It stops most generic automation, which is why it is so popular. But every visible puzzle is a hurdle at which some visitors give up, and most services load a third-party script, which raises privacy and consent questions. A CAPTCHA also only helps if it is set up correctly: a public test site key, a widget without its script or a token the server never verifies looks like protection but is not. A free check on formexposed.com points out such errors from the outside.
Accessibility is part of that cost. Image puzzles shut out blind people and many people with low vision, audio alternatives do not help deaf-blind people, and tricky logic tasks burden people with cognitive impairments. WCAG 2.2 success criterion 1.1.1 requires a text alternative describing the CAPTCHA’s purpose and alternative forms for different senses. Background checks avoid most of this, but when they become suspicious, the fallback is often a visual puzzle again – test that path with a keyboard and a screen reader.
CSRF token: protection against forgery, not against spam
A CSRF token is a random value the server puts into the form and expects back. It was designed against cross-site request forgery, where another website makes a visitor’s browser send a request the visitor never intended. On a public contact form it has a side effect: bots that post straight to the form address without loading the page are rejected. Any bot that fetches the page and sends the token back gets through. Most frameworks and form plugins include CSRF tokens anyway – keep them on, but do not count them as spam protection.
What has to happen on the server
- Validate every field again on the server: required fields, length, e-mail format, and no line breaks in fields that end up in mail headers.
- Verify CAPTCHA and proof-of-work tokens on every submission, with the issuing service or in your own code, and reject tokens that are reused.
- Limit submissions per IP address and time window. That stops floods from one source; spam spread over many addresses needs other layers.
- Consider proof-of-work: before sending, the browser solves a small computational task. Visitors see no puzzle and nothing is tracked, but mass submission becomes expensive.
A sensible combination: two or three layers
- 1Start with the invisible layers: an accessible honeypot and a signed time trap, both checked on the server.
- 2Add a rate limit per IP address so that a single source cannot flood the form.
- 3If targeted spam still gets through, add proof-of-work or a CAPTCHA – preferably one without a visible puzzle and with an accessible alternative.
- 4Keep the CSRF token your framework provides – as a bonus, not as a defence.
- 5Test the result as a visitor – keyboard only, with a screen reader, on a phone – and check that real messages still arrive.
On many sites, honeypot, time trap and rate limit together already remove most generic spam without any visible hurdle; a CAPTCHA is the reserve for when that is not enough. On WordPress, the free formexposed plugin combines honeypot, time check and proof-of-work without needing Google. To see what your form shows from the outside – which layers are present, whether a CAPTCHA is configured effectively – a free check on formexposed.com needs only a domain, no account. It cannot see your server code, so the server-side part stays your job.