Bot protection for publicly accessible form

Hi

I have a contact me form set up on this site
https://emmawedgwoodaesthetics.co.uk/contact/

I’m getting a lot of bots now submitting contact me’s

I was wondering what is the go to option for form protection/human checking?

Recaptcha?

Thanks
Chris

I use multiple layers:

  • Recaptcha
  • “Honeypot” fields or checkboxes. (A field or checkbox marked as “hidden” - if it’s filled out or checked, the entire form is discarded.)
  • “Reject list” for originating domains
  • A manual reject list by originating IP address. (Yes, I know I might be potentially blocking legitimate requests, but given the limited geographical interest of this form/site, I highly doubt it.) I use fail2ban to help identify these.
  • Rejecting certain text patterns in the submission.

It’s gotten the spam bots down to a very tolerable level.

Thanks Ken

I implemented a honeypot field yesterday but still getting lots of action today.

I’ll add recaptcha and work my way down the list :smiley:

I’m curious, how are you implementing the honeypot field? Are they just not taking the bait?
(If it’s too obvious, a lot of bots have been set up to avoid it. For example, I don’t define the field as type=hidden. I set it up as a regular field, but inside a div with a CSS class display: none.)

Thanks for the follow up Ken I just looked at my code and I see what I have done wrong

Below is my code. The issue I have is I forgot to add the field to my crispy layout.
Going to add now and see if it helps.


class HoneypotField(forms.BooleanField):
    default_widget = forms.CheckboxInput(
        {"style": "display:none !important;", "tabindex": "-1", "autocomplete": "off"}
    )

    def __init__(self, *args, **kwargs):
        kwargs.setdefault("widget", HoneypotField.default_widget)
        kwargs["required"] = False
        super().__init__(*args, **kwargs)

    def clean(self, value):
        if cleaned_value := super().clean(value):
            raise ValidationError("")
        else:
            return cleaned_value


class ContactForm(forms.Form):
    asdf = HoneypotField()
    name = forms.CharField(
        max_length=100,
        required=True,
        widget=FloatingLabelWidget(
            attrs={
                "class": "text-light placeholder-transparent peer h-10 w-full border-b-2 border-light text-orange-300 focus:outline-none\
                     focus:border-gold bg-transparent"
            }
        ),
    )
    email = forms.CharField(
        max_length=100,
        required=True,
        widget=FloatingLabelWidget(
            attrs={
                "class": "text-light placeholder-transparent peer h-10 w-full border-b-2 border-light text-orange-300 focus:outline-none\
                     focus:border-gold bg-transparent"
            }
        ),
    )
    message = forms.CharField(
        help_text="",
        widget=FloatingLabelTextAreaWidget(
            attrs={
                "class": "text-light placeholder-transparent peer w-full border-b-2 border-light text-orange-300 focus:outline-none\
                     focus:border-gold bg-transparent mt-5"
            }
        ),
    )
    opt_in = forms.BooleanField(
        label=False,
        required=True,
    )

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.label_class = "absolute transition-all left-0 -top-3.5 text-gold text-sm peer-placeholder-shown:text-base \
                                    peer-placeholder-shown:text-gold peer-placeholder-shown:top-2 peer-focus:-top-3.5 peer-focus:text-gold \
                                    peer-focus:text-sm"
        self.helper.form_class = "ml-5p w-full md:w-2/3 lg:w-1/2 my-10"
        self.helper.layout = Layout(
            Field(
                "name",
                template="tailwind/floating_label_field.html",
                wrapper_class="relative my-5",
                placeholder="Name",
            ),
            Field(
                "email",
                template="tailwind/floating_label_field.html",
                wrapper_class="relative my-5",
                placeholder="Email",
            ),
            Field(
                "message",
                template="tailwind/floating_label_field.html",
                wrapper_class="relative my-5",
                placeholder="Message",
            ),
            Div(
                HTML(
                    """
            <div class="font-noe text-sm font-normal tracking-tight text-skin mb-3 mt-1">I confirm that I have read and agree to Emma Wedgwood Aesthetics <a href="/privacy-terms" class="underline" >terms and privacy policy.</a></div>
        """
                ),
                Field(
                    "opt_in",
                ),
                css_class="grid grid-cols-2",
            ),
## NEED TO ADD MY FIELD HERE ##
            ButtonHolder(
                Submit(
                    "submit",
                    "Submit",
                    css_class="bg-transparent cursor-pointer font-semibold h-8 font-rubik text-ourstory border border-gold hover:border-gold text-xs  rounded-3xl w-1/5",
                )
            ),
        )