DEV Community

Alexis
Alexis

Posted on

Honeypot Fields: Bot Protection That's Free and Takes 5 Minutes

TL;DR: A honeypot is a hidden form field that bots fill out and humans don't. When the field contains data, you reject the submission. It's invisible, requires no user interaction, and blocks most automated spam.


Your contact form is getting hammered. Dozens of spam submissions per day. You could set up a CAPTCHA, but that means integrating a third-party service, managing API keys, and dealing with the UX cost: 15% of users abandon forms when faced with a CAPTCHA challenge.

Honeypots are simpler. A few lines of HTML and CSS, a server-side check, and you're done. No external dependencies, no API costs, no user friction. They won't stop every bot, but they'll stop most of them, and your legitimate users won't notice they exist.


How It Works

A honeypot exploits a fundamental difference between humans and bots:

  • Humans fill out visible fields and ignore what they can't see
  • Bots parse HTML and fill out every field they find

You add a form field that's hidden via CSS. Humans never see it. Bots fill it out. If the field has a value when the form is submitted, you reject it.

<form action="/submit" method="POST">
  <label for="email">Email</label>
  <input type="email" name="email" id="email" required />

  <!-- Honeypot: hidden from humans, visible to bots -->
  <div class="form__alt" aria-hidden="true">
    <label for="website">Website</label>
    <input type="text" name="website" id="website" tabindex="-1" autocomplete="off" />
  </div>

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

<style>
  .form__alt {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
  }
</style>
Enter fullscreen mode Exit fullscreen mode

Server-side validation:

[HttpPost("subscribe")]
public IActionResult Subscribe([FromForm] SubscribeRequest request)
{
    // Honeypot check: if filled, it's a bot
    if (!string.IsNullOrEmpty(request.Website))
    {
        logger.LogWarning("Honeypot triggered from {IP}", HttpContext.Connection.RemoteIpAddress);

        // Return 200 to avoid revealing the trap
        return Ok();
    }

    // Process legitimate submission
    await subscriptionService.AddAsync(request.Email);

    return Ok(new { success = true });
}
Enter fullscreen mode Exit fullscreen mode

Implementation Details That Matter

Field Naming

Don't name your field honeypot or trap. Bots look for obvious names and skip them.

Bad Names Good Names
honeypot website
trap company
spam fax
bot-check mobile

Use names that look like legitimate optional fields. Bots expect forms to have fields like website or company and will fill them.

Hiding Techniques

Don't use:

  • type="hidden": Bots know to skip these
  • display: none inline: Bots detect inline styles
  • visibility: hidden: Easily detected

Do use:

  • External CSS with positioning off-screen
  • aria-hidden="true" for accessibility
  • tabindex="-1" so keyboard users skip it
  • autocomplete="off" to prevent browser autofill

Response Strategy

When a honeypot catches a bot, return a success response. If you return an error, the bot operator learns their submission was detected and can adjust.

// Good: Silent rejection
if (isHoneypotFilled)
{
    return Ok(); // Bot thinks it succeeded
}

// Bad: Reveals the trap
if (isHoneypotFilled)
{
    return BadRequest("Bot detected"); // Bot operator learns to avoid this
}
Enter fullscreen mode Exit fullscreen mode

Adding Time-Based Detection

Bots submit forms instantly. Humans need time to read and type.

Add a timestamp when the page loads. Check how long the submission took. Reject anything faster than a reasonable threshold.

<input type="hidden" name="form_time" value="1703894400" />
Enter fullscreen mode Exit fullscreen mode
[HttpPost("contact")]
public IActionResult Contact([FromForm] ContactRequest request)
{
    var submissionTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
    var loadTime = request.FormTime;
    var elapsed = submissionTime - loadTime;

    // Reject if submitted in less than 3 seconds
    if (elapsed < 3)
    {
        logger.LogWarning("Form submitted too fast: {Seconds}s", elapsed);

        return Ok();
    }

    // Honeypot check
    if (!string.IsNullOrEmpty(request.Website))
    {
        return Ok();
    }

    // Process legitimate submission
    // ...
}
Enter fullscreen mode Exit fullscreen mode

The Laravel Honeypot package uses a 1-second default threshold. For complex forms, 5-10 seconds is reasonable.


When Honeypots Work

Honeypots are effective against:

Bot Type Effectiveness
Basic scrapers High: Fill every field blindly
Form-filling scripts High: Don't execute CSS
Spam services Medium: Some have learned to skip hidden fields
Headless browsers Low: Can execute CSS and detect hidden fields

Studies report 80% reduction in basic spam with honeypots alone. Combined with time-based checks, some implementations block over 99% of automated submissions.


When Honeypots Fail

Honeypots won't catch:

Sophisticated bots that execute JavaScript and respect CSS. Headless browsers like Puppeteer can detect which fields are visible.

Human spam from click farms or paid operators. If a human fills out the form, the honeypot won't trigger.

Targeted attacks where the attacker inspects your form structure. Once they identify the honeypot, they skip it.

Password manager autofill that fills hidden fields. This is a documented issue, covered in our companion post on password manager ignore attributes.


Layered Protection

Honeypots work best as one layer in a defense stack:

Layer Catches
Honeypot Basic bots that fill all fields
Time check Bots that submit instantly
Rate limiting High-volume automated attacks
Cloudflare Turnstile Sophisticated bots, headless browsers

For most contact forms and newsletter signups, honeypot + time check provides adequate protection without user friction. Add Turnstile or server-side validation (like Akismet) for high-value forms.


Framework Integrations

Most form libraries have built-in honeypot support:

Framework Package/Feature
Laravel spatie/laravel-honeypot
WordPress Contact Form 7 Honeypot plugin
React Manual implementation or remix-utils for Remix
ASP.NET Manual implementation (see examples above)

Summary

Honeypots trade sophistication for simplicity. They won't stop every bot, but they'll stop most of them, and your users won't know they're there.

Technique What It Catches
Hidden field Bots that fill all fields
Time threshold Bots that submit instantly
Deceptive naming Bots that skip obvious traps

For forms where user experience matters more than bulletproof security, honeypots are the right tool. For authentication, payments, or high-value actions, combine them with stronger measures.

Related: Why Your Honeypot Catches Humans (Not Bots), on preventing password managers from filling honeypot fields.


Honeypots are one layer of defense. For comprehensive bot protection, see Cloudflare Turnstile or Cloudflare Bot Management.

Top comments (0)