Protect lead form from spam bots: a layered checklist

A layered, vendor-neutral way to keep junk out of a lead form, from free invisible checks to CAPTCHA and verification. Also covers where click filtering fits and where it does not.

TDS Team Author
Published
8 min Reading time
All posts

You protect a lead form with several cheap layers. A hidden honeypot field, a minimum time-to-submit, strict server-side validation, rate limits, duplicate checks and, where the lead is worth it, phone or email confirmation. CAPTCHA goes on top of that, and only when the cheaper layers let too much through.

The order matters because each layer costs you something. Every extra field or puzzle lowers the conversion rate of real visitors, so you start with checks they never see and add friction only where the numbers justify it.

Short answer

Start with invisible checks (honeypot, timing, server-side validation, rate limit), add duplicate detection and confirmation for valuable leads, and use CAPTCHA last. Separately, stop bot clicks before they reach the page. TDS.SO does that second part on the link, in front of the landing. It does not protect the form itself.

Two different problems that look the same

Junk leads come from two places. Some are scripts that find your form and post to it directly, never loading the page the way a browser would. Others are automated visitors that arrive through your ad link, load the page, and sometimes fill the form because a script told them to.

The first group is solved at the form and its endpoint. The second group is cheaper to deal with earlier, at the click. If you treat both with CAPTCHA alone, you pay for every bot click, annoy real users, and still miss the scripts that call your endpoint without a browser. For how to recognise the second group in a click log, see signs of bot traffic.

Layer 1: a honeypot field

A honeypot is an extra input that real people never see. You hide it with CSS (not type="hidden", because simple bots skip hidden inputs), give it an attractive name such as website or company, and reject any submission where it is filled in.

Code
<div style="position:absolute;left:-9999px" aria-hidden="true">
  <label>Leave this empty
    <input type="text" name="website" tabindex="-1" autocomplete="off">
  </label>
</div>

Set autocomplete="off" and tabindex="-1", otherwise browser autofill or keyboard users will fill it and you will reject real leads. Check it on the server. A honeypot catches naive form-filling scripts and nothing more advanced, so treat it as a free first filter.

Layer 2: time-to-submit

A person needs a few seconds to read a form and type into it. A script can submit in milliseconds. Put a timestamp in a signed token when the form is rendered, and compare it with the time the submission arrives.

  • Reject submissions faster than a threshold you choose, for example 3 seconds for a form with several fields.
  • Reject tokens that are far too old (say, a day), since replayed tokens are a common pattern.
  • Sign the token on the server so it cannot be forged by editing the page.

Keep the threshold generous. Autofill can complete a form in about a second, so a hard limit that is too high rejects real people. Log rejections for a week before you start dropping anything.

Layer 3: server-side validation

Anything done in the browser can be skipped by posting straight to your endpoint. The rules that matter have to live on the server.

  • Types and lengths. A name field of 4,000 characters or a phone field with letters is not a person.
  • Format. Normalise phone numbers to one format and check that the country code matches the market you advertise in.
  • Allowed values. Dropdowns and radio buttons should only accept the values you rendered.
  • Content. Reject links in fields that should not contain links, and obvious placeholder text such as test or asdf.
  • Origin. Check the Origin or Referer header and a CSRF token. Both can be faked by a determined script, but they stop careless ones.

Layer 4: rate limits

Limit how many submissions one IP address, one session and one device can make in a window. Something like 3 per IP per hour is a reasonable starting point for a typical lead form, and you can tune it from your own logs.

Two cautions. Mobile carriers and offices share IP addresses between many people, so combine the IP with a cookie or session before you block, and prefer a soft response (a delay or a CAPTCHA challenge) over a hard ban. Also return the same generic response whether you accept or reject, so a script cannot learn which rule it tripped.

CAPTCHA and its trade-offs

