WordPress Security

Stopping Form Spam in WordPress Without Annoying Real Visitors

Stopping Form Spam in WordPress Without Annoying Real Visitors

I once inherited a site where the client had stopped checking their contact form entirely. It received around four hundred submissions a day, and perhaps three of them were from real people. The rest were SEO pitches, crypto scams and gibberish. The client had concluded that the form was useless, and they’d been losing genuine enquiries for months without realising. Tackling WordPress form spam properly means recovering those lost leads.

Form spam is one of those problems that seems minor until you add up the cost. Real leads get buried. Staff waste time sorting submissions. Auto-reply emails go to fake addresses and damage your sending reputation. And in some cases, spam bots use your form to send emails to other people, turning your site into a relay.

The good news is that almost all form spam can be stopped. The trick is to stop it in ways that real visitors never notice, and to save the visible challenges for when they’re truly needed.

Understand where the spam comes from

There are broadly three types of form spam, and each needs a slightly different approach.

Automated bots are the bulk of it. Scripts crawl the web looking for forms, fill in every field and submit. They don’t run JavaScript in many cases, they submit instantly and they often fill in fields that humans can’t see.

Smarter bots use headless browsers that execute JavaScript and behave more like humans. They’re less common but harder to catch with simple tricks.

Human spammers are real people, often paid very little, who manually fill in forms with sales pitches. No automated check will catch them reliably because they are, in fact, human.

A layered approach handles the first group almost entirely, the second group mostly and the third group partially.

Layer one: the honeypot

A honeypot is a form field hidden from humans with CSS but visible to bots reading the HTML. Humans leave it empty. Bots fill it in. If the field has a value, the submission is spam.

Most good form plugins include a honeypot option, sometimes enabled by default. Gravity Forms, WPForms, Fluent Forms and Formidable all have one. If yours doesn’t, it’s simple to add.

Honeypots have zero friction for real users, which is why they’re the first layer. They catch a large share of dumb bots on their own.

A small caution: don’t name the field something obviously fake like “honeypot”. Some bots skip fields with suspicious names. Use something plausible such as “website” or “company_url” and hide it properly, including from screen readers with aria-hidden and a tabindex of -1, so assistive technology users don’t fill it in by accident.

Layer two: timing checks

Humans take time to fill in a form. Even a short contact form takes ten seconds or more. Bots often submit within a second of the page loading.

A timing check records when the form was loaded and rejects submissions that come back too fast. Some form plugins include this. You can also implement it with a hidden timestamp field and a server-side check.

Set the threshold conservatively. Three to five seconds catches most bots without risk of blocking a fast human using browser autofill.

Layer three: invisible challenges

If honeypots and timing checks aren’t enough, the next step is an invisible challenge that verifies the browser behaves like a real one.

Cloudflare Turnstile

Turnstile is Cloudflare’s free alternative to CAPTCHA. It runs checks in the background and most visitors never see anything. When it isn’t sure, it shows a simple checkbox rather than a puzzle. It doesn’t require your site to be on Cloudflare, and it doesn’t use tracking cookies for advertising.

This is my default choice for most client sites now. Several form plugins support it natively, and there are integration plugins for those that don’t.

Google reCAPTCHA v3

reCAPTCHA v3 is also invisible. It gives each submission a score between 0 and 1 based on how human the behaviour seems, and you decide the threshold.

It works well, but it has drawbacks. It loads Google scripts on the page, which affects performance and raises privacy questions under GDPR. It also requires the reCAPTCHA badge to be visible or a disclosure text to be shown. Scores can be inconsistent for users with privacy-focused browsers or VPNs.

hCaptcha

hCaptcha is another option, popular with privacy-conscious sites. It has an invisible mode, but it shows visual challenges more often than Turnstile in my experience.

Layer four: content filtering

Some spam gets past behavioural checks, especially human-submitted spam. Content filtering looks at what was submitted rather than how.

Akismet works with many form plugins and checks submissions against a huge database of known spam. It’s excellent for comment spam and good for form spam.

