All guides
spamhtml forms

Spam protection for HTML forms: honeypots, Turnstile, and rate limiting

A practical guide to stopping form spam — honeypot fields, Cloudflare Turnstile, and rate limiting — and how to layer them without hurting conversions.

Formcrest7 min read

A contact form that has been live for more than a few days will get spam. It is nearly guaranteed. The same bots that scrape email addresses from web pages also look for form endpoints to abuse — submitting fake leads, link-building pitches, or random garbage that clogs your inbox and muddies your data.

The good news is that most form spam can be stopped with a few practical techniques that add zero friction for real visitors. This guide covers the three layers that actually work — honeypots, Cloudflare Turnstile, and rate limiting — and explains how to combine them.

Why forms attract spam

Every HTML form on the public internet is an open endpoint. Bots discover forms by crawling pages and scanning for common patterns in HTML (<form, action=, type="submit").

Common motivations:

  • SEO link injection. Submitting links in message fields in hopes they appear somewhere public.
  • Fake lead generation. Flooding an inbox with garbage submissions to waste time or money.
  • Generic noise. Poorly targeted bots that fire at anything resembling a form.

None of these require a human. They are automated processes that POST payloads programmatically. Stopping them is a matter of making the endpoint look less like an easy target.

Layer 1: the honeypot field

The honeypot is the simplest, most effective, and least disruptive spam defence for contact forms. The idea: add a hidden field to your form. Real visitors never see it and never fill it in. Bots, which parse the HTML and fill in every field they find, fill it in. When the field arrives with a value, you know the submission came from a bot.

<form action="https://api.formcrest.com/v1/submit/abc123" method="POST">
  <label>
    Email
    <input type="email" name="email" required />
  </label>

  <label>
    Message
    <textarea name="message" required></textarea>
  </label>

  <!-- Honeypot: hidden from visitors, irresistible to bots -->
  <input
    type="text"
    name="_honey"
    style="display:none"
    tabindex="-1"
    autocomplete="off"
  />

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

A few implementation details matter:

  • Hide it with CSS, not type="hidden". A type="hidden" field is expected to be invisible — some bots know to skip those. A visually hidden text input looks like a real field to a bot.
  • Set tabindex="-1". This removes the field from the keyboard tab order. Real keyboard users navigating your form never land on it.
  • Set autocomplete="off". This prevents browsers from auto-filling the honeypot field, which would cause false positives for legitimate users.
  • Use the right field name. On Formcrest, the canonical honeypot name is _honey. Formcrest also recognises _gotcha, botfield, url, and website as honeypot fields for compatibility with forms migrated from other services.

When a submission arrives with a non-empty honeypot field, the right behaviour is to silently accept it — respond with a normal success — and flag the submission as spam internally. Returning an error gives bots a signal that they were caught and an incentive to adapt. Silent acceptance does not.

The honeypot's one meaningful limitation: more sophisticated bots that specifically parse CSS to find hidden elements will not fill in the field. Against targeted, adaptive attacks, you need additional layers.

Layer 2: Cloudflare Turnstile

Turnstile is Cloudflare's privacy-friendly alternative to traditional CAPTCHA challenges. Where classic CAPTCHAs ask visitors to identify fire hydrants in photos, Turnstile runs a lightweight challenge in the background — analysing browser signals to determine whether the client looks like a human — and only shows an interactive puzzle in cases where it is not confident. Most real visitors see a small "Verifying..." widget that resolves in under a second.

Why Turnstile instead of reCAPTCHA? reCAPTCHA is widely used but sends visitor data to Google. Turnstile is designed to collect less identifying data while achieving comparable detection rates.

When to add Turnstile:

  • High-traffic pages where honeypots alone are not enough
  • Pages in directories or communities that attract sophisticated spam
  • Any form where the cost of processing a spam submission is high (for example, a form that triggers an API call, a database write, or a sales workflow)

How to add it:

First, enable the Require Turnstile setting on the form in your dashboard. Then add the widget markup and script to your form:

