Illustration of a funnel and mesh gate catching a stream of small robot shapes while a person slips through a side door with an envelope

Spam Form Submissions on WordPress? CAPTCHA, Cloudflare and What Still Gets Through

Bots keep filling your WordPress contact form with junk. Here's how to layer a honeypot, a CAPTCHA and Cloudflare, set them up in WPForms and Forminator, and what no tool will stop.

Your contact form used to bring in a lead or two a week. Now it brings in forty messages a day, and thirty-nine of them are someone selling you backlinks.

The clutter is the small cost. The bigger one is the genuine customer message at the bottom of the pile, and a team that has learned to ignore every notification email because it's always junk.

Here's the deal: you can stop most of it. You can't stop all of it, and no CAPTCHA changes that. Both halves matter.

The quick answer

  1. Turn on your form plugin's built-in spam checks first: the honeypot and the minimum-time-to-submit check. Visitors never notice them.
  2. Add Cloudflare Turnstile as your CAPTCHA. It's free to use, and both WPForms and Forminator support it.
  3. If your site also sits behind Cloudflare, add one narrow rule for POST requests to the form's path, plus a rate limit. Don't switch on every bot setting you can find.
  4. Test as a visitor, on a computer and on a phone. Then check the plugin's entries.
  5. Accept that some junk is typed by humans. Shorten the form and set up a triage habit.

The rest of this post is the detail for each step, plus the part most guides skip: the tools that block bots also block some automation you actually want.

Platform steps below are as of October 2026, and each one names the vendor page it came from. Plugin screens get renamed between versions, so if a label doesn't match, look for the closest one.

1. What you're fighting

Two different things land in your inbox, and they need different defenses.

Bots. Scripts that find a form, fill every field and press submit, over and over. Some post straight to your form's address and never load the page at all. Bots are cheap and relentless, and they're what the rest of this post stops.

Humans. A sales rep pasting the same pitch into every contact form on a list. Someone paid a few cents per submission to drop a link. A person with a script and a lot of free time. They open the page in a real browser, so they pass every check built to spot a machine.

What the junk usually looks like:

  • Sales pitches: "We can get your site to page one."
  • Link drops: a message that's mostly a URL.
  • SEO and web design offers dressed up as a customer question.
  • Fake leads with a made-up name and an email address that bounces.
  • Phishing attempts, with a link or attachment request in the message.

What it costs: time, buried real leads, junk records in your CRM, and notification emails nobody reads anymore. If the junk also triggers an auto-reply from your site, you're sending mail to addresses you don't control.

If your ads count every form submit as a lead, junk also skews your numbers. We covered that side in AI spam leads are exploding.

2. The layers, and which to try first

No single layer catches everything. Stack them, cheapest and quietest first.

  1. Honeypot. A hidden field people never see. Simple bots fill in every field, so a filled hidden field marks the submission as spam. No friction for visitors.
  2. Time-to-submit check. A real person takes more than a couple of seconds to fill in a form. A script often doesn't.
  3. Built-in filter. Akismet, if your form plugin supports it and you already use it.
  4. CAPTCHA or challenge. Turnstile, reCAPTCHA or hCaptcha. This adds a check the visitor may see.
  5. Edge blocking. Cloudflare rules in front of the site, which stop traffic before WordPress does any work.

Try layers 1 and 2 first. They're already in your plugin, they cost nothing, and they take five minutes. Add a CAPTCHA if junk still comes through. Add the Cloudflare layer if bots are hammering the form so hard they slow the site or fill your database.

3. CAPTCHA options compared

A CAPTCHA is a check the visitor has to pass before the form submits. Here's how the common ones compare. The first three rows are Google's reCAPTCHA, which comes in three versions.

Google's older reCAPTCHA pages are marked deprecated and point to Google Cloud Fraud Defense, so check Google's current docs before you set up a new site.

Option

What the visitor sees

Notes

Our take

reCAPTCHA v2 checkbox

An "I'm not a robot" box, sometimes followed by a picture puzzle

Google's versions page says the user clicks a checkbox and either passes at once or is challenged

Familiar, and visible. Fine if you already use it

reCAPTCHA v2 invisible

Usually nothing

Per Google, only the most suspicious traffic is prompted to solve a challenge by default

A reasonable pick if you want no checkbox

reCAPTCHA v3

