Spam
Akismet isn't enough — what to layer
Akismet is the WordPress default for spam. But it's not a complete solution. Here's the four-layer setup I run on production sites.
Akismet has been the WordPress default for spam since 2005. It’s still good. It’s still worth running. But on its own, it’s not a complete spam solution.
I learned this the hard way after a client’s contact form ate 4,000 spam submissions in a week despite Akismet being on. Akismet flagged them all correctly. The submissions still hit the database, still triggered email notifications, still filled the inbox.
Here’s the four-layer setup that actually works.
What Akismet does well
Akismet is a reputation database. It’s seen this email address, this user agent, this IP, this content pattern before, and it knows whether it spammed elsewhere on the web.
That’s a powerful signal. Especially for content-heavy spam (the “great article! Visit my pharmacy site” kind). Akismet catches that with high precision.
What Akismet doesn’t do well:
- Block submissions before they’re stored. Akismet flags. Storage decisions are up to your forms plugin.
- Catch unique-content spam. New domain, new email, real-looking message. Akismet has no signal yet.
- Rate-limit. A spammer who submits 200 forms in 10 seconds will trigger 200 Akismet checks. Akismet doesn’t slow them down.
- Throw away truly junk traffic. Bots that probe
/wp-content/forms/submit.phpto find form endpoints? Akismet doesn’t see those.
That’s why you layer.
Layer 1: Honeypot
The honeypot is a field that humans don’t see and bots fill in. Bots submit every input on a form. Humans only fill what they’re shown.
Core Forms ships a honeypot by default — every form rendered through [cf_form] or the Gutenberg block has an invisible field named something like _cf_h47abc. If the field comes back filled, the submission is dropped silently.
This catches the lazy 60% of bot traffic. The bots that just iterate through <input> fields without rendering JavaScript.
You don’t configure this. It’s on by default. Don’t disable it.
Layer 2: Rate limit
A real human submits a form once. Maybe twice if they made a typo. A bot submits 200 times in two minutes.
Core Forms has a per-IP rate limit setting in Settings → Submission limit. I default to 5 submissions per IP per hour. The threshold is loose enough that legitimate retries pass, tight enough that bots get cut off.
This catches the medium 30% of bot traffic. The bots that try to fuzz the form by submitting many variants quickly.
Layer 3: Captcha (the right one)
Now you’re at the bots that submit at human pace, with realistic content. They need to pass a captcha to reach Akismet.
Pick one of reCAPTCHA v3, Cloudflare Turnstile, or hCaptcha. I covered the comparison in detail elsewhere, but the short version:
- High-volume client sites with real money on the line: reCAPTCHA v3 with a 0.5-0.7 threshold.
- Privacy-conscious sites: Cloudflare Turnstile.
- Compliance-paperwork-needed sites: hCaptcha.
Captcha catches another 9% of bots. The ones that have realistic content but can’t solve the silent verification.
Layer 4: Akismet
What’s left after the first three layers is a small stream of submissions, mostly humans, with the occasional sophisticated spammer who passed all three.
That’s where Akismet earns its keep. The spammer with realistic-looking content but a flagged email address gets caught here.
Core Forms checks Akismet on every submission that made it past honeypot, rate limit, and captcha. The flagged submission is stored as spam (so the bot thinks they succeeded), but it’s quarantined to the Spam tab. Your inbox doesn’t see it.
The whitelist (in Settings → Akismet) is for false positives. Add gauravtiwari.org and submissions from your own domain skip the Akismet check. Useful for testing.
What this catches in practice
Running all four on a typical contact form, here’s what the funnel looks like over a month:
Total form submissions: 3,200
- Honeypot dropped: 1,900 (60%) — never stored
- Rate-limit dropped: 800 (25%) — never stored
- Captcha rejected: 300 (9%) — never stored
- Akismet flagged: 150 (4.5%) — stored as spam, hidden
- Real submissions: 50 (1.5%) — your inbox
Without the layers, you’d see 3,200 submissions in the inbox. With them, 50. That’s a ~64x reduction.
The exact numbers vary by site. The pattern doesn’t.
What you should not do
Don’t disable Akismet because “captcha catches everything.” Captcha catches simple bots. Akismet catches reputation-flagged content. Different threat models, both useful.
Don’t run multiple captchas. I see this on audits all the time. reCAPTCHA + hCaptcha + Turnstile, all loaded on the same page. They don’t compound — they conflict. Pick one.
Don’t rate-limit too tight. 1 submission per IP per hour catches bots and also catches a real user with a typo. Test with 5/hour, watch for false positives, tune from there.
Don’t trust “Akismet’s premium plans.” The paid plans add features for comments. For form submissions, the free Akismet API key works fine.
The fast audit
On any site running Core Forms:
1. Open Settings → Submission limit. Confirm "5 per IP per hour" or similar.
2. Open Form → Settings → Spam protection. Confirm honeypot is on (default).
3. Confirm one captcha is wired (recaptcha/hcaptcha/turnstile).
4. Open Settings → Akismet. Confirm API key is present.
5. Open Spam tab. Look at last week's count.
If the Spam tab is empty, either you don’t get spam (lucky), or one of the layers is silently dropping things you don’t realize.
The next step
Audit one form. Confirm all four layers are wired. Check the Spam tab against your inbox for the last week.
The goal isn’t zero spam. The goal is no spam in the inbox. Akismet on its own can’t promise that. The layered setup can.
All four layers (honeypot, rate limit, captcha, Akismet) are bundled with every Core Forms license. Pricing.