Avoid HTML form spam using CSS

An approach of avoiding HTML form spam is using CSS. Non-human spammers usually fills out every input field in a form and submit it, and to overcome this kind of spam you must be able to differ between real human form submits and non-human spam. A technique to distinguish between non-spam and spam is using CSS; the basic idea is to make an extra dummy input text field in your form, and using CSS to make it invisible to the real human users. Thereby, if a post is sent to your php script handling the request and this extra text field contains information, you know that the submit must be spam, and the script can ignore the post.

Here is a small example form:

The human text field is used for detecting spam, you might call it something else than “human”, however this should be hidden by using CSS such that it is not visible for the user on the webpage. This can be achieved add the following to your CSS file:

#human {
visibility:hidden;
display:none;
}

The solution is as you see very to implement and proves to be effective.

Additional notes:

Using JavaScript to hide the dummy input text field is also an option. E.g. using a JavaScript Framework like Prototype.js it can be done with one line of code:

$('human').hide();

More information on hiding elements using prototype.js.

This entry was posted in Web Development and tagged , , . Bookmark the permalink.

50 Responses to Avoid HTML form spam using CSS

  1. Never thought of that (I wish I did though :))
    Nice one!

  2. Jason says:

    Love this idea. One question though. I’m no php guru, so what does the php side of this look like?

  3. Viktor says:

    Hi,

    nice idea but what about screenreaders?
    An empty inputbox without label would be disturbing for users.

  4. Will Ayers says:

    Very interesting idea.

    @jason

    The php part of this idea would simply consist of a function that would check to see if the $_POST[‘human’] contained any text (data) if so it ends it right there and does not add the comment to a data base (or what ever method you use to store the information). Hope that helps.

  5. I’ve heard that some spambots are that smart, that they start to read css and do not input anything into inputs that are hidden via css.

    Another solution for that is hidding them with javascript. It’s pretty easy, no captcha for users, and no spam :)

  6. @Marcin Krupinski

    You are absolutely right, using JavaScript to hide the dummy input text field might be a better option. E.g. using a JavaScript Framework like Prototype.js it can be done with one line of code:

    $(‘human’).hide();
  7. Hiding the element via JavaScript will still be detectable by clever spambots.

  8. Pingback: LautundKlar Webdesign Blog » Formular Spam mit CSS verhindern

  9. Pingback: coder in action : Spamming verhindern

  10. Dave Wood says:

    That is a very clever solution, but I agree with viktor. You could circumvent this problem by adding a description of the input.

    Thanks for the tip.

  11. pkchukiss says:

    On my own contact form (http://pkchukiss.sgblogging.com/contact.php), I added a text field prompting visitors who want to send me email to solve a simple maths sum.

    Till now, I have not have a problem with spam emails. If the spam bots do get too clever, I could always stick the maths problem in an image.

    If you are paranoid, you could combine the two methods together.

  12. Chris says:

    Beautiful in its simplicity!

  13. Floroskop says:

    Hello!
    I think this try.

  14. Escape says:

    clever idea!! thanks heap! it’s so simple yet effective.

  15. normalperson says:

    It’s such a nifty simple solution if you need something for spam on a basic or restricted server. Works cool. Added the stylesheet bit. In my php form to email wrote code like this after checking

    // This line prevents values being entered in a URL

    if ($_SERVER[‘REQUEST_METHOD’] != “POST”){exit;}

    // This line prevents a blank form being sent

    while(list($key,$value) = each($_POST)){if(!(empty($value))){$set=1;}$message = $message . “$key: $value\n\n”;} if($set!==1){header(“location: $_SERVER[HTTP_REFERER]”);exit;}

    // check if man or machine
    if ($_POST[‘human’] “”){
    echo “Bad doggy. Sit bobo. Sit.”;
    exit;}

  16. normalperson says:

    Additional idea for if they catch on to the human hidden field etc.

    Create say 4 human fields

    Add the CSS code to your style sheet
    #human {
    visibility:hidden;
    display:none;
    }

    Then in your form to email script decide which one you would check for needing to contain no values.

    // check if man or machine
    if ($_POST[‘human3’] “”){ //you choose human1 – 4
    echo “Bad doggy. Sit bobo. Sit.”;
    exit;}

    Could even add a randomizer for the four fields to make it even more random.

  17. David Brix says:

    Some Folks, such as myself, might find that the php script given by “normalperson” might not work.

    When I implemented it I first tried the complete snippet that he gave and immediately got an syntax error generated by the server.

    Ultimately, I added only the Post check for the “human ” field, but still had a syntax error generated. I ran it by an associate of mine, David Lincer, and he discovered that there was code missing. In the ($_POST[‘human’] “”) argument it was missing “==”.

    THE ORIGINAL CODE SNIPPET:

    // check if man or machine
    if ($_POST[‘human’] “”){
    echo “Bad doggy. Sit bobo. Sit.”;
    exit;}

    THE CORRECTED CODE:

    // check if man or machine
    if ($_POST[‘human’] == “”){
    echo “Bad doggy. Sit bobo. Sit.”;
    exit;}

    In addition, I changed the relevent action to redirect to my thank you page so that any bot would think that it was successful and not bother to try another attack tactic. My final code looks something like this…

    // check if man or machine
    if ($_POST[‘human’] == “”){
    header( “Location: $thankyouurl” );
    exit;
    }
  18. Pingback: PHP-Shops.de: Erfolgreich Online-Shops führen

  19. midhun says:

    Do you think this is a better approach than image reading to avoid spamming ??

  20. Gino says:

    This is a good idea. Some people are doing spam works. If the robots are spamming we can easily block them by using this idea but we couldn’t do anything. I am in search for block this kind of spams.I think if we can check the email id is valid or not we can identify. Can anyone give some ideas about how we can check the email is valid or not.

  21. Alaina says:

    My company is using html forms and lately we’ve been getting a lot of spam coming in through them. They don’t seem to want to do anything about it to fix it so I’m attempting to find a solution myself. So this may be a silly question (I understand the basics of html/css, but asp/php is rather confusing to me), but can this method be applied to forms that are being sent with asp?

  22. Alaina says:

    is there anyway you can remove that last post?

  23. James says:

    Another thought on this is instead of hiding it altogether is placing it at an absolute value that is -top -left. This makes it invisible to humans, but spam bots still see it and will fill it in. Also has the added advantage of not producing scroll bars, and not getting the smart spam bots to skip it because it is simply hidden ie:

    #human {
    top: -100px;
    left: -100px;
    }

  24. James says:

    Wish I could edit my comments -.-
    #human{
    position:absolute;
    top:-100px;
    left:-100px;
    }

  25. SEO Services says:

    Nice idea, I’ll have to test that out and see how well it works.

  26. defreegames says:

    thanks for sharing…

  27. Chris Done says:

    Hi Viktor,

    I don’t think screen readers read the DOM tree, at all. They read the screen, literally. For example, Opera. If you hide an element with CSS, the screen reader doesn’t see it. Why should it, really?

    I suspect this method is perfectly fine for screen readers, but I haven’t tested it.

  28. Web development says:

    See this link you can see further info on how to avoid spam without a CAPTCHA http://www.webdigi.co.uk/blog/2009/does-your-website-really-need-a-captcha/

  29. YHVH says:

    Django does this standardly with it’s auto creation of forms. Seems to work on the sites I run.

  30. Alexwebmaster says:

    Hello webmaster
    I would like to share with you a link to your site
    write me here preonrelt@mail.ru

  31. Frode says:

    Might be even better if you set a default value of the human field, and if that value changes its managed as spam?

  32. BotBoy says:

    Frode why would the bot bother changing the default setting?

  33. Trinity says:

    You could also hide the dummy input text field behind another div that has a higher z-index value and is sized and filled so as to obscure the dummy field from view. That way, the css of the dummy input text field could remain identical to the css of the other text fields.

    I think it would be difficult very difficult for a bot to detect that another div that is positioned in front of the dummy input field.

  34. Stephanie Boucher says:

    I’ve tried the hidden field option to distinguish human from non human, but the php form always returns an error. I’ve tried normalperson’s idea with and without Dave Brix’s modification, and no joy. Any suggestions? Stephanie

  35. chantz says:

    David Brix, thanks for the PHP snippet. I’ll try it, but where in the code do you add it? Does it matter where you put it (e.g. does it have to be before fclose or something) or can you just stick it in the end? If it helps, I’m using GoDaddy’s webformmailer.php. Thx!

  36. Kenny says:

    Thanks for this! Such a simple solution.

  37. dave says:

    Where do you place the php script

    // check if man or machine
    if ($_POST[‘human’] == “”){
    echo “Bad doggy. Sit bobo. Sit.”;
    exit;}

    in the form? Do you place it right after the “from action”?

  38. Pingback: pligg.com

  39. dr john says:

    dave,

    you place the code snippet in the php script that is the action for the form, near the very top, so it is tested before the rest of your action script runs and processes the data, and exits at that point.

    Many scripts use a foreach($_POST as $value) loop to check for blank fields in the data sent, or for characters likely to be used by a hacker (; — { and similar, see SQL Injection examples), so you’d have to have a little bit of code that tested each $value and if it was your hidden field, skip the check.

  40. Pingback: Absurdist.Org » Blog Archive » Tutorial: Hassle-free anti-spam using CSS

  41. Ashish Kumar says:

    Informative article, thanks for sharing such a great source
    for me!!!!!!!!

  42. Pingback: » Avoid HTML form spam using CSS My Logbook

  43. aSeptik says:

    nice, but what if javascript is disabled? ;)

  44. Jordan says:

    This trick worked for years for me, recently more and more have been getting through. Within the past month. Think there’s a spambot update spreading the net?

  45. Michael says:

    I’m a bit confused (though I know virtually nothing about PHP). I can’t seem to get the PHP side of this to work. It doesn’t seem right to me that the subroutine exits if nothing is found (== “”). Shouldn’t it exit if something *is* found (!= “”) in the “human” field? Either way, I can’t seem to get it to work, and any help would be appreciated in clearing this up for me. Thanks!

  46. paddy says:

    Very Interesting

  47. Tim B. says:

    Additionally to this method, you could use Javascript for form validation, making the hidden field required with class=”required”. Then remove class=”required” with Javascript when the page loads.

  48. John says:

    Excellent, you made my day!

Leave a Reply