How to create a simple Honeypot to protect your Forms against Spammers

← ← ←   5/2/2022, 2:17:45 AM | Posted by: Felippe Regazio


I think this post will be short and useful. The goal here is to demonstrate a simple technique to help you block spammers and bots that could attack your website forms. This meant to be an extra layer in spam prevention, not the main resource to. Use it with another tools like reCaptcha, etc. Due its simplicity, i really recommend you to follow this form pattern, so, lets code:

Imagine you have the following form structure:

  
  <form id="myformid" action="/myformaction">
    <label for="name">Your Name</label>
    <input type="text" id="name" name="name" placeholder="Your name here" required maxlength="100">
    <label for="email">Your E-mail</label>
    <input type="email" id="email" name="email" placeholder="Your e-mail here" required>
  </form>
  

Most of simple bots will search form common patterns, like label common names, input id's, input common attributes, required fields, etc, and than the bot will fill 'em with fake info to try send you, and your customers, spams or some malicious codes. The most common fields to search are fields named like "email, phone, address"...

So, lets cheat on that and create a simple honeypot by changing our form structure to:

  
  <style>
      .ohnohoney{
          opacity: 0;
          position: absolute;
          top: 0;
          left: 0;
          height: 0;
          width: 0;
          z-index: -1;
      }
  </style>

  <form id="myformid" action="/myformaction">
      <!-- Real fields -->
      <label for="nameaksljf">Your Name</label>
      <input type="text" id="nameksljf" name="nameksljf" placeholder="Your name here" required maxlength="100">
      <label for="emaillkjkl">Your E-mail</label>
      <input type="text" id="emaillkjkl" name="emaillkjkl" placeholder="Your e-mail here" required>
      <!-- H o n e y p o t -->
      <label class="ohnohoney" for="name"></label>
      <input class="ohnohoney" autocomplete="off" type="text" id="name" name="name" placeholder="Your name here">
      <label class="ohnohoney" for="email"></label>
      <input class="ohnohoney" autocomplete="off" type="email" id="email" name="email" placeholder="Your e-mail here">
  </form>    
  

Lets see the changes:

First we created a class to hide things. The .ohnohoney class. Important to point some things now:

Dont use display:none, some bots cant access fields with display none, other simply know that they should'nt fill the display none fields. Dont use "hidden" in the class name, some advanced bots can recognize it.

Than we created the "Real fields". This are the visible fields and the ones which must be relevant to your backend in terms of data. This fields must have the identifications changed to hashes. Commonly i use the pattern "nameHASH" all together. Dont use "name-hash" or variations of that, a simple split would expose the real field name. Now, a bot cant recognize what this fields are, they're just know that the form has some fields which must be filled, maybe following the "type" as pattern.

By creating the "h o n e y p o t" fields we will be able to identify the Spammer. Important to: Let the label empty, use your 'ohnohoney' class to hide all those fake inputs. Turn your fake input the most simple, generic and attractive as possible. Use simple and common names as "email, phone, name, etc", disable the autocomplete (so, browser will not fill it), disable rules, but keep the types.

Now we have 2 parts in our form: Real fields with our inputs protected by hashes and strange names (you can implement the hash or strange names as you prefer). And our honeypot (dont write "honeypot", prefer split the letters to avoid any recognition). Now on your backend:

Verify if any of the "h o n e y p o t" fields came filled. If yes, congrats, you trapped a spam. Most of them will fill all this fields without differentiate them. So, all you have to do is to check if any of your "h o n e y p o t" fields came filled, if yes, its a spam. If you prefer, you can do this check on the client, in case of an ajax form, this will avoid use server resources to compute unuseful data (but keep the backend validation anyway). When you catch a spam, just dont send the data and do whatever you want with it. If names as "email, phone, etc" are important to your backend, just transcript the names using arrays.

Here is a single-file repo with a simple implementation of this technique: Access the Repo

Remember: this is just a simple layer to prevent attacks in a simple way, some technologies can identify even this patterns, so use all the weapons you can against it. But i believe that this simple pattern can avoid at least 50% of spams in your webpage.