Honeypot not stopping spam bots? Why, and what to add
Updated
A hidden honeypot field is a free way to catch simple spam bots. It does not stop a bot that drives a real browser and fills only the fields that a person sees. This page explains why, and what to add.
Where a honeypot alone is enough
A honeypot is free, runs on your own server and sends nothing to anyone. Scripts that post every field of a form fill the honeypot too, so your server catches them. If you have a small contact form with spam from simple scripts, a honeypot can be enough. Try a honeypot first. If you still get spam, add Bot403.
Where Bot403 is better
A script that drives a headless browser can skip the hidden fields and fill only the fields that a person sees. Playwright, a common tool for this, waits until a field is visible before it fills it. A field with display:none does not count as visible. As a result, the hidden field stays empty, and your server accepts the spam. A proof of work has no field to skip: each submission costs CPU time in the browser, also in a headless browser. Bot403 also adds a honeypot field (default name _website), so you keep the free check and add the costly one.
Side by side
The facts come from the Playwright documentation (https://playwright.dev/docs/actionability), checked on 2026-10-23. "Not stated" means the page does not say. If something changed, email me. Then I will correct it.
| Capability | Bot403 | Honeypot |
|---|---|---|
| Price | free for 5,000 a month, then €3 a month | free |
| Setup | one script tag and one API call | one hidden field and one check on your server |
| Catches scripts that fill every field | yes, with its own honeypot field | yes |
| Cost for a bot that skips hidden fields | CPU time for each submission | none |
| What visitors see | nothing | nothing |
| Data sent to a third party | the challenge and the verify call go to Bot403 | none |
Switch in 10 minutes
If you want, keep your own honeypot. Add one script tag with your public key. The script adds the token and its own honeypot field to each form. On the server, post the form to /api/v1/verify before you accept it. The answer is ok, or a reason such as honeypot. The verify page has the request for Node.js, Bun, Deno, Hono, Next.js, Cloudflare Workers, PHP, Python, Go and Ruby. The form fields stay as they are.