Nothing, ever

Returns a score from 0.0 (likely a bot) to 1.0 (likely a person), and Google says a default threshold of 0.5 is a start. The form has to decide what to do with a low score

WPForms' docs recommend it only for advanced users. Skip it unless you'll watch the scores

hCaptcha

A checkbox, with image challenges at a difficulty you set

WPForms describes it as a free reCAPTCHA alternative that focuses on user privacy

Good alternative if you don't want Google involved

Cloudflare Turnstile

Usually nothing, or a short check in the widget

Three widget modes: Managed, Non-Interactive and Invisible (Cloudflare). Free plan, per Cloudflare's plans page

What we'd try first. Works without moving your site to Cloudflare

WPForms Custom Captcha

A math question or a question you write

Needs a paid WPForms license, per WPForms

No third party. Easy for a determined script, and annoying for people

A few notes the table can't hold.

Cost. Cloudflare's plans page lists Turnstile on the Free plan with unlimited challenges. For reCAPTCHA, Google's tier comparison lists a free Essentials tier of up to 10,000 assessments per calendar month, and says it requires a valid billing instrument in Google Cloud. If your form gets that many submissions, you have a different problem.

Privacy. Google's reCAPTCHA FAQ says reCAPTCHA sets a cookie named _GRECAPTCHA when it runs. If your privacy policy lists the services your site uses, add whichever one you pick.

Accessibility. Any check that asks someone to pick traffic lights is harder for some people than for others. WPForms has a page on CAPTCHA accessibility options. Invisible methods help, and so does a plain phone number next to the form, so nobody gets locked out.

Forminator doesn't have its own question-style CAPTCHA that we could find in its docs. It uses a honeypot plus the three providers above (reCAPTCHA, hCaptcha and Turnstile).

4. Set it up in WPForms

WPForms has two jobs here: switch on the quiet checks, then add a CAPTCHA.

Step 1: The quiet checks

What it is. WPForms' spam prevention guide describes its modern anti-spam protection as a honeypot-based, multi-layer check. It says forms made after version 1.6.2 use it, and older forms may still use the legacy honeypot. The same page says the minimum time to submit is on by default at 2 seconds.

Where to look. Open the form in the builder, go to Settings, then look for Spam Protection and Security. As of October 2026, that's the screen WPForms' docs name.

What good looks like. The anti-spam protection is on, and the minimum time setting is on.

Akismet. If you use Akismet, WPForms has a setup page. The toggle sits on the same screen, but WPForms says you won't see it if your site isn't connected to an Akismet account. Look for an option to store spam entries rather than block them. While you're testing, storing is the safer choice, because you can see what it caught.

Step 2: Add a CAPTCHA

The three provider integrations (reCAPTCHA, hCaptcha and Turnstile) are available in every version of WPForms, including Lite, according to WPForms' CAPTCHA guide. The steps are the same pattern each time:

  1. Get keys from the provider. Every provider hands you a site key (public, goes in the page) and a secret key (private, stays on the server).
  2. Paste them into WPForms. Go to WPForms > Settings and look for the CAPTCHA tab. Choose the provider, paste both keys, and save.
  3. Turn it on for the form. In the form builder, go to Settings > Spam Protection and Security and switch on the CAPTCHA for that form. WPForms also lets you drag a CAPTCHA field into the form.
  4. Confirm it appears. WPForms says the preview or builder shows an error if the keys are wrong, and a truncated paste is the usual cause.

Provider notes, from WPForms' own docs:

  • Turnstile. In Cloudflare, create a Turnstile widget with a name and your domain. WPForms recommends leaving the mode on Managed, the default. One key pair can cover several domains. If both WPForms and your theme load Turnstile, it can stop working, so load it once.
  • reCAPTCHA. Each version needs its own key pair, so a v2 checkbox key won't work for v3. WPForms' reCAPTCHA page lists v2 Checkbox, v2 Invisible and v3, and says you can keep using v2 or v3 after Google moves your keys into a Google Cloud project.
  • hCaptcha. Add your site in hCaptcha to get the site key, and your account has one secret key shared across sites, per WPForms' hCaptcha page. It also covers the difficulty setting, and recommends Auto.
  • Custom Captcha. A paid-license feature. Math is the default type, and you can switch to your own question and answer, per WPForms' Custom Captcha page.

