Easy Spam Prevention Using Hidden Form Fields

Maybe I’m old-fashioned or a purist, but there’s one aspect of usability that’s severely lacking on many websites. I’m referring to the insanity surrounding spam prevention.

As noted in a personal blog entry back in November 2011, I was having some issues with spam and came up with a solution that I’ve come to learn isn’t really new, but that few people seem to use or know about. It’s an extremely simple yet effective method of preventing spam on your website forms that I’d like to share with you here.

The Problem

Obviously as your website grows in popularity, the spam invariably increases. There are several well-known methods of spam prevention including:

  • Banning IP addresses
  • Forcing users to register and verify their email before posting
  • CAPTCHA images or similar Turing tests
  • Third-party solutions which use ever-growing databases of known spammers to compare against
  • Manually moderating or approving posts

The problem with the majority of these methods is that the users suffer. Banning IP addresses rarely works because those can be spoofed or reassigned and you might actually end up blocking a legitimate user; spammers tend to use dynamic IPs anyway.

Forcing users to register or read a difficult CAPTCHA image shifts the burden from the website owner onto the user, causing them to have to jump through more hoops to contribute. CAPTCHA images are a horrible solution anyway in that they don’t cater well to those with disabilities and they’re also increasingly vulnerable to OCR (Optical Character Recognition) programs.

I don’t want to rely on some third-party solution because the fewer dependencies I have in my project the better I’m going to feel about it. If that leaves me manually sorting through spam for hours on end then so be it, so long as the burden is mine. Some people will argue that the added complexity is a necessary evil, but I just can’t seem to bring myself to agree.

The Solution

So there I was deleting spam after spam trying to think of a non-intrusive solution when I started noticing a pattern … a spambot cannot distinguish the difference between whether or not fields are optional or required, so it just fills them all out. If you think about it, every website is different when it comes to marking required fields; some do it with asterisks, some with red text, some with the still poorly supported HTML5 attribute “required”, and others don’t bother to mark them at all, but rather redirect you back if you happen to miss one. It only makes sense that a bot would get tripped up on such a thing and simply not even try.

Eureka! There it was, a Turing test that was built in to my application all along! Now how to make the most of it.

Not only do spambots struggle with recognizing required fields, but they also struggle with reading CSS or JavaScript, at least for now. The simplest solution, then, is to add a completely arbitrary field to each form and then to hide it using any number of such methods, for example:

<input type="text" name="foo" style="display: none;">

Alternatively, you could opt for something a little more complex like giving the field an ID or a class which would then force the bot to scan through your CSS files to determine the element’s visibility.

You could also use Javascript to remove the arbitrary field from display as the page loads, for example:

<div id="fooDiv">
<label for="foo">Leave this field blank</label>
<input type="text" name="foo" id="foo">
</div>
<script>
(function () {
    var e = document.getElementById("fooDiv");
    e.parentNode.removeChild(e);
})();
</script>

Notice how the field in the example has been given a label instructing the user to leave the field blank on the off chance they have JavaScript disabled.

Now you can rest assured that if the field ever has a value when the form submission reaches your server then the transaction can be discarded as junk. No matter which method you use the bot now has the added task of figuring out whether or not a given field is visible and/or required, which you could argue would take some pretty advanced AI or a more targeted approach on behalf of the spammer.

It might also help to randomize where the arbitrary field is displayed and how it is named so that it is even less predictable.

Of course, no solution is completely foolproof, as spam is sometimes still manually submitted by humans, so it never hurts to have more than one prevention procedure in place. To add another layer of protection, when spam is detected you should still go ahead and redirect the bot as though it were a successful form submission; I don’t like to give them any reason to probe.

I love good, old-fashioned, out of the box solutions, especially when they are elegant and work. I hope you find this trick as equally useful as I have, and I hope you’re willing to share any improvements or some other solutions you might happen to come up with.

