---
title: "Honeypot Spam Protection"
description: "Protect your forms from spam bots with an invisible honeypot field - a simple yet effective spam prevention technique."
url: https://forminit.com/docs/honeypot/
---

# Honeypot Spam Protection

Protect your forms from spam bots with an invisible honeypot field.

> **Note:** Forminit includes built-in spam protection by default. Honeypot is an optional extra layer of protection for forms that receive high volumes of spam.

---

## How It Works

Honeypot protection exploits a key difference between humans and bots:

1. **Humans** don't see or interact with hidden fields
2. **Bots** automatically fill out every field they find, including hidden ones

When a submission includes a value in the honeypot field, Forminit flags it as spam and rejects the submission. Legitimate users will never trigger this because they can't see or fill the hidden field.

---

## Quick Start

Add a hidden honeypot field to your form:

```html
<form id="contact-form">
  <input type="text" name="fi-sender-firstName" placeholder="First name" required />
  <input type="text" name="fi-sender-lastName" placeholder="Last name" required />
  <input type="email" name="fi-sender-email" placeholder="Email" required />
  <textarea name="fi-text-message" placeholder="Message" required></textarea>
  
  <input type="hidden" name="_gotcha" style="display:none !important" />
  
  <button type="submit">Send</button>
</form>
```

That's it! Any bot that fills in the `_gotcha` field will have their submission automatically rejected.

---

## Field Requirements

| Attribute | Value | Required |
|-----------|-------|----------|
| `type` | `hidden` | Yes |
| `name` | `_gotcha` (default) | Yes |
| `style` | `display:none !important` | Recommended |
| `value` | Empty (no value) | Yes |

**Important notes:**

- The field must have **no value** — leave it empty
- Use both `type="hidden"` and `style="display:none !important"` for maximum protection
- Do not add `required` attribute to the honeypot field

---

## Custom Honeypot Field Name

By default, the honeypot field is named `_gotcha`. Some sophisticated bots recognize common honeypot names and avoid them. You can use a custom field name for better protection.

### Change the Field Name

1. Go to your **Form Settings**
2. Navigate to **Honeypot**
3. Enter your custom field name
4. Save changes

### Update Your Form

After changing the field name in settings, update your HTML to match:

```html
<input type="hidden" name="website_url" style="display:none !important" />
```

**Tips for custom field names:**

- Use names that look like real fields (e.g., `website`, `company_url`, `fax_number`)
- Avoid obvious names like `honeypot`, `trap`, or `bot_check`
- Don't use the `fi-` prefix for honeypot fields

---

## Framework Examples

### HTML / Static Website

```html
<form id="contact-form">
  <input type="text" name="fi-sender-firstName" placeholder="First name" required />
  <input type="text" name="fi-sender-lastName" placeholder="Last name" required />
  <input type="email" name="fi-sender-email" placeholder="Email" required />
  <textarea name="fi-text-message" placeholder="Message" required></textarea>
  
  <input type="hidden" name="_gotcha" style="display:none !important" />
  
  <button type="submit">Send</button>
</form>

<p id="form-result"></p>

<script src="https://forminit.com/sdk/v1/forminit.js"></script>
<script>
  const forminit = new Forminit();
  const FORM_ID = 'YOUR_FORM_ID';
  
  document.getElementById('contact-form').addEventListener('submit', async (e) => {
    e.preventDefault();
    
    const formData = new FormData(e.target);
    const { data, error } = await forminit.submit(FORM_ID, formData);
    
    if (error) {
      document.getElementById('form-result').textContent = error.message;
      return;
    }
    
    document.getElementById('form-result').textContent = 'Message sent!';
    e.target.reset();
  });
</script>
```

### Next.js

```tsx
'use client';

import { useState } from 'react';
import { Forminit } from 'forminit';

export function ContactForm() {
  const [status, setStatus] = useState<'idle' | 'loading' | 'success' | 'error'>('idle');
  const [error, setError] = useState<string | null>(null);
  const forminit = new Forminit({ proxyUrl: '/api/forminit' });

  async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
    e.preventDefault();
    setStatus('loading');
    setError(null);

    const formData = new FormData(e.currentTarget);
    const { data, error } = await forminit.submit('YOUR_FORM_ID', formData);

    if (error) {
      setStatus('error');
      setError(error.message);
      return;
    }

    setStatus('success');
    e.currentTarget.reset();
  }

  return (
    <form onSubmit={handleSubmit}>
      <input type="text" name="fi-sender-firstName" placeholder="First name" required />
      <input type="text" name="fi-sender-lastName" placeholder="Last name" required />
      <input type="email" name="fi-sender-email" placeholder="Email" required />
      <textarea name="fi-text-message" placeholder="Message" required />
      
      <input type="hidden" name="_gotcha" style={{ display: 'none' }} />
      
      {status === 'error' && <p className="error">{error}</p>}
      {status === 'success' && <p className="success">Message sent!</p>}
      
      <button type="submit" disabled={status === 'loading'}>
        {status === 'loading' ? 'Sending...' : 'Send'}
      </button>
    </form>
  );
}
```

### Nuxt.js