CAPTCHA works, and it has a price. Visible puzzles add steps for real users and can lower the completion rate. Invisible or score-based versions hide that cost for most people, but they depend on a third-party script, can misjudge users on VPNs or unusual browsers, and raise privacy questions you may need to cover in your policy. Solving services exist for most puzzles, so it slows down a determined attacker rather than stopping one.

OptionCost to real usersStopsWatch out for
HoneypotNoneNaive scriptsAutofill filling the hidden field
Time-to-submitNoneInstant postsThreshold set too high
Rate limitLowFloods from one sourceShared IPs
Invisible CAPTCHALowMany generic botsThird-party script, false positives
Visible CAPTCHAMedium to highMany botsLower completion rate
Phone or email confirmationHighFake contact dataAbandonment, SMS cost

The practical rule is to show a CAPTCHA only to submissions that already look suspicious (a failed timing check, a burst from one IP), and leave everyone else alone.

Verification and duplicate checks

Valid-looking data can still be fake. For leads that are expensive to follow up, confirm the contact before it reaches your team. Send a one-time code to the phone, or a confirmation link to the email, and only count the lead after it is used. Expect some real people to drop at this step, so apply it where a fake lead costs more than a lost one.

Duplicate checks are cheaper and catch a lot. Hash the normalised phone and email and look for repeats inside a window, and flag several leads that share the same IP and user agent within minutes. Decide in advance what a duplicate means for you: a person re-submitting is not the same as the same number appearing under five different names.

Filtering bot clicks before they reach the page

Everything above runs after the visitor has already loaded your landing page, which means the click was already paid for. If a share of your traffic is automated, you can reduce it earlier, at the link.

TDS.SO does this on the ad link. You choose a filter level (Off, Standard, High, JavaScript browser check or Custom) and tick the signals you want to act on: unknown platform, unknown browser, empty country, empty city, IPv6, data centers, VPN, empty referrer. Clicks that fail go to a page you set, and they stay in the click log with the reason (vpn, datacenter, suspicious_headers and so on), so you can check what was filtered. See anti-bot filtering for the details.

To be clear about the limits: this works on the link, before the landing. It does not see your form, does not validate fields and does not stop a script that posts directly to your form endpoint. Those layers stay your job. Treat the two as complementary, one reducing junk traffic and the other reducing junk submissions. A tighter level can also catch real people on VPNs, so start mild and read the log.

FAQ

Is a honeypot enough on its own?

For a small form with little traffic, it may be enough for a while. Against scripts that render the page or read the field names, it will not hold. Combine it with timing and server-side checks.

Does CAPTCHA reduce conversions?

Visible puzzles add a step, so they can. The size of the effect depends on your audience and form, so measure it with a split test instead of assuming. Showing it only to suspicious submissions limits the cost.

How do I tell if the junk comes from bot clicks or from direct posts?

Compare the lead timestamps with your click log. If junk leads have matching clicks from data centers or VPNs, the traffic is the source. If leads arrive with no corresponding click at all, something is posting to your endpoint directly.

Should I block by IP address?

Use IP as one signal, not the only one. Shared and mobile IPs mean a block can hit real people, and attackers rotate addresses. See JS fingerprint vs IP blocking for the trade-offs.

Does a traffic filter protect my form?

No. A click filter acts before the landing and reduces how many automated visitors arrive. The form still needs its own protection.

If bot clicks are part of your junk lead problem, you can set up filtering on the link with TDS.SO anti-bot, and keep the form checks from this article on your side.

Was this article useful?
TDS Team Author

Guides and write-ups on routing, bot filtering and tracking from the TDS.SO team.

All articles by the author
Keep reading

Related

All posts
Antibot 7 min

Bot traffic cost calculation: what bots take from your budget

11 Nov 2026 · TDS Team
Antibot 8 min

Filter VPN, Proxy and Datacenter Traffic: When and When Not

11 Nov 2026 · TDS Team
Antibot 9 min

Email security scanner clicks: why clicks exceed readers

10 Nov 2026 · TDS Team

Try it on
your own traffic

Link the Telegram bot and get 3 days free, once per account.

Create account