Stop Spam Before It Starts: A Honeypot for Your Webflow Forms
A no-backend way to block spam on Webflow forms — trap the bots with a honeypot field, turn away the free-email junk, and keep your inbox full of leads worth chasing. Setup steps, custom attributes, and the GitHub repo.
You open your inbox Monday morning and there are eleven new "leads." One wants to sell you SEO. One is selling backlinks to fight the first one. Three are blank except for a name like asdf qwerty. And buried somewhere in the pile is the one real person who actually wanted to talk to you — if you can find them before you give up scrolling.
Form spam is the tax you didn't agree to pay. It's noise that hides signal. Every junk submission is a row your sales follow-up has to look at, dismiss, and resent a little. And the bots are nothing if not enthusiastic. They fill every field on the form like an overeager intern trying to look busy on day one — name, phone, that weird hidden field you forgot was there, all of it.
I've been building Webflow sites for 7 years and shipped over 100 of them, so I've watched what actually hits these forms — and the overwhelming majority of it is low-effort scripts, not a hacker in a hoodie. That matters, because it means you can stop most of it cheaply.
Here's the good news: you can stop most of it before it ever reaches you, with no backend, no Zapier step, and no CAPTCHA making your real visitors prove they're human by clicking on traffic lights. Two simple defenses do the heavy lifting — a honeypot to catch the bots, and a domain filter to turn away the throwaway emails. Both run client-side. Both are wired into Webflow in an afternoon.
Let me walk you through it.
What Does It Actually Do?
The script does two things simultaneously:
1. Blocks free/personal email domains. When someone submits your form with a Gmail, Yahoo, Hotmail, iCloud, or similar address, the script intercepts the submission and shows an error message before anything hits your inbox. It also catches common typos like gmali.com and gamil.com, so accidental mis-spellings don't slip through.
2. Traps bots with a hidden field. A technique called a "honeypot" involves placing a hidden input field on the form, one that real users never see or fill out, but bots do (because they blindly fill every field they find). If that field has a value on submit, the script knows it's a bot and silently blocks the submission.
The result: cleaner leads, less noise, and no backend changes required.
Setting It Up
Step 1: Add the CMS Toggle
The script is designed to be toggled on or off via a Webflow CMS field, useful if you want validation on some pages but not others (a contact form vs. A newsletter signup, for example).
In your CMS collection, add a Switch field named "Form Validation".
Then, on the page where your form lives, select the wrapper element and add a Custom Attribute:
- Name:
data-form-validation - Value: Bind it to your CMS "Form Validation" field
When the CMS field is toggled on, this attribute outputs "true" on the element, and the script activates.
Step 2: Configure Your Form Elements
Inside your Webflow form, add two custom attributes:
- A hidden input (bot trap): add attribute
data-input-15 - An error message div: add attribute
data-error-message
The email input and submit button are found automatically by the script, no attributes needed on those.
Step 3: Embed the Script
Grab the contents of global-code.js from the honeypot-webflow GitHub repo. Then in Webflow, go to Project Settings → Custom Code, scroll to Footer Code, and paste it wrapped in script tags:
<script>
(function () {
// Check CMS toggle on the page wrapper
const formValidationEnabled = document.querySelector('[data-form-validation="true"]');
if (!formValidationEnabled) return;
// Regex pattern for free email domains, matching any TLD
const freeEmailPattern = /@(gmail|gmali|gamil|yahoo|ymail|hotmail|outlook|aol|icloud|protonmail|proton|mail|gmx|zoho|tutanota|fastmail|yandex|live|msn)\.\w+$/i;
const basicEmailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
function validateEmail(email) {
if (!basicEmailPattern.test(email)) {
return { isValid: false, message: 'Please enter a valid business email' };
}
if (freeEmailPattern.test(email)) {
return { isValid: false, message: 'Please enter a valid business email' };
}
return { isValid: true, message: '' };
}
function initForm(formWrapper) {
const form = formWrapper.querySelector('form');
if (!form) return;
const emailInput = form.querySelector('input[type="email"]');
const input15 = form.querySelector('input[data-input-15]');
const submitButton = form.querySelector('input[type="submit"], button[type="submit"]');
const errorMessageDiv = form.querySelector('[data-error-message]');
if (!emailInput || !submitButton) return;
function validateForm() {
const email = emailInput.value.trim();
// Silently block submission if input-15 is filled
if (input15 && input15.value.trim().length > 0) {
submitButton.disabled = true;
if (errorMessageDiv) errorMessageDiv.style.display = 'none';
return;
}
const emailValidation = validateEmail(email);
if (emailValidation.isValid) {
submitButton.disabled = false;
if (errorMessageDiv) errorMessageDiv.style.display = 'none';
} else {
submitButton.disabled = true;
if (errorMessageDiv) {
errorMessageDiv.style.display = 'block';
errorMessageDiv.textContent = emailValidation.message;
}
}
}
emailInput.addEventListener('input', validateForm);
if (input15) input15.addEventListener('input', validateForm);
}
// Apply to all Webflow forms on the page
document.querySelectorAll('.w-form').forEach(initForm);
})();
</script>
Which Email Providers Are Blocked?
Out of the box, the script blocks: Gmail, Yahoo, Ymail, Hotmail, Outlook, AOL, iCloud, ProtonMail, Proton, Mail.com, GMX, Zoho, Tutanota, Fastmail, Yandex, Live, and MSN, across any TLD. It also catches the typos gmali and gamil.
You can add or remove providers by editing the blocked domains list directly in the script before embedding.
Why a CMS Toggle?
Rather than hardcoding validation on every form, you get per-page control without touching code. This is especially handy for lead gen pages where you want strict business email enforcement, event signups where Gmail is fine, or A/B testing validation messaging without a redeployment.
A Note on Honeypots vs. CAPTCHA
Let me be honest about the limits, because pretending a tool does more than it does is how you get burned later.
Honeypot fields are not a complete bot-blocking solution, but they're significantly less friction for real users than a CAPTCHA — nobody buys from you because you made them click on traffic lights first. Sophisticated bots can detect and skip honeypot fields, but the vast majority of form spam comes from low-effort scripts that fill every field they find. For most Webflow marketing sites, this approach catches plenty of junk without annoying legitimate leads.
For very high-traffic forms or particularly targeted spam, consider layering this with Webflow's native reCAPTCHA integration as an additional defense.
Putting It All Together
Once configured, your Webflow form will: check the CMS toggle, inspect the hidden honeypot field on submit, validate the email domain, and, if both checks pass, allow the native Webflow form submission to proceed normally.
No backend, no Zapier step, no extra services. Check out the full source at github.com/twistedx/honeypot-webflow.
A clean form isn't a vanity thing. It's the front door of your whole pipeline — the first place a real prospect and a real lead become a real row in your CRM. Keep the junk out of that door and everyone downstream trusts what comes through it.
If your forms are part of a bigger build — or the bigger build is the part that's actually broken — that's the kind of plumbing we do. Have a look at our Webflow development work, or just get in touch and tell us what your inbox looks like on a Monday.