```vue
<script setup lang="ts">
import { ref } from 'vue';
import { Forminit } from 'forminit';

const FORM_ID = 'YOUR_FORM_ID';

const status = ref<'idle' | 'loading' | 'success' | 'error'>('idle');
const errorMessage = ref<string | null>(null);
const formRef = ref<HTMLFormElement | null>(null);

const forminit = new Forminit({ proxyUrl: '/api/forminit' });

async function handleSubmit() {
  if (!formRef.value) return;
  
  status.value = 'loading';
  errorMessage.value = null;

  const formData = new FormData(formRef.value);
  const { data, error } = await forminit.submit(FORM_ID, formData);

  if (error) {
    status.value = 'error';
    errorMessage.value = error.message;
    return;
  }

  status.value = 'success';
  formRef.value.reset();
}
</script>

<template>
  <form ref="formRef" @submit.prevent="handleSubmit">
    <input type="text" name="fi-sender-firstName" placeholder="First name" required />
    <input type="text" name="fi-sender-lastName" placeholder="Last name" required />
    <input type="email" name="fi-sender-email" placeholder="Email" required />
    <textarea name="fi-text-message" placeholder="Message" required />
    
    <input type="hidden" name="_gotcha" style="display: none !important" />
    
    <p v-if="status === 'error'" class="error">{{ errorMessage }}</p>
    <p v-if="status === 'success'" class="success">Message sent!</p>
    
    <button type="submit" :disabled="status === 'loading'">
      {{ status === 'loading' ? 'Sending...' : 'Send' }}
    </button>
  </form>
</template>
```

### Node.js (Server-side)

When building forms programmatically on the server, include the honeypot field:

```js
import express from 'express';
import { Forminit } from 'forminit';

const app = express();
app.use(express.urlencoded({ extended: true }));

const forminit = new Forminit({
  apiKey: process.env.FORMINIT_API_KEY,
});

const FORM_ID = 'YOUR_FORM_ID';

app.post('/submit', async (req, res) => {
  const formData = new FormData();
  
  // Add form fields
  formData.append('fi-sender-firstName', req.body.firstName);
  formData.append('fi-sender-lastName', req.body.lastName);
  formData.append('fi-sender-email', req.body.email);
  formData.append('fi-text-message', req.body.message);
  
  if (req.body._gotcha) {
    formData.append('_gotcha', req.body._gotcha);
  }
  
  const { data, error } = await forminit.submit(FORM_ID, formData);
  
  if (error) {
    return res.status(400).json({ success: false, message: error.message });
  }
  
  res.json({ success: true, submissionId: data.hashId });
});

app.listen(3000);
```

---

## Combining with Other Protection

For maximum spam protection, combine honeypot with other methods:

| Method | Best For | User Impact |
|--------|----------|-------------|
| **Honeypot** | Basic bot protection | None (invisible) |
| **reCAPTCHA** | Advanced bot protection | Low (invisible v3) to Medium (checkbox) |
| **hCaptcha** | Privacy-focused protection | Medium (requires interaction) |
| **Rate Limiting** | Preventing abuse | None (automatic) |

Example combining honeypot with reCAPTCHA:

```html
<form id="contact-form">
  <input type="text" name="fi-sender-firstName" placeholder="First name" required />
  <input type="email" name="fi-sender-email" placeholder="Email" required />
  <textarea name="fi-text-message" placeholder="Message" required></textarea>
  
  <!-- Honeypot -->
  <input type="hidden" name="_gotcha" style="display:none !important" />
  
  <!-- reCAPTCHA -->
  <div class="g-recaptcha" data-sitekey="YOUR_SITE_KEY"></div>
  
  <button type="submit">Send</button>
</form>
```

---

## Common Issues

### Submissions incorrectly flagged as spam

If legitimate submissions are being blocked:

1. **Check for autofill** — Some password managers or browser extensions might fill hidden fields
2. **Verify the field is hidden** — Ensure both `type="hidden"` and `style="display:none"` are set
3. **Check for default values** — Make sure the honeypot field has no value attribute

### Bots bypassing honeypot

Sophisticated bots may avoid honeypot fields. Consider:

1. **Use a custom field name** — Change from the default `_gotcha` to something less obvious
2. **Add reCAPTCHA or hCaptcha** — Combine honeypot with CAPTCHA for stronger protection
3. **Use CSS hiding** — Some bots only check for `type="hidden"`, not CSS visibility

### Field not working

Verify your implementation:

```html
<!-- ✅ Correct -->
<input type="hidden" name="_gotcha" style="display:none !important" />

<!-- ❌ Wrong - has fi- prefix -->
<input type="hidden" name="fi-_gotcha" style="display:none !important" />

<!-- ❌ Wrong - has a value -->
<input type="hidden" name="_gotcha" value="test" style="display:none !important" />

<!-- ❌ Wrong - missing style -->
<input type="hidden" name="_gotcha" />
```

---

## Related Documentation

- [Cloudflare Turnstile Integration](https://forminit.com/docs/cloudflare-turnstile/) — Privacy-first CAPTCHA alternative
- [reCAPTCHA Integration](https://forminit.com/docs/recaptcha/) — Google reCAPTCHA setup
- [hCaptcha Integration](https://forminit.com/docs/hcaptcha/) — Privacy-focused CAPTCHA
- [Form Blocks Reference](https://forminit.com/docs/form-blocks/) — Complete reference for all field types
- [HTML Integration](https://forminit.com/docs/html/) — Static site setup guide
