Using timestamps to reduce WordPress comment spam

Update 8.27.11: The method described in this post uses PHP to generate the timestamps. If your site is using a caching plugin, the timestamps in the HTML will be stale, and this method will not work. Please see my updated post at A cache-friendly method for reducing WordPress comment spam for a new method using JavaScript for sites that use page caching.

In this post, I’ll explain how to reduce the amount of comment spam your WordPress blog receives by using an unobtrusive ‘handshake’ between the two files necessary for a valid comment submission to take place. I’ve written a few different articles on reducing comment spam by means of a challenge response test that the visitor must complete before submitting a comment, but I’m now looking for ways to achieve the same results while keeping the anti-spam method invisible to the visitor.

I’m a big fan of Akismet, but I also want to block as much spam as possible before it is caught by Akisment in order to reduce the number of database entries.

One thing this method does not do is rename and hide the path to the form processing script, but it makes that technique obsolete, anyway.

In the timestamp handshake method, a first timestamp is generated and written as a hidden input field when the post page loads. When the comment is submitted, a second timestamp is generated by the comment-processing script and it and the page-load timestamp are saved as variables. If the page-load timestamp variable is blank, which should be the case if the spambot uses any other page to populate the comment, the script will die. The page-load timestamp is then subtracted from the comment-submission timestamp. If the comment was submitted less than 60 seconds after the post page was loaded, the script dies with a descriptive error message. Hopefully, this will separate the bots’ comments from those left by thoughtful human visitors who have taken the time to read your post. If a human visitor does happen to submit a comment within 60 seconds of the page loading, he or she can click his or her browser’s back button and try resubmitting the comment again in a few seconds.

One drawback is that this method does involve editing a core file – wp-comments-post.php. You’ll have to re-edit it each time you upgrade WordPress, which is a nuisance, I know. The good thing is that if you forget to do this, people can still comment – you just won’t have the anti-spam protection.

Note that the instructions in the following steps are based on the code in WordPress version 2.3 and the Kubrick theme included with that release. You may need to adjust for your version of WordPress.

Step 1 – Add the hidden timestamp input field to the comment form

Open the comments.php file in your current theme’s folder and find the following lines:

<p><textarea name="comment" id="comment" cols="100%" rows="10" tabindex="4"></textarea></p>

<p><input name="submit" type="submit" id="submit" tabindex="5" value="Submit Comment" />

Add the following line between them:

<p><input type="hidden" name="timestamp" id="timestamp" value="<?php echo time(); ?>" size="22" /></p>

Step 2 – Modify the wp-comments-post.php file to create the second timestamp and perform the comparison

Open wp-comments-post.php and find the lines:

$comment_author       = trim(strip_tags($_POST['author']));
$comment_author_email = trim($_POST['email']);
$comment_author_url   = trim($_POST['url']);
$comment_content      = trim($_POST['comment']);

Immediately after them, add the following lines:

$comment_timestamp    = trim($_POST['timestamp']);
$submitted_timestamp  = time();

if ( $comment_timestamp == '' )
	wp_die( __('Hello, spam bot!') );
	
if ( $submitted_timestamp - $comment_timestamp < 60 )
	wp_die( __('Error: you must wait at least 1 minute before posting a comment.') );

That’s it; you’re done.

Credits

Thanks to Jonathan Bailey for suggesting the handshake in his post at http://www.plagiarismtoday.com/2007/07/24/wordpress-and-comment-spam/.

10 thoughts on “Using timestamps to reduce WordPress comment spam

  1. Jonathan Bailey

    I answered your comment on my site about this but also wanted to post here and say that I really like this idea. It makes a lot of sense and would be almost impossible for a spam bot to duplicate. This is a great idea.

    I’d love to hear more about how this is working out for you as you use it. I’m going to look at it for my own site.

  2. Pingback: One Fab Fit Mom - Weight Loss Success! | How to stop spam in wordpress blogs

  3. Pingback: 12 ways to utterly crush spambots on your blog

  4. lattyb

    i think this is awesome. i’ve just installed it and in 15minutes, have noticed a massive decrease in spam.

    thank you kindly.

  5. Pingback: Twelve Mile Circle » Blog Archive » Blessed Relief - maps, geography, travel

  6. Regilda

    Vivato peplos!
    The codas sites en vero interesto! Perfecto guide! Idealte buke into me programmato.
    Cuesta code PHP:
    $submitted_timestamp – $comment_timestamp < 60
    Recoomendo more – uppetto 300
    Steppo-bu-steppo commentare – graciate Autore!
    Regarte graciate!

  7. spam botter

    Well that’s great .. now I’ll just set my spam bot to wait longer than 60 seconds if it gets an error with posting under 60 seconds…

  8. Dave Child

    I wrote something similar for my bblog installation and now I’m moving to WP I’m looking to do the same – so thanks for your work. There is one problem, easily corrected, with this approach.

    Spam bots that save the form and just keep re-sending the same form data will always appear to have been viewing the page for some time (they’ll have saved the hidden form field with an old time stamp).

    The way to fix this is to add a config variable – a very large (6 digit minimum) number that is added to the hidden field timestamp and then subtracted before the comparison is made.

    You also need to add a check to ensure the hidden timestamp isnt in the future. You can add a further check to ensure the page wasn’t loaded more than, say, 24 hours before the comment was posted.

    Then, change that variable periodically, by a large degree (at least 86400). Any “saved data” bots (which I found the majority giving me grief were) won’t be able to keep up.

  9. Steve

    Another way is to pass the timestamp in the form and as a session var, then check when the form is processed to see if they are equal.

Comments are closed.