Learn

Honeypot fields: how they work and where they fail

A honeypot is a form field that people never see and simple bots fill in anyway. If it comes back with something in it, a bot sent the form. It is free, private and invisible, and it stops only the bots that are not trying.

Last updated

How it works

Many form bots do not render the page. They read the HTML, find the form, and put a value in every input so that no required field is left empty. A honeypot exploits that habit: one extra input, hidden from people, that only a program would think to fill.

Your server checks it before anything else. Empty means the form probably came from a person. Filled means it certainly came from a program.

Building one that people never trip

The hard part is not catching bots. It is making sure no real person ever fills the field, because each one who does is a lost message you never hear about. Four details matter:

  • Move it off screen rather than using type="hidden" or display: none. Bots that skip hidden inputs skip those too.
  • Take it out of the way of assistive technology: aria-hidden="true" on its wrapper so screen readers do not announce it, and tabindex="-1" so a keyboard user never tabs into it.
  • Give it a name that autofill has no value for. Browsers and password managers fill fields that look like a name, an email or an address, and a person whose browser filled your honeypot looks exactly like a bot. Add autocomplete="off", and try the form with the password managers your visitors use.
  • Fail quietly. Answer a filled honeypot the way you answer a real message, and throw it away. A bot told it failed can be adjusted.
HTML
<style>
.hp { position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden; }
</style>
<form action="/contact" method="POST">
<label for="email">Email</label>
<input id="email" name="email" type="email" required />
<label for="message">Message</label>
<textarea id="message" name="message" required></textarea>
<!-- The honeypot: people never see it, bots fill it in -->
<div class="hp" aria-hidden="true">
<label for="website">Website</label>
<input id="website" name="website" type="text" tabindex="-1" autocomplete="off" />
</div>
<button type="submit">Send</button>
</form>
JavaScript
server.post("/contact", async (req, res) => {
// Anything in the honeypot means a bot filled it in. Answer as if it
// worked, so the bot learns nothing, and keep nothing.
if (req.body.website) {
return res.redirect(303, "/thanks");
}
// ...handle the real message
});

A second trap: time

A person takes at least a few seconds to fill in a form. Many bots take none. Recording when the page was served and refusing a submission that comes back too fast catches another slice of simple bots.

Two cautions. Sign the timestamp on the server, or the bot simply sends an older one. And keep the minimum short, because autofill and a short message can make a real person fast too.

Where honeypots fail

A honeypot only works on a bot that falls for it. These do not:

  • Bots that drive a real browser. A headless browser renders the page, can tell which inputs are visible, and fills only those.
  • Bots written for your form. Anyone who looks at the page source once can see the field and leave it out.
  • People. Spam typed by people never touches a field the sender cannot see; see why spam gets past your CAPTCHA.

It can also fail the other way, which is worse because nobody notices: an autofill tool or a browser extension fills the field, and a real enquiry is discarded as a bot. Watch how many submissions the honeypot catches. A sudden change in either direction is worth a look.

Honeypot or CAPTCHA?

Both, usually, in that order. The honeypot costs nothing and removes the laziest bots before anything else runs. A challenge handles the bots the honeypot cannot see.

A classic CAPTCHA does that by asking the visitor to solve a puzzle, which brings back the friction a honeypot avoids. Challenge keeps it invisible: when the visitor presses Send, their browser runs a small proof-of-work check and the solution travels with the form. There is no field for a bot to discover and leave out. A bot that skips the check is refused, and one that runs it pays CPU time on every submission. It does not stop headless browsers outright; the proof-of-work explainer explains why.

For what a person typed, the layer is a content classifier such as Classify. The full stack, from honeypot to review queue, is in the guide to stopping contact form spam, and both products start free on one plan; see pricing.

Where Botpoison fits. Stop the bots, then read the rest

Challenge

An invisible check for bots, before the form is sent.

Classify

A verdict on every message: spam or clean, with a score.

Get started with Challenge

Add the layer a honeypot cannot be: a check every submission pays for, whatever the bot reads.

Free to start

One plan, an allowance for each product. No credit card needed.

Keep reading

How to stop contact form spam

Honeypots, rate limits, a challenge, a content classifier and a review queue: which spam each layer stops, and which it lets through.

Last updated

Why spam gets past your CAPTCHA

Much of the spam that still arrives was typed by a person. A test for humans cannot stop it, and reading the message can.

Last updated

What is a proof-of-work CAPTCHA?

The browser does a small computation instead of the visitor solving a puzzle. How it works, what it costs, and what it does not stop.

Last updated

What is an invisible CAPTCHA?

Risk scores, browser challenges and proof of work all call themselves invisible. What each one does, and what invisible means for accessibility.

Last updated

reCAPTCHA and the GDPR: what EU regulators decided

The French CNIL and an Austrian court both found that reCAPTCHA needed consent. What they decided, and the questions it leaves for a form.

Last updated

Botpoison stops spam, not leads

Stop spam now
No credit card required
Invisible
Accessible
Two products, one plan