
How to Stop Comment Spam on a WordPress Website?
Open comments on a new WordPress site and the first visitors are rarely people. Within days, the moderation queue fills with links to casinos, pharmacies, and SEO services, generic praise written to slip past filters, and pingbacks from sites you have never heard of. Left alone, spam buries real conversations, adds rows to your database, slows the admin, and can publish links that damage your site's reputation with search engines.
No single setting stops all of it. What works is a set of layers: WordPress's own Discussion settings to hold suspicious comments, a spam filtering service to classify the rest, a cheap trap that catches automated bots, and closing the doors spammers use that real visitors never do.
This article covers how comment spam reaches your site, the Discussion settings that matter most, how to use Akismet or Antispam Bee, how to add a honeypot field and a minimum submission time with a few lines of PHP, when to add Cloudflare Turnstile, how to shut off pingbacks and attachment comments, and how to clean up a spam backlog with WP-CLI.
How Comment Spam Reaches Your Site
Most comment spam is automated. Bots crawl the web for WordPress sites and post directly to wp-comments-post.php, often without ever loading the page that contains the form. Others submit through the form like a person would, and a small share is posted by low-paid humans who are hard to tell apart from real commenters.
| Source | How it arrives | What stops it best |
|---|---|---|
| Simple bots | Direct POST to wp-comments-post.php | Honeypot, minimum time check |
| Form-filling bots | Submit the real form with filled fields | Akismet or Antispam Bee, Turnstile |
| Human spammers | Typed comments with a link | Moderation rules, link limits |
| Pingbacks and trackbacks | XML-RPC and trackback endpoints | Disabling pingbacks and trackbacks |
| Old posts | Targeted because they rank and get less attention | Auto-closing comments after N days |
Because the sources are different, the defenses need to be layered.
Step 1: Configure the Discussion Settings
WordPress has useful spam controls built in. Go to Settings → Discussion and review these options.
Default post settings
- Allow link notifications from other blogs (pingbacks and trackbacks) on new posts. Turn this off. Real pingbacks are rare today, and the feature is a major spam channel.
- Allow people to submit comments on new posts. Leave this on if you want comments, or turn it off sitewide if you do not. You can still enable comments on individual posts.
Other comment settings
- Comment author must fill out name and email. Keep this on. It stops the laziest bots.
- Users must be registered and logged in to comment. Enable this only on community or membership sites. It almost eliminates spam but also most casual comments.
- Automatically close comments on posts older than 14 days. Spammers target older posts, which often rank well and get less attention. Set a value that suits your content, such as 30 or 60 days.
Before a comment appears
- Comment must be manually approved. The strongest setting, because nothing goes public without your review. It suits sites with modest comment volume.
- Comment author must have a previously approved comment. A good middle ground. A visitor's first comment is held for moderation, and later comments from the same name and email appear automatically.
Comment Moderation
Hold a comment in the queue if it contains 2 or more links. Most legitimate comments contain no links, so lower this to 1 if spam with a single link gets through.
The text box below it holds words, names, URLs, emails, or IP addresses that send a matching comment to the moderation queue.
Disallowed Comment Keys
Comments matching anything in this list are sent straight to the trash. Add terms that only appear in spam on your site: specific domains, product names, or phrases you see repeatedly.
Matching is broad: each line is matched inside words as well, so a short term such as cam would also catch "campaign" and "camera". Use longer, specific phrases and domains, and review the trash occasionally for false positives.
After changing the settings, click Save Changes. For more on turning comments on and off, see how to enable comments on WordPress posts and how to disable or enable comments on specific WordPress pages.
Step 2: Add a Spam Filtering Plugin
Discussion settings decide what to hold. A spam filter decides what is spam, and that is where most of the work happens.
Akismet
Akismet, made by Automattic, sends each comment to its service, which compares it against patterns from millions of sites and returns a verdict. Spam goes to the Spam folder, and Akismet keeps a history for each comment showing why it was classified.
- Go to Plugins → Add New Plugin, search for Akismet Anti-spam, then install and activate it.
- Go to Settings → Akismet Anti-spam (or follow the setup prompt) and connect it with an API key.
- Choose whether to discard the worst spam automatically or keep everything in the Spam folder for review.
Akismet is free for personal, non-commercial sites. Commercial sites, including business sites and stores, need a paid plan. Because comment data is sent to an external service, mention Akismet in your privacy policy. Akismet can display a notice under the comment form explaining how comment data is processed.
Antispam Bee
Antispam Bee is a free alternative that does its checks locally on your server, with optional checks such as language detection. It is popular with sites that want to avoid sending comment data to a third party.
- Install and activate Antispam Bee from Plugins → Add New Plugin.
- Go to Settings → Antispam Bee and enable the checks that fit your site, such as trusting approved commenters and checking the comment form's timing.
- Decide whether to mark spam or delete it immediately, and how long to keep spam before automatic deletion.
Use one filtering plugin, not both. Two filters interfering with each other make false positives harder to diagnose.
Step 3: Add a Honeypot Field
A honeypot is a form field that humans never see but bots fill in, because bots tend to complete every input. If the field has a value, the comment is spam. It costs nothing, needs no external service, and does not bother real visitors.
Add the following as a must-use plugin so it keeps working regardless of your theme:
<?php
// wp-content/mu-plugins/comment-honeypot.php
/**
* Plugin Name: Comment Honeypot
* Description: Adds a hidden honeypot field and a minimum time check to the comment form.
*/
const WSM_HONEYPOT_FIELD = 'wsm_website_url';
const WSM_MIN_SECONDS = 4;
// 1. Add the hidden fields to the comment form.
add_action( 'comment_form', function () {
$timestamp = time();
$signature = wp_hash( 'comment-form-' . $timestamp );
?>
<p class="wsm-hp" aria-hidden="true" style="position:absolute;left:-9999px;">
<label for="<?php echo esc_attr( WSM_HONEYPOT_FIELD ); ?>">Leave this field empty</label>
<input type="text" name="<?php echo esc_attr( WSM_HONEYPOT_FIELD ); ?>" id="<?php echo esc_attr( WSM_HONEYPOT_FIELD ); ?>" value="" tabindex="-1" autocomplete="off">
</p>
<input type="hidden" name="wsm_ts" value="<?php echo esc_attr( $timestamp ); ?>">
<input type="hidden" name="wsm_sig" value="<?php echo esc_attr( $signature ); ?>">
<?php
} );
// 2. Mark suspicious comments as spam before they are saved.
add_filter( 'pre_comment_approved', function ( $approved, $commentdata ) {
// Only check regular comments from visitors who are not logged in.
if ( is_user_logged_in() || ( ! empty( $commentdata['comment_type'] ) && 'comment' !== $commentdata['comment_type'] ) ) {
return $approved;
}
$honeypot = isset( $_POST[ WSM_HONEYPOT_FIELD ] ) ? trim( wp_unslash( $_POST[ WSM_HONEYPOT_FIELD ] ) ) : '';
$timestamp = isset( $_POST['wsm_ts'] ) ? absint( $_POST['wsm_ts'] ) : 0;
$signature = isset( $_POST['wsm_sig'] ) ? sanitize_text_field( wp_unslash( $_POST['wsm_sig'] ) ) : '';
// Bot filled the hidden field.
if ( '' !== $honeypot ) {
return 'spam';
}
// Fields missing or tampered with: the form was not loaded from this site.
if ( ! $timestamp || ! hash_equals( wp_hash( 'comment-form-' . $timestamp ), $signature ) ) {
return 'spam';
}
// Submitted faster than a human could type a comment.
if ( time() - $timestamp < WSM_MIN_SECONDS ) {
return 'spam';
}
return $approved;
}, 10, 2 );
How it works:
- The
comment_formaction runs inside the comment form, so the fields are added to every theme's form. The honeypot is moved off-screen rather than hidden withdisplay: none, which some bots detect. It is also removed from keyboard navigation withtabindex="-1"and hidden from screen readers witharia-hidden, so real users never land on it. - The signed timestamp records when the form was rendered.
wp_hash()signs it with your site's secret salts, so a bot cannot forge an old timestamp, and a direct POST without the fields fails the signature check. pre_comment_approvedlets you change the approval status just before the comment is saved. Returning'spam'sends the comment to the Spam folder instead of rejecting it outright, so you can review false positives.- Logged-in users and pingbacks are skipped, so the check only applies to visitor comments.
Two cautions. Full-page caching is not a problem: a cached page carries an older timestamp and its matching signature, so the signature still validates and the minimum time check simply passes. A custom comment form is a problem: if your theme's form does not call the comment_form action, the hidden fields will be missing and every visitor comment will be marked as spam. Post a test comment while logged out after installing.
Step 4: Add Cloudflare Turnstile for Heavy Spam
If spam still gets through, add a challenge. Cloudflare Turnstile is a CAPTCHA alternative that verifies visitors in the background in most cases, without asking them to click images. It is free and does not require using Cloudflare for your DNS.
- In the Cloudflare dashboard, open Turnstile, add your site's domain, and copy the site key and secret key.
- Install a WordPress Turnstile integration plugin, such as Simple Cloudflare Turnstile, and enter the keys.
- Enable it for the comment form, and optionally for login, registration, and password reset forms.
Turnstile, Google reCAPTCHA, and hCaptcha all add a third-party script and process visitor data, so mention them in your privacy policy. Use a challenge only when the earlier layers are not enough. Every extra step slightly reduces genuine comments.
Step 5: Close the Side Doors
Disable pingbacks and trackbacks completely
Turning off pingbacks in Discussion settings only affects new posts. Older posts keep their setting, and the XML-RPC pingback method stays available. To shut both off sitewide:
<?php
// wp-content/mu-plugins/disable-pingbacks.php
/**
* Plugin Name: Disable Pingbacks
*/
// Close pings on every post, old and new.
add_filter( 'pings_open', '__return_false' );
// Remove the XML-RPC pingback method.
add_filter( 'xmlrpc_methods', function ( $methods ) {
unset( $methods['pingback.ping'], $methods['pingback.extensions.getPingbacks'] );
return $methods;
} );
// Remove the X-Pingback header.
add_filter( 'wp_headers', function ( $headers ) {
unset( $headers['X-Pingback'] );
return $headers;
} );
Note that the xmlrpc_enabled filter, which is often recommended for this, only disables XML-RPC methods that require authentication. It does not stop pingbacks, which is why the code above removes the pingback method directly.
Disable comments on media attachments
Every image you upload gets its own attachment page, and those pages can accept comments. Few people notice them, which makes them an easy target:
<?php
// wp-content/mu-plugins/disable-attachment-comments.php
/**
* Plugin Name: Disable Attachment Comments
*/
add_filter( 'comments_open', function ( $open, $post_id ) {
if ( 'attachment' === get_post_type( $post_id ) ) {
return false;
}
return $open;
}, 10, 2 );
Since WordPress 6.4, new installations redirect attachment pages to the file itself by default. Older sites keep their previous behavior, so this filter is still worth adding.
Remove the website field
Many spammers comment only to get a link. Removing the Website field from the comment form takes away that incentive:
<?php
// wp-content/mu-plugins/comment-form-tweaks.php
add_filter( 'comment_form_default_fields', function ( $fields ) {
unset( $fields['url'] );
return $fields;
} );
WordPress already adds rel="nofollow ugc" to links in comments, so they pass little search value, but bots do not check before posting.
Cleaning Up a Spam Backlog
If your site already has thousands of spam or pending comments, clean them up from the command line rather than paging through the admin.
# Terminal
# Count comments by status
wp comment count
# Permanently delete everything in the Spam folder
wp comment delete $(wp comment list --status=spam --format=ids) --force
# Review pending comments before deleting them
wp comment list --status=hold --fields=comment_ID,comment_author,comment_content --number=20
If the shell complains that the argument list is too long, delete in batches with --number=1000 and repeat. Back up the database first. Deleted comments cannot be recovered.
Common Problems and Fixes
- Legitimate comments land in Spam. Check the Spam folder weekly and mark real comments as not spam, which trains Akismet. Remove overly broad entries from Disallowed Comment Keys.
- Every visitor comment is marked as spam after adding the honeypot. Your theme's comment form does not fire the
comment_formaction, so the hidden fields are missing. Add the action to the template or use a plugin-based honeypot. - Spam keeps arriving on old posts. Comments are still open on them. Enable automatic closing after a set number of days, or close comments in bulk from Posts → All Posts with the bulk edit option.
- Pingback spam continues after turning off the Discussion option. That setting only applies to new posts. Use the
pings_openfilter and remove the XML-RPC pingback method as shown above. - The moderation queue is overwhelming. Turn on Comment author must have a previously approved comment, lower the link threshold to 1, and add a spam filtering plugin.
- Spam comes from registered accounts. Disable open registration under Settings → General → Membership if you do not need it, and add Turnstile to the registration form.
WordPress Comment Spam FAQ
Combine several layers: tighten the Discussion settings, use a spam filter such as Akismet or Antispam Bee, add a honeypot field, disable pingbacks, and close comments on older posts. Add Cloudflare Turnstile only if spam still gets through.
Akismet is free for personal, non-commercial sites. Business sites, stores, and other commercial sites need a paid plan. Antispam Bee is a free alternative that runs its checks locally.
Yes, on most sites. Genuine pingbacks are rare, and the feature is a common spam channel. Turn off the option in Discussion settings and use the pings_open filter to close pings on existing posts as well.
Not when it is built correctly. Moving the field off-screen, adding tabindex minus one, and marking it aria-hidden keeps keyboard and screen reader users from reaching it, while bots that fill every field still trigger it.
Usually not. Discussion settings, a spam filter, and a honeypot stop most spam without adding friction. Add a low-friction challenge such as Cloudflare Turnstile only if spam continues.
It can. Published spam adds low-quality content and outbound links to your pages. WordPress adds nofollow and ugc to comment links, but it is still best to keep spam from ever appearing publicly.
Conclusion
Comment spam is a volume problem, and the solution is layers that each remove a share of it. Start with the free controls in Settings → Discussion: require name and email, hold first-time commenters, limit links, and close comments on older posts. Add Akismet or Antispam Bee to classify what remains. A honeypot and a signed timestamp stop most automated bots before they reach the filter, and closing pingbacks and attachment comments removes channels real visitors never use.
Review the Spam folder occasionally to catch false positives, and add a challenge such as Cloudflare Turnstile only if spam still gets through. With those layers in place, your moderation queue goes back to what it should be: real readers starting real conversations.
Here are some useful references for going deeper on comment spam in WordPress:
- WordPress Documentation: Discussion Settings — every option on the Discussion screen explained.
- WordPress Developer Resources: pre_comment_approved — the filter used to set a comment's approval status.
- WordPress.org Plugins: Akismet Anti-spam — the spam filtering service from Automattic.
- WordPress.org Plugins: Antispam Bee — a free, locally run spam filter.
- Cloudflare Docs: Turnstile — how Turnstile works and how to get site keys.


