Defeating Form Spam Bots

I was receiving probably 50 to 100 spam messages every day. Not the worst I’ve seen, but still annoying.

What I was doing

I was doing the standard honeypot element, y’know where you have a text <input> that’s hidden somehow using CSS, which if filled you discard the submission. It was relatively effective, I’d probably give it a solid 75% effectiveness. The problem with 75% effectiveness if you were getting 100 spam submissions a day, you’re still getting 25 spam messages a day. Dammit.

I then changed the name of this input to “other-name”, in the hopes that it would trip up the spammer scripts that had a mild amount of smarts behind them. This change of input name did help, and I’d say we got to around 90% success, or 10 spam messages a day depending on whether you’re a glass full or glass empty sort of person.

What I’m doing now

We’re going to now need a page that will tell the user what happened if they have javascript disabled. You can’t fall back and accept inputs on this URL because that defeats the entire point of this. It’s important that that page does not accept any form submissions.

Next up, send your form there. <form action='/that-needs-js/'> now we’ll use Javascript to fix what we just broke. Spam bots will eventually start parsing javascript if people do this enough, but for now I’ve found that barely any of them (if any at all) are doing so.

<form id='myContactForm' action='/that-needs-js/' data-action='/your/actual/form/submit/url'>

Next it’s a case of having the browser substitute in that data-action for the regular action before submitting the form. Bung this in the page somewhere.

<script>
    function updateContactFormDestination() {
        var contactForm = document.getElementById("myContactForm");
        var realSubmitUrl = contactForm.getAttribute('data-action');

        contactForm.setAttribute('action', realSubmitUrl);
    }

    document.addEventListener("DOMContentLoaded", function(event) { 
        updateContactFormDestination();
    });
</script>

Currently this has, for me, had a 100% success rate. 0 spam emails coming from my form per day.

I give it a week.