How to confirm it works. Open the page in a private window and submit the form like a customer. It should go through, and the entry should appear in WPForms. Then check the page on your phone. If the widget doesn't load or the form won't submit, re-copy both keys first.

5. Set it up in Forminator

Forminator keeps its CAPTCHA keys in one plugin-wide place and its quiet checks inside each form. This section follows the Forminator documentation, which was written for a recent version, so labels may differ in yours.

Step 1: The quiet checks

Honeypot. Per the docs, the honeypot sits under Behavior > Security in the form's editor. The docs describe it as a hidden input that's only created when the form loads in a browser. Bots that fill it in are treated as failed, and they get a fake success message.

Akismet. Akismet has to be installed and active first. Forminator then lets you either show a custom failure message or mark the entry as spam. The docs say marked entries are logged in the database but don't appear in your Submissions list. They also say the default failure text is "Something went wrong." If a real person reports that message, turn Akismet off for a moment to test it. Akismet gives Forminator a pass or fail with no sensitivity setting, so the docs suggest relying on a CAPTCHA and the honeypot instead if it flags real people.

Step 2: Add a CAPTCHA

  1. Get keys from Google, hCaptcha or Cloudflare.
  2. Paste them into Forminator. Look for the CAPTCHA page in Forminator's settings, choose the provider, paste the site key and secret key, and save. The docs say this has to happen before you add the field. Otherwise the form shows a prompt that links to it.
  3. Add the CAPTCHA field to the form and pick the provider in the field's settings.

Provider notes, from the same documentation:

  • reCAPTCHA. Forminator supports v2 Checkbox, v2 Invisible, v3 and Enterprise. Enter correct keys for each version you plan to use, or saving the field's settings will fail.
  • hCaptcha. Add your domain under Hostnames in hCaptcha first. One set of keys covers the checkbox and invisible types.
  • Turnstile. The widget mode can be Managed, Non-interactive or Invisible. Alignment applies only to the first two, because an invisible widget has nothing to align. After you save the keys, a widget preview confirms the setup. Older Forminator installs may need an update to get Turnstile.

How to confirm it works. Same test as above: a private window, a real submission, an entry in Forminator's Submissions. If it's missing, check whether Akismet marked it as spam, since marked entries are hidden from Submissions.

6. Cloudflare: stop bots before WordPress sees them

A form plugin only checks the submission after it reaches your site. Cloudflare sits in front of the site, so it can turn traffic away earlier. That also takes load off WordPress.

Cloudflare's guide for this, Protect your forms from spam and abuse, runs in this order:

  1. Turnstile on the form, with the token checked on the server. Cloudflare says the widget alone doesn't protect a form, because attackers can post directly to the form's address. Your plugin does that server check for you once the keys are in.
  2. A rate limit on POST requests to the form's path. Rate limiting counts requests from each visitor and acts above a limit you set. Cloudflare's guide says to look at your normal submission rate first and set the limit above it. It recommends a managed challenge as the action on Pro and above.
  3. A custom rule that challenges POST requests to the form path from sources that aren't verified bots. Start with a challenge, not a block, and watch what it catches before you tighten it.
  4. Bot Fight Mode, from the security settings.
  5. Monitor. Review Security Events, filtered to your form's path.

What each plan gets. Cloudflare's docs describe two settings with similar names. Bot Fight Mode is the free on/off switch. Super Bot Fight Mode is the more configurable version, with a separate action for each type of bot, including verified bots, and it needs a Pro plan or higher. Check Cloudflare's Super Bot Fight Mode page for what your plan includes. Cloudflare's WAF overview lists rate limiting on the Free plan with one rule.

How to confirm it works. In Security Events, you should see challenged or blocked requests for the form's path after you turn a rule on. Then submit the form yourself from a normal browser and confirm it still goes through. If your own submission gets challenged more than once, the rule is too tight.

7. The downside: Cloudflare blocks good automation too

Everything in section 6 has a catch. A rule built to stop bad automation can't always tell bad from good, and the good kind is a bigger share of your traffic than it used to be.

Things that can get caught:

  • AI agents and assistants acting on behalf of a person, like one filling in your contact form for a customer who asked it to.
  • AI search crawlers that decide whether you show up in AI answers. We cover that choice in Should my small business block AI bots?
  • Uptime monitors that check your site on a schedule.
  • Payment and webhook callbacks from services that post to your site, like a payment processor confirming an order.
  • Search engine crawlers, if a rule is too broad.
  • Accessibility tools and assistive software.