<form action="https://api.formcrest.com/v1/submit/abc123" method="POST">
  <label>
    Email
    <input type="email" name="email" required />
  </label>

  <label>
    Message
    <textarea name="message" required></textarea>
  </label>

  <!-- Honeypot -->
  <input type="text" name="_honey" style="display:none" tabindex="-1" autocomplete="off" />

  <!-- Turnstile widget -->
  <div class="cf-turnstile" data-sitekey="YOUR_SITE_KEY"></div>

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

<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>

The widget renders a hidden input named cf-turnstile-response and fills it with a token when the challenge completes. On submission, Formcrest verifies that token with Cloudflare before processing the submission. Submissions without a valid token are treated as spam. Get your site key from the Cloudflare Turnstile dashboard.

Turnstile is available on every Formcrest plan, including the free tier — you do not need to upgrade to use it.

One trade-off: Turnstile adds a JavaScript file and a Cloudflare network call. For most sites this is imperceptible, but test it if you have a strict Content Security Policy or performance budget.

Layer 3: rate limiting

Even with a honeypot and Turnstile, a determined attacker can manually craft requests that bypass both — sending programmatic POSTs without ever rendering your form's JavaScript. Rate limiting is the backstop.

Rate limiting works at the network layer: if a single IP address or a single form endpoint receives more requests in a short window than a normal human visit pattern would produce, excess requests are rejected with a 429 Too Many Requests response and a Retry-After header indicating when to retry.

For legitimate visitors, this is invisible. No human fills in a contact form multiple times per second. For bots running burst attacks, it means the vast majority of their requests are bounced before they ever hit your submission quota.

On Formcrest, per-IP and per-form rate limiting runs automatically at the edge on every form, on every plan. There is nothing to configure.

Defense-in-depth: layering all three

The layers are complementary. A bot that evades the honeypot by parsing CSS may still fail Turnstile. A bot that can render JavaScript and solve Turnstile will still hit the rate limit if it tries to submit at scale. For most contact forms, the honeypot alone is sufficient — add Turnstile when you need a harder guarantee, and rate limiting is always running in the background.

What happens to flagged spam

On Formcrest, submissions flagged as spam — by the honeypot, Turnstile, or rate limiting — are stored in the dashboard and marked as spam rather than being silently dropped. This means you can review flagged submissions if you ever suspect a legitimate submission was incorrectly caught.

Importantly, spam-flagged submissions do not count against your monthly submission quota. An attack that attempts thousands of submissions per hour will not consume your quota — the rate limiter rejects most, and the honeypot or Turnstile catches the rest.

Setting up spam protection in Formcrest

Spam protection is configured per-form in the dashboard. The honeypot is active by default. Turnstile is opt-in: enable it on a form and add the widget to your markup. Rate limiting requires no configuration.

For the full setup guide, including the complete example with both honeypot and Turnstile, see /docs/forms/spam.

Start protecting your forms — sign up free, no credit card required.


FAQ

Does the honeypot ever produce false positives?

Rarely, but it can happen if a browser extension, password manager, or accessibility tool fills in hidden fields. Setting autocomplete="off" and tabindex="-1" reduces this significantly. If you suspect legitimate submissions are being flagged, review them in the Formcrest dashboard — spam submissions are stored, not deleted.

Can I use Turnstile on the free plan?

Yes. Cloudflare Turnstile is available on every Formcrest plan, including the free tier. You need a Cloudflare account to get a site key, but Cloudflare's Turnstile offering itself is also free.

What is the difference between honeypot spam and rate-limited requests?

A honeypot-flagged submission made it through the rate limiter — it was not part of a burst attack, just a bot that filled in every field. A rate-limited request never completed at all — it was rejected at the edge before Formcrest processed it. Both are handled transparently without affecting your quota.

Should I use a honeypot field if I am submitting via fetch instead of a native form POST?

Yes. Keep the _honey field in your HTML. When you build FormData from the form element, the honeypot field is included automatically. Its value will be empty for real submissions and non-empty for bots that complete the form without executing the JavaScript that would normally prevent them.

Ship your form in minutes

Point any HTML form at Formcrest — validation, spam filtering, and delivery included. Free for 500 submissions a month, no credit card.

Get started free