Comments on this article are closed. Have a question about HTML? Why not ask it on our forums?

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • Skippy

    We tried this a few years ago with a competition entry mechanic that we did for one of our clients, and it worked a treat, drastically cutting down spam entries.

    Unfortunately the brand was nervous that there was no physical user evidence of spam prevention, so they asked us to revert back to ugly looking captcha forms.

    • http://www.spiraleye.com Timothy

      Don’t you love clients?
      “You’ve found a elegant way to prevent robots sending me spam but how are people going to know that they are human??” :D

  • http://kyno.co.uk Matt Clarke

    Great article.
    I love simple things like this, good thinking!

  • http://www.lifeisaprayer.com/ Jeff Geerling

    The name for this kind of spam prevention is a “honey pot”, since, like a bear being unable to resist a jar of honey, spam bots can’t resist filling out an entire form. There’s a module that does this automatically in Drupal (http://drupal.org/project/honeypot), and I’m guessing there are similar modules for other CMSes.

    It’s a much more user-friendly way of preventing spam on your site. Only when spammers directly target a site (and work around a honey pot) do I recommend people look into other solutions (like Mollom, Akismet, or sometimes a CAPTCHA).

  • Line Yoble

    I use such a technique for years.
    I had never shared about it because I’m convinced that once well known, bots will adapt and find a way to bypass the technique.
    Now, I must find something else… :-(
    Thanks Martin.

  • Chris Emerson

    If the spammers can get round more and more complex CAPTCHAs as time goes on, then something like this is going to present no barrier at all when they catch on and start coding for it. This is a very weak barrier that just happens not to have been coded around by the spam bot builders… yet!

  • Les

    There is a third alternative that does not rely upon the client in any way, shape or form, and come to think of it, it’s a better solution all round, and that is to implant a hidden field in any form with a token that is generated and maintained on the server.

    Myself personally, I use a queue based array held in the session, an array that holds randomly generated tokens of the last five requests, you need to hold on average this amount due to redirects, etc.

    But whatever floats your boat I suppose :)

  • Joachim

    Another good one is to set a cookie on the user and if that cookie isnt set upon posting there is a good chance that it’s a bot… However to use all these methods at the same time is a more robust way :)

  • Marty

    Thanks for the ideas. Never really thought of it like this. I’ll be adding this to a form to test it out.

  • Ian

    Indeed, the technique you’ve mentioned is called the ‘honeypot’. Conceptually named due to a bot getting caught with their hand in it.

    I like to use this along with an active session test. Essentially, I test to see if a user has come to the page before submitting the form. Most bots will post (submit) the form directly without hitting the page first to fill it out like a human would.

    So, when a human comes to the page first, the page generates a unique ID. It stores that ID in the session and populates a hidden (ie input type=hidden) field with that ID. If there is no session or no ID or the ID is stale (not previously used), the submission fails.

    The biggest issue with this method is if the user fails to submit the form before the session dies (eg, walks away from the computer). A simple hidden refreshing iframe would resolve that problem however.

    Slightly more complex, but also very effective.

    Cheers

  • Jonathan Weighell

    Yeah, I’ve done this on my contact form for the past few years – and it works perfectly!

  • Patrick

    AKA – Reverse Captcha

  • Patrick

    And for the comment below: Honepot is something totally different.

  • ralph.m

    One thing to consider is what people will see with CSS off, or who are using a screen reader and may thus come across the hidden form field. Merely telling them to do nothing might be a bit confusing. There was an interesting discussion about this in the forums last week, which suggested that perhaps a better solution is a simple time check, whereby the submission is aborted if the form is submitted to soon after page load:

    http://www.sitepoint.com/forums/showthread.php?861648-Captcha-To-Use-Or-Not-To-Use&p=5144556&viewfull=1#post5144556

  • http://www.sensibleweb.co.uk Phil Johns

    I have used the form at http://www.dagondesign.com/articles/secure-php-form-mailer-script/ for years and although the captcha is simple and plain to read I do not get any problem with spam.

  • Nick

    Tried this on a site once, but it caused a problem with browsers that were autofilling in form data. Possibly naming it “foo” would avoid this however.

  • http://ChiefAlchemist.com Mark Simchock

    Nice idea Martin. But help me out, why use Javascript to hide the fooDiv? Why not just use CSS, it can’t be disabled?

    I’d like to suggest (of the top of my head) that there’s probably a good solution using a hidden field and giving that field a value via Javascript / jQuery on page load or on submit. There’s gotta be a way to trick a stupid bot to show its stupidity.

    • http://www.psinas.com Martin Psinas

      Mark, you could use Javascript or CSS, or a combination of both (which can both be disabled). The strength of this spam prevention method has less to do with hiding the form field, and more so to do with the fact that the bot doesn’t know the field isn’t required.

      When I submitted this article I didn’t have “Using Hidden Form Fields” in the title and I wish it wasn’t published that way because it focuses on the wrong point.

  • Dite

    Been doing this for years and still do. I always email the forms which have the field completed to a monitor just in case. From 10’s of thousands of submissions I have picked up about 20 or so which actually appear to be genuine users. No idea how those users managed to fill out the honeypot field without disabling CSS and probably never will. Worth checking the blocked ones though.

  • http://nicknotfound.com Nick

    I’ve used this technique for years, and it works great. The only thing I found that caused a problem was that I had to name the field something the spam bots wanted to fill in (such as ‘subject’ instead of ‘foo’). The problem with that is IE (of course it’s IE) will still auto-fill a field even if that field is hidden using CSS. A simple autofill=”off” on the input element fixed it.

  • http://www.britishproductsdirectory.co.uk Syd Partridge

    Yes, this idea has been around for a while. One of the reasons it is not suggested is because screen readers ‘see’ the hidden field and the user is confused. What I like about this is; the ‘Leave this field blank’ label. This label could also be used to explain to visually impaired users why it is there.

    • http://roadha.us haliphax

      Screen readers shouldn’t read anything with display:none on it. I’ve been using this technique for years on a college web site, and it’s been working fantastically across the board.

      • Adam

        Most accessibility APIs will include form controls that carry that property and many aural ATs, including (but not limited to) W-E, Orca, and NVDA, will announce those controls or have done so in prior versions (which are sure to be still in use). That is one of a number of important distinctions in the behaviour of the form mode (and equivalents) versus the normal browsing mode.

  • Juil

    I’ve heard of this before, but thanks for the article.
    I’m curious about when you mentioned redirecting the bot as though it were a successful submission. How exactly do you do this?

    • http://www.psinas.com Martin Psinas

      Hey Juil, I simply mean that you should redirect the bot to your “thank you” page, just as you would for anyone else submitting a comment to let them know that the submission was successful.

  • Van Luu

    Simple and effective. Thank you for this :)

  • http://harrytran.com Harry tran

    I used to only use this method to prevent spam. It works for a couple of weeks, but once the website picks up on hits, the bots figure it out quickly.

  • http://www.dominiopi.com alex

    Sounds easy. but how do you check whether the foo field is filled, so you can act upon that condition. I’m trying –if (is_null($_POST['foo']))– in PHP but does not seem to work. Sorry if this is a silly question but I’m not really a programmer and I’m just trying to modify a webform code found on the web.

    • http://www.psinas.com Martin Psinas
      if(isset($_POST['foo']) && trim($_POST['foo']) != '') {
          // junk
      }
  • http://timgallantcreative.com Tim

    I used to use honeypots, but after a year or so, it seemed the method became ineffectual against spam. Too bad; it’s my preferred method.

  • http://www.sagie.es cesar

    In my experience, using ajax for submitting the forms prevents spam.

    If I can´t use ajax, then I use 2 email fields, the first called “email”, and hidden with css. If the hidden field is not set with its default value, then u know it´s a spammer.

  • http://cssbased.com cssbased

    I use a required checkbox such as “I have read and accept the Terms and Conditions.” or “I am not spamming”. Bots can not check a checkbox and it can not pass validation on serverside.