Bot Fight Mode can't be exempted. Cloudflare's docs say it can't be skipped with a custom rule, because it runs outside the rules engine. Their false-positives page says your options are to turn it off or upgrade to Super Bot Fight Mode, which does allow Skip rules. The same docs describe Super Bot Fight Mode as the one with verified-bot handling.

Verified bots are the easy case. Cloudflare keeps a list of verified bots. A bot has to identify itself honestly and behave, for instance by following robots.txt. Since July 2026, Cloudflare's docs say agents that used to be labeled "signed agents" count as verified bots too, tagged as intermediaries. An AI assistant that isn't on that list gets treated like any other unknown automation.

How to carve out exceptions without opening a hole:

  1. Scope rules to the form's path and to POST requests only. A rule that covers the whole site is how crawlers and monitors get caught. Pages that visitors read don't need bot challenges, and the form submission does.
  2. Leave verified bots alone. Cloudflare's own form rule excludes them.
  3. For a specific service you trust, use a custom rule with the Skip action, scoped as narrowly as you can. That's the usual route, and the narrower, the better.
  4. Use a challenge before a block. A challenge lets a real person through. A block doesn't.
  5. Watch Security Events for a week after any change, and look for the monitor or service you rely on.
  6. Test with the real thing. Run your uptime monitor, a test payment or a test webhook, and see what Cloudflare did with it. If you want AI agents to find and use your form, try one.

None of this is a reason to skip Cloudflare. It's a reason to scope the rules, test them, and look at the logs.

8. You will never fully stop it

Back to the humans from section 1.

A person typing into your form passes every CAPTCHA, because a CAPTCHA tests for a machine, not for bad intent. A honeypot doesn't fool them. A rate limit won't trip on one message. No setting stops a sales rep from pasting a pitch.

So the goal changes. You stop the bots, and you lower what the humans cost you.

  • Keep the form short. Name, email, a message, and one question that's specific to your business. Fewer fields means fewer places to paste a pitch.
  • Add a required field bots and pitchers mis-fill, like a dropdown for what the person needs. Open text boxes are where pitches go.
  • Filter on the receiving end. Most mail systems let you build a rule that sends messages containing "page one of Google" or "guest post" to a folder instead of the inbox. Check that folder weekly, because filters make mistakes.
  • Triage in one place. Have form entries land in a shared inbox, a CRM or a ticket queue instead of one person's email, so someone owns the cleanup.
  • Don't auto-reply to everything. An auto-reply to a fake address is mail you shouldn't be sending.
  • Say who the form is for, in a line above it. "This form is for questions about our services. We don't respond to sales offers." It won't stop a script, and sometimes it stops a person.

We don't know a way to remove human spam entirely, and anyone selling that is overselling.

9. What we'd do on a typical small-business contact form

For a WordPress site with one contact form and no IT department:

  1. Confirm the honeypot and the minimum-time check are on in your form plugin. Five minutes.
  2. Add Turnstile. Create the widget, paste the keys into the plugin, switch it on for the form.
  3. Test as a customer in a private window and on your phone. Check that the entry arrived.
  4. Cut the form down to the fields you use.
  5. Set an inbox rule for the pitches you see most.
  6. Wait two weeks. Look at what still comes through before you add anything.
  7. Only then look at Cloudflare rules, and scope them to the form's POST.
  8. Check Security Events after any change, for anything you rely on.

Do this one change at a time. Over-filtering is quiet. You never see the customer who gave up.

10. When to get help

Bring in someone if:

  • Junk still arrives in volume with a CAPTCHA and the quiet checks on.
  • Real customers say the form won't submit.
  • The site slows down or the database fills up with form entries.
  • You can't tell whether a Cloudflare rule is blocking something you need, like a payment callback.
  • You suspect the form has been used to send mail or probe your site, and you're not sure the site hasn't been compromised. Start with WordPress site hacked? First steps.

If you'd like a hand with the WordPress side, see our WordPress care and security work, or get in touch.

Related reading

No comments yet

Managed Nerds Weekly

Get the week's posts in one email

New IT, security and SEO posts every Monday. That's it.