Making forms spam-proof without CAPTCHAs

CAPTCHAs are a thing of the past. When I want to submit my information or subscribe to a newsletter, I shouldn’t be put out just because the website has a spam problem. They’re a usability nightmare, horrible on mobile devices and let’s be honest, they never really fit the design of your website. I’ll share the little trick I use to replace these awful things.

Bots are dumb

If you google for CAPTCHA alternatives, you should come across references to a “honey pot” solution. The name is nice and makes a lot of sense when you understand how it works.

The main idea is that you look for how bots are different from humans without making the humans prove that they are, in fact, human.

Bots try to brute-force your form. Human users, however, will carefully read each and every label and fill in fields accordingly.

It may not seem like much, but this is the key difference. So, what if we somehow make sure that the user can’t see or read a field? They won’t be able to fill it in whereas bots are going to loop through all the form fields and complete whatever they come across to avoid triggering any completion requirement errors. The bot can’t resist filling in the fields just like a bear can’t resist the honey pot.

Hands on

Let’s have a look at a short code example to see what this little trick looks like.

The markup

The beauty about this technique is that it doesn’t require any extra scripts or hacks. You simply add a field for something that isn’t too crazy like ‘name’ or ‘zip code’ and hide it. If you use a field that’s already in the form, the bots may get through by treating it as a duplicate and leaving it blank.

<form action="subscribe.php" method="POST">
	<label for="name" class="hidden">Name</label>
	<input type="text" id="name" name="name" class="hidden" />

	<label for="email">E-mail address</label>
	<input type="email" id="email" name="email" />

	<button type="submit">Subscribe</button>
</form> 
 

The CSS

The only thing that’s left is adding a style rule for the ‘hidden’ class.

Note that it’s important to also add visibility: hidden; to the class to account for screen readers that ignore display: none;


.hidden{
	display: none;
	visibility: hidden;
}

Intelligence

The only thing left is checking whether the honey pot has been touched or not. I prefer doing this server side because I like to keep my client side scripts as light and small as possible.

In PHP this would look something like:


if(empty($_POST['name'])){
	//save the email address to the database
}

But if you already have some sort of validation in place in your javascript, you might as well just add this little check.

That’s it

That’s all there is to it. It’s so simple, you can implement this little trick faster than you can incorporate CAPTCHA into your page. I’ve been using it for a couple of years now on small contact forms and subscribe forms with great success.