Stopping Form Spam: reCAPTCHA, Honeypots and Validation
Put a form on a website and, sooner or later, the junk arrives: fake inquiries, link-stuffed messages, sign-ups with made-up addresses. It wastes time, pollutes your contact list, and can even hurt your email reputation if you send welcome emails to addresses that never asked for them. The fix is rarely one tool. This guide walks through the main options, reCAPTCHA, honeypot fields, time checks and validation, what each one stops, what it costs your real visitors, and how to combine them without making the form harder to finish.
Updated

Where form spam comes from
It helps to know what you’re defending against, because different defenses stop different senders:
| Source | What it looks like | What tends to stop it |
|---|---|---|
| Simple bots | Scripts that find forms and fill every field, often within a second of loading the page | Honeypot fields, time checks, server-side validation |
| Smarter bots | Scripts that run a real browser, skip hidden fields and wait before submitting | reCAPTCHA and similar risk checks, rate limits |
| Direct submissions | Requests sent straight to your form’s submit address without loading the page at all | Server-side checks: a reCAPTCHA token verified on the server, validation on the server |
| Human spammers | People pasting ads or links by hand | Content filters, moderation, review before follow-up; CAPTCHAs barely slow them down |
| Fake sign-ups with real addresses | Someone else’s email entered into your newsletter form | Confirmation emails (double opt-in) and server-side checks |
No single method covers every row. The usual approach is layers: cheap, invisible checks that stop the bulk of automated junk, plus one stronger check when that isn’t enough.
Rule one: validate on the server
Browser validation, such as a required field or an email field that rejects “abc,” helps honest visitors fix mistakes. It doesn’t stop spam. MDN’s guide to client-side form validation is blunt about it: client-side validation “should not be considered an exhaustive security measure,” because it’s easy to bypass, and your app should always validate form data on the server as well. A bot can skip your page entirely and send whatever it wants to the address the form submits to.
In HTML, the built-in validation attributes look like this:
<form method="post" action="/contact">
<label for="name">Name</label>
<input id="name" name="name" required maxlength="100">
<label for="email">Email</label>
<input id="email" name="email" type="email" required>
<label for="message">Message</label>
<textarea id="message" name="message" required minlength="10" maxlength="2000"></textarea>
<button>Send</button>
</form>Those attributes (required, type="email", minlength, maxlength, pattern and others) run in the browser. On the server, repeat the same rules and add a few that only the server can check:
- Reject what the browser should have stopped. Empty required fields, an invalid email format, or text longer than your maximum mean the request didn’t come through your form as designed.
- Accept only the fields you expect. Ignore or reject extra parameters.
- Keep length limits on every text field. Very long messages are a common sign of pasted spam, and limits protect your database and notification emails.
- Use the right field types. A phone field that accepts only phone-number characters and a URL field that checks the format reduce junk with no cost to real visitors.
- Escape everything you display. Treat form content as plain text when you show it in your dashboard or in a notification email, never as HTML.
Validation won’t stop a bot that fills in well-formed answers, but it removes a lot of garbage and is the foundation for everything else.
Honeypot fields
A honeypot is an extra form field that people can’t see, so they leave it empty, while simple bots that fill every input fill it in. If the field arrives with a value, the server quietly discards the submission.
Honeypots are popular because they add no friction at all. The W3C’s note on the inaccessibility of CAPTCHA discusses them among the non-interactive alternatives and puts it simply: “if a honeypot suffices, use a honeypot until evidence of robotic attacks dictates something else.”
A basic version looks like this:
<!-- Visually hidden, skipped by keyboard and screen readers -->
<div class="hp-field" aria-hidden="true">
<label for="website">Leave this field empty</label>
<input id="website" name="website" type="text" tabindex="-1" autocomplete="off">
</div>
<style>
.hp-field { position: absolute; left: -9999px; }
</style>And on the server, the check is one line of logic: if the website field isn’t empty, don’t save the submission, don’t send notifications, and return the normal “thank you” response so the bot learns nothing.
A few details decide whether a honeypot helps or hurts:
- Hide it from people, including assistive technology. aria-hidden and tabindex="-1" keep screen-reader and keyboard users from landing on it. A clear label such as “Leave this field empty” is a fallback if someone does reach it.
- Watch out for browser autofill. If the field name looks like something a browser autofills (such as “email” or “phone”), real visitors’ browsers may fill it in and you’ll throw away genuine messages. Use a neutral name and autocomplete="off".
- Use a normal text input, not type="hidden". A hidden input is easy for a script to recognize and skip. A regular text input moved off screen looks like any other field to a simple bot.
- Log what you discard, at least at first. If genuine inquiries go missing, you want to know.
The limitation is obvious: a bot that renders the page and only fills visible fields walks straight past a honeypot. Honeypots are a first layer, not a complete answer.
Time checks
People take at least a few seconds to read and fill a form. Many bots submit almost instantly. A time check records when the form was loaded (for example, in a signed hidden value or server-side session) and rejects submissions that arrive impossibly fast.
Keep the threshold low, a few seconds rather than a minute, because password managers and autofill let real people submit quickly, and keep the timestamp signed so a bot can’t simply change it. Also allow for the opposite case: someone who opens the page, leaves for an hour and comes back should still be able to send the form, or at least get a clear message asking them to try again.
reCAPTCHA: what the versions do
Google reCAPTCHA is the best-known risk check. Google’s overview of reCAPTCHA types describes a few versions that work quite differently:
| Type | What the visitor sees | What your server gets | Trade-off |
|---|---|---|---|
| v2 checkbox | An “I’m not a robot” checkbox; sometimes an image challenge | A token to verify: pass or fail | Visible and familiar; a challenge adds friction for some visitors |
| v2 invisible | Usually nothing; by default only the most suspicious traffic gets a challenge | A token to verify: pass or fail | Less friction, but challenges can still appear |
| v3 | Nothing; no interaction | A score from 0.0 (very likely a bot) to 1.0 (very likely good) | No friction, but you decide what to do with low scores |
With the v2 checkbox, when the visitor completes the check, the widget adds a value named g-recaptcha-response to the form. Google’s widget documentation explains that this token is posted along with the form, and that you can run a callback when the response expires and the visitor needs to check the box again.
For v3, Google’s v3 documentation says it “returns a score for each request without user friction.” By default you can use a threshold of 0.5, though Google suggests reviewing your traffic first. Its advice for low scores is to act quietly rather than block outright: ask for extra verification, or send the item to moderation. Each place you run it can carry a named action, and you should check that the action in the response matches the one you expect.
reCAPTCHA must be verified on the server
The checkbox on the page proves nothing by itself. A bot can skip the page and post the form directly. What makes reCAPTCHA work is the server check: your server sends the token to Google and only accepts the submission if Google confirms it. Google’s verification documentation spells out the details:
POST https://www.google.com/recaptcha/api/siteverify
secret=YOUR_SECRET_KEY
response=TOKEN_FROM_g-recaptcha-response
remoteip=VISITOR_IP (optional)
Response (JSON):
success true or false
challenge_ts when the challenge loaded
hostname the site where it was solved
error-codes optional list of errors- Tokens expire. Each token is valid for two minutes and can be verified only once. Expired or reused tokens come back with the error code timeout-or-duplicate.
- Check the hostname. Make sure the response’s hostname is your own site.
- Keep the secret key secret. It belongs on the server only, never in page code.
- Show a helpful error. If verification fails, say so and let the visitor try again without losing what they typed.
The two-minute rule matters on long forms. If someone ticks the box first and then spends five minutes writing a message, the token may have expired by the time they press Send. Placing the checkbox just above the submit button helps, and so does handling the expired callback so the visitor is prompted to check it again.
reCAPTCHA practicalities in 2026
If you set up reCAPTCHA yourself, three practical points are worth knowing today:
- The documentation has moved. Google’s classic reCAPTCHA developer pages are now marked deprecated and point to its Google Cloud documentation. The pages still explain how the widget and verification work, but check the Google Cloud docs for current setup.
- Free usage has a monthly limit. Google’s reCAPTCHA billing page (last updated October 9, 2026) lists up to 10,000 assessments per calendar month per organization at no cost. Without billing enabled, requests beyond that receive a quota error until the next month. With billing enabled, 10,001 to 100,000 assessments cost a flat $8, and $0.001 per assessment above that. If you run v3 on every page, assessments add up faster than if you only check form submissions.
- Branding and cookies. Google’s reCAPTCHA FAQ says you may hide the floating badge only if you include the reCAPTCHA branding visibly in the user flow, such as the text “This site is protected by reCAPTCHA.” It also notes that reCAPTCHA sets a necessary cookie (_GRECAPTCHA) for its risk analysis, which you may want to mention in your privacy policy.
The cost of a CAPTCHA to real visitors
Every challenge asks real people to prove themselves. The W3C note on CAPTCHA accessibility explains why this falls hardest on people with disabilities: visual puzzles are unusable with a screen reader, audio alternatives are hard to understand and exclude deaf-blind users, and multi-step puzzles are hard for people with cognitive disabilities. It also notes that reCAPTCHA v2 sometimes falls back to a challenge that assistive technology users can’t complete. Its recommendations: use the least challenging method that meets your security needs, keep interactive challenges to a minimum, and offer alternatives.
There’s a conversion cost too. A visitor who fills in every field and then gets stuck on an image challenge may simply give up. If you measure form abandonment field by field (see our guide to finding the field where people give up), a step that many people reach but don’t get past is a sign the check is too strict. Compare drop-off before and after you turn a challenge on, and weigh it against how much spam it blocks.
A practical way to think about it: start with the invisible layers (validation, honeypot, time check). Add a visible challenge only when spam still gets through, and only on the forms that are actually being hit.
Choosing your layers
| Method | Stops | Doesn’t stop | Friction | Effort |
|---|---|---|---|---|
| Server-side validation | Malformed and oversized junk, direct posts with missing fields | Well-formed spam | None (helps real users fix mistakes) | Low |
| Honeypot field | Bots that fill every field | Bots that skip hidden fields; humans | None | Low |
| Time check | Bots that submit instantly | Bots that wait; humans | None (if the threshold is low) | Low |
| reCAPTCHA v2 checkbox | Most automated submissions, including direct posts (when verified on the server) | Human spammers | A click, sometimes a puzzle; accessibility concerns | Low to medium |
| reCAPTCHA v3 | Automated traffic, scored in the background | Human spammers; scores need tuning | None, unless you add a step for low scores | Medium |
| Rate limiting | Floods from one source | Distributed or slow spam | None for normal use | Medium |
| Confirmation email (double opt-in) | Fake newsletter sign-ups using other people’s addresses | Spam inquiries in contact forms | One extra click for subscribers | Medium |
| Content rules or moderation | Link-stuffed or off-topic messages, including human spam | Clean-looking spam | None if done after submission | Ongoing |
For most small sites, a sensible starting combination is server-side validation plus a honeypot, adding a reCAPTCHA checkbox when spam continues. Newsletter sign-up forms deserve extra care: sending welcome emails to addresses that never signed up generates spam complaints. Our guides to SPF, DKIM and DMARC and email sign-up pop-ups cover the email side.
What to do with spam that gets through
Some will. When it does:
- Don’t reply. Replying confirms your address is active and that someone reads the form.
- Don’t add it to your email list. Spam sign-ups are the worst kind of contact to email. Remove them before any welcome sequence runs.
- Look for patterns. The same phrases, links or fields filled oddly suggest a rule you can add on the server.
- Check which form is targeted. Often it’s one old form or one page. Protect that one more strictly instead of adding a challenge everywhere.
- Re-check after changes. When you tighten a rule, check that genuine submissions still arrive by sending a test yourself.
Spam protection in marketingLABO forms
If you build forms with marketingLABO’s form builder, here is what’s available today:
- reCAPTCHA (v2 checkbox), with one switch. In the form builder’s settings, the Security section has a toggle to enable reCAPTCHA. A shared site key is used automatically, so there are no keys to create or paste in.
- Verified on the server. When reCAPTCHA is on, each submission’s token is checked on the server before the entry is accepted, so posting directly to the form without completing the check doesn’t work.
- Your own error message. The “reCAPTCHA failed” message, like the other error messages, can be edited in the Error messages section.
- Validation built in. Required fields and format checks such as email, URL and phone number, plus minimum and maximum length, an email confirmation field and a terms checkbox, each with an editable error message. Real-time validation can show errors as soon as a field loses focus.
- A/B tests follow the original form. If you run an A/B test on a form, the variant uses the reCAPTCHA setting of the original form, so both versions are protected the same way.
- Drop-off by field. The form’s drop-off report shows where people stop, which helps you see whether turning on reCAPTCHA is costing you genuine submissions.
What it doesn’t have: there’s no honeypot setting and no score-based (v3) option, so the choice in the builder is the reCAPTCHA checkbox on or off. The free plan includes one form; see pricing for more forms, or sign up free to try it. For making the form itself easier to finish, see our form UX best practices.
A quick checklist
- Every form validates on the server, not just in the browser.
- Text fields have sensible maximum lengths; email, phone and URL fields check their format.
- A honeypot field is in place, hidden from people and screen readers, with a neutral name and autofill off.
- Submissions that arrive impossibly fast are rejected (with a low threshold).
- If you use reCAPTCHA, the token is verified on the server, the hostname is checked, and the secret key never appears in page code.
- Long forms place the checkbox near the submit button and handle expired tokens.
- If you hide the reCAPTCHA badge, the required branding text appears in the form.
- Newsletter sign-ups are cleaned before any automated email goes out.
- Form drop-off is compared before and after adding a visible challenge.
FAQ
Is a honeypot enough on its own?
Sometimes. On a small site that only gets simple bots, a honeypot plus server-side validation can be all you need. If spam keeps coming, the bots are probably skipping hidden fields, and it’s time to add reCAPTCHA or another check.
Does reCAPTCHA stop human spammers?
Not really. A person can tick the box. For hand-typed spam, content rules, moderation and simply not following up on obvious junk work better.
Should I use reCAPTCHA v2 or v3?
v2 gives a clear pass or fail and is simpler to run. v3 adds no friction but gives you a score, and you need to decide what to do below your threshold (Google suggests 0.5 as a default starting point). If you can’t act on a score, for example by sending low-scoring messages to review, v2 is easier.
Why do some genuine visitors fail the check?
Expired tokens are a common cause: the token is valid for two minutes, so a visitor who ticks the box and then takes a long time to finish may need to check it again. Google’s FAQ also acknowledges that good users can occasionally be flagged. Clear error messages that keep the visitor’s answers make this much less painful.
Can I use a honeypot and reCAPTCHA together?
Yes, and many sites do. The honeypot and the server-side checks quietly discard the simplest bots before they cost you anything, and reCAPTCHA handles the bots that get past them. Because the honeypot adds no friction, there’s no downside to keeping it when you add a visible check.
Will a CAPTCHA hurt my conversion rate?
It can add friction, especially if an image challenge appears. The only reliable way to know for your form is to compare submissions and drop-off before and after turning it on.
Sources
- Google reCAPTCHA, Verifying the user’s response (accessed October 12, 2026): https://developers.google.com/recaptcha/docs/verify
- Google reCAPTCHA, reCAPTCHA v3 (accessed October 12, 2026): https://developers.google.com/recaptcha/docs/v3
- Google reCAPTCHA, reCAPTCHA v2 widget display (accessed October 12, 2026): https://developers.google.com/recaptcha/docs/display
- Google reCAPTCHA, Choosing the type of reCAPTCHA (accessed October 12, 2026): https://developers.google.com/recaptcha/docs/versions
- Google reCAPTCHA, FAQ (accessed October 12, 2026): https://developers.google.com/recaptcha/docs/faq
- Google Cloud, reCAPTCHA billing information (last updated October 9, 2026; accessed October 12, 2026): https://docs.cloud.google.com/recaptcha/docs/billing-information
- W3C, Inaccessibility of CAPTCHA (Group Draft Note, December 16, 2021; accessed October 12, 2026): https://www.w3.org/TR/turingtest/
- MDN Web Docs, Client-side form validation (accessed October 12, 2026): https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Forms/Form_validation
Start free — no credit card needed
Sign up freeMore articles

Win-Back Emails: How to Re-engage Customers Who Stopped Visiting
How to plan win-back emails: define inactivity, write a 2–3 email sequence, stop when people return, and clean your list without hurting deliverability.
Read the article →
Resending to Non-Openers: When It Helps and When It Hurts
When to resend an email to people who didn’t open it, how to do it (new subject, one resend, the right wait), and why Apple Mail makes “non-openers” fuzzy.
Read the article →
Countdown Timer Pop-ups: Using Urgency Without Dark Patterns
When a countdown timer pop-up is honest, what the FTC and EU rules say about fake urgency, and how to set up a timer that matches a real deadline.
Read the article →
Email Sign-up Pop-ups: Offers, Fields and Placement That Work
How to plan an email sign-up pop-up: the offer, which fields to ask for, consent wording, who should see it, when to show it, and what to do with sign-ups.
Read the article →
A/B Testing Your Forms: Sample Size, p-Values and When to Stop
How to A/B test a form properly: why a 50:50 split, how many views you need, what a p-value really says, and why stopping early fools you.
Read the article →
How to Add a Tracking Script in BigCommerce Script Manager
Add a tracking script to your BigCommerce store with Script Manager: header placement, which pages to pick, consent category, load method, testing and fixes.
Read the article →