Keyword and pattern rules catch the recurring pitches. If you keep getting messages about “SEO services” or links to particular domains, a rule that flags those words or blocks submissions containing links can cut volume dramatically. Many contact forms have no legitimate reason to contain URLs at all.

Field validation helps too. If your form asks for a phone number, validate that it looks like one. If it asks for a name, reject names that contain URLs. Bots often put junk in every field.

Be careful with blunt filters. Blocking every message that contains the word “free” will catch legitimate enquiries. Start by flagging rather than blocking, review what gets flagged for a week or two, then tighten.

Layer five: server and firewall rules

If spam volume is very high, it can affect server performance. Blocking at the server or firewall stops bad traffic before WordPress loads.

  • A web application firewall can block requests from known bad IP addresses and bot networks.
  • Rate limiting on form submission endpoints stops a single IP from submitting dozens of times a minute.
  • If your business only serves certain countries and spam comes overwhelmingly from elsewhere, country-based rules can help, though they also block legitimate visitors travelling or using VPNs, so use them carefully.

For sites under Cloudflare, a rate-limiting rule on the form’s submission URL is one of the most effective measures against high-volume attacks.

What about classic CAPTCHAs?

The old style CAPTCHA, the one that asks you to pick out traffic lights or type distorted letters, should be a last resort.

It frustrates real users and lowers conversion rates, sometimes noticeably. It’s a real barrier for people with visual or cognitive disabilities, which is an accessibility problem. And modern bots and CAPTCHA-solving services get through them anyway.

If you’ve added honeypots, timing checks, an invisible challenge and content filtering and you still have a spam problem, then a visible challenge on a specific form might be justified. But in most cases, the earlier layers make it unnecessary.

Don’t let your form send spam for someone else

This is the part people miss. Many forms send an automatic confirmation email to the address entered in the form. Bots exploit this by entering a victim’s email address and putting spam content in the name or message field. Your server then delivers that spam to the victim, from your domain.

The result is that your domain gets reported, your email deliverability suffers and your real messages start landing in spam folders.

To prevent this:

  • Don’t include user-submitted content in auto-reply emails. Keep confirmations generic: “Thanks, we’ve received your message.”
  • Only send auto-replies after the submission passes spam checks.
  • Consider whether you need auto-replies at all. An on-page confirmation message often does the job.

Check that the protection actually works

After setting up protection, test it. Submit the form yourself as a normal visitor and make sure it goes through. Try it on mobile, with autofill, and in a privacy-focused browser. Then check spam entries for a week and look for false positives.

Most form plugins keep a record of entries marked as spam. Review it occasionally, especially in the first few weeks, to make sure real enquiries aren’t being caught. Losing a real lead to an overzealous filter is worse than letting through the occasional spam message.

A sensible default setup

For most small business sites, this combination stops nearly all spam:

  1. A form plugin with a built-in honeypot, turned on.
  2. Cloudflare Turnstile in invisible or managed mode.
  3. Akismet or a simple rule that flags submissions containing links.
  4. Generic auto-reply emails, or none at all.

That’s usually enough. Add rate limiting or firewall rules only if you’re dealing with high-volume attacks, and add visible challenges only if everything else has failed.

Spam protection should be invisible to the people you want to hear from. If a real customer has to prove they’re human, you’ve made it harder for them to give you their business. Handled this way, WordPress form spam becomes a minor background nuisance instead of a daily chore.

Frequently asked questions

Why am I suddenly getting much more form spam?

Your form has likely been added to a bot’s target list. This happens when sites get more visible or when spam tools share lists. Volume often jumps suddenly. Adding an invisible challenge usually brings it back under control.

Does Turnstile work with any form plugin?

Many popular form plugins now support it natively. For those that don’t, integration plugins exist. Check that the integration verifies the token on the server, not only in the browser.

Should I put a CAPTCHA on my login page too?

Login pages are better protected with rate limiting, strong passwords and two-factor authentication. An invisible challenge can help against bots, but it’s not a substitute for those measures.

Is Akismet free?

Akismet is free for personal, non-commercial sites. Business sites need a paid plan. For many small businesses the cost is easily justified by the time saved.