Spam

A reCAPTCHA alternative that your visitors never see.

Most form spam is automated and most of it can be stopped without asking a real person to click on traffic lights. Here is the layered approach Heartdove applies to every form on every plan, what each layer catches, and when an optional human check is worth adding.

Updated 20 October 2026

What a CAPTCHA costs you

A CAPTCHA puts a puzzle between a visitor and the send button. Some people fail it, some give up, and people who use screen readers or have motor or vision impairments are hit hardest. It also loads a third-party script into your page, which is a privacy question you then have to answer in your policy. The spam it stops is real, but so is the enquiry you never received because the puzzle was in the way.

The alternative is to make the server do the work. Bots are bad at looking like a real browser on a real page, and most of them give themselves away before a human check is needed.

Layer 1: exact origin checks

Every submission must come from a website address you registered for the form, and the match is exact. A script posting the form from somewhere else, or from no page at all, is refused before anything is stored. This alone removes the bulk of drive-by scripts that scrape a key from one site and fire it from another.

Layer 2: per-visitor rate limits

Each visitor can only send so many submissions a minute. A bot hammering the endpoint gets a 429 with a retry delay; a person sending a message and a correction does not notice.

Layer 3: a hidden trap field

The generated snippet includes a checkbox that no person sees. Bots that fill every field tick it, and anything that arrives with the trap set is quarantined for review instead of alerting you. Keep the field exactly as generated: hidden with CSS, out of the tab order, autocomplete off.

The trap, in context
<form action="https://submit.heartdove.com/v1/submit" method="POST">
  <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY" />
  <label>Email <input type="email" name="email" required /></label>
  <label>Message <textarea name="message" required></textarea></label>
  <!-- Hidden spam trap: people never see it, bots tick it -->
  <input type="checkbox" name="botcheck" tabindex="-1" autocomplete="off" style="display:none" />
  <button type="submit">Send message</button>
</form>

Layer 4: spam scoring and quarantine

Every message is scored before it is stored, using the trap, link counts and the allow and block rules you set in the form’s settings. High scores are quarantined: the message is saved, listed in the inbox’s In review tab with its reasons in plain words, and no alert is sent. From there you can release it (“Not spam, deliver it”) or delete it and block the sender. Nothing is thrown away silently.

Layer 5, optional: Cloudflare Turnstile

For a busy form that still attracts manual spam, you can turn on Cloudflare Turnstile per form. It runs a browser check that is usually invisible and only shows an interaction when it is unsure. Heartdove verifies the token on the server against the registered hostname and the form action, and the typed client fetches a fresh token on every retry. Turnstile is never required, and most forms do not need it.

What Heartdove does not do

  • It does not verify reCAPTCHA tokens. If you add reCAPTCHA to your page yourself, Heartdove ignores the token; use Turnstile if you want a server-verified human check.
  • It does not inject a script. The plain HTML snippet loads nothing from Heartdove; only Turnstile, when you enable it, adds a script.
  • It does not promise that a real person never sees friction. Turnstile can ask for an interaction when it is unsure, which is why it stays optional.

How the layers add up

Scripts firing a copied key from elsewhereRefused by the exact origin check.
Floods from one addressRate limited with a retry delay.
Bots filling every fieldCaught by the hidden trap, quarantined.
Link-stuffed and rule-matching messagesScored and quarantined for review.
Manual spam on a busy formOptional Turnstile, verified on the server.

All of this is on the Free plan. See what is implemented and the request format.

Questions

Is a honeypot enough on its own?

No single layer is. The trap catches naive bots; the origin check and rate limits catch scripts; scoring and quarantine catch the rest without losing a real message. That is why they are combined.

Does this help with GDPR?

The plain form loads no third-party script and sets no cookie from Heartdove, which keeps your page simpler to describe in a privacy policy. Heartdove itself stores submissions in the United States; check the privacy policy for the processors involved. No compliance certification is claimed.

What happens to a quarantined message?

It is stored and listed under In review with its reasons. You can release it, which sends the alert under your usual allowance, or delete it and block the sender. Messages on a form in privacy mode keep no content and can only be deleted.

Can a visitor accidentally trigger the trap?

Only if the field is visible. Keep it hidden with CSS as generated; browser autofill does not tick hidden checkboxes.

Never lose another enquiry.

Connect your first form in a few minutes. Your existing design stays exactly as it is.