Blog (my web musings)

Find out what's interesting me, get tips, advice, and code gems that don't fit elsewhere.


Search Blog


A few years ago, I set up a web page that contained several different forms. I don't really know much about how spambots work (does anyone?) but, after a few weeks, it started taking hits - the usual junk about mail order brides and marketing advice, etc. The strange thing was that the spam only ever came in on the very first form - that is, via the form that appeared uppermost in the HTML - and it happened with too much predictability and regularity for it to just be coincidence.

This led me to wonder about how spambots actually "think"? Do they attack a form and, once they've done their damage, say "Ha, I have done my evil deed. Now I must run away quickly before I am caught, and find another form to defile!". Hmmm, maybe they do, in whatever programming language they use (although, most likely, they don't). Well, this got me thinking; if their behaviour is so predictable, can I use it against them as a simple anti-spam measure?

So I devised a little test.

Create a decoy form

On the attacked page, I inserted a decoy contact form at the very top of my HTML and commented it out with the standard HTML commenting tags. Anybody viewing the page normally via a browser would not see this form, but a code-crawling spambot would (the code at least) and hopefully be tempted into the trap;

<!--
<form action="form-trick-action.php" method="post" name="t_form">
Full Name: <input type="text" name="t_name"><br/>
Email Address: <input type="email" name="t_email"><br/>
Message: <textarea name="t_message"></textarea><br/>
<input type="submit" value="Send Message">  
</form>
-->

Now, the form action attribute of this decoy form pointed to a "form-trick-action.php" script that just fired off a spam-alert email to me so I could see when the bots attacked. And boy did it work! 25-100 spam emails per day sent off into the ether to a temporary email account. I recreated this test again recently so I could show you a sample screen cap of the inbox;

Include a "trap" field in your real form

Next came the real form towards the bottom of the HTML. For this I used an almost identical version of the decoy form above, except with a real form action, and slightly different field names. It also had one extra critical feature - an extra input field named "website". I chose a plausibly legitimate name ("website") to trick the spambots - the logic being that if I had used something more obvious, like "antispam", the little blighters might have avoided it;

<form action="form-real-action.php" method="post" name="form">
Full Name: <input type="text" name="name"><br/>
Email Address: <input type="email" name="email"><br/>
<input type="text" name="website" id="website">
Message: <textarea name="message"></textarea><br/>
<input type="submit" value="Send Message">  
</form>

You might be wondering why I wanted the bots to target this extra field. The answer lies in the next chunk of code that I added to the "form-real-action.php" script;

Ignore bots, process humans

<?php
if(empty($_POST['website'])) { // if the "website" field is empty, send email ...
    $to = "This email address is being protected from spambots. You need JavaScript enabled to view it.";
    $subject = "Contact Message Received";
    $message = "Message from: $_POST['name'],\n\n
            On email address: $_POST['email'],\n\n
            Message:\n\n
            $_POST['message']";
    $headers = "From: This email address is being protected from spambots. You need JavaScript enabled to view it.";
    $sent = mail($to, $subject, $message, $headers);
    header("Location: http://www.mywebsite.com/thanks.php"); // redirect to "Thank You" page ...
    exit();
    } else { // if the "website" field contains any input, do nothing (no email sent) ...
    exit();
    }
?>

Please note, this code is not a complete script. It is just a sample, stripped down to the basics so you can see the working method.

Put simply, if the "website" field remained empty, then the script would send me an email - the true contact message from a real person. If however the "website" field was not empty, and contained input when the form was submitted, the script stopped dead.

Hide the "trap" field from humans

Of course at the moment there is a blinding flaw in this logic - the "website" field would be clearly visible on the web page (although not labelled), and accessible by the general public, so I employed a bit of CSS to hide it from humans. You might already have noticed that I gave the "website" field an id of "website" too, so it could easily be hidden with the following CSS;

#website { display:none; }

Once the "website" field was hidden with the CSS, humans couldn't accidentally type anything into it and the script would allow the email to be sent to me.

In conclusion

My theory appears to be correct. Spambots really do focus on spamming the first form they find, before scarpering as quickly as possible, so if the first form they come to happens to be a decoy, their efforts are fruitless. This approach has almost seen an end to my spam problems. Once the initial tests had been done, I turned off the spam-alert emails that the decoy form was generating and that left the real email account free to receive real contact form messages from real visitors.

Use this knowledge to protect against form spam

  • Include a simple decoy form at the top of the HTML / web page and comment it out with standard HTML comment tags - the spambots will see it, try to attack it, and then move on.
  • Include a "trap" field on your real form that the processing PHP script will check for input - input = bot (exit) / empty = human (process).
  • Hide the "trap" field with CSS so that a visitor can't type anything into it accidentally.

Of course I'm not saying that this should be the only method of anti-spam protection that you use - you should try to factor in a combination of more robust procedures to stop those vicious little fiends dead in their tracks, such as JavaScript form encryption, CAPTCHA and filtering - but one more arrow in your quiver is sure to help.