Enterprise-grade spam and fraud protection for every website
The machine-learning screening big platforms build in-house, one URL away. Doorman stops pitches, bots, fake sign-ups, card testers and abuse in milliseconds, with no captcha.
Free for 1,000 checks a month. No card required. Try it on a message · Agent setup
Example: Doorman screening submissions from a contact form, a sign-up form, a checkout and a comment box, each judged in under 300 milliseconds and delivered or kept out with the sentence that decided it.
Works with the form you already have
- HTML
- React
- Next.js
- Webflow
- Framer
- WordPress
- Express
See it work in 26 seconds
A pitch arrives through a contact form, Doorman reads it and keeps it out, and your coding agent sets the whole thing up for you.
Transcript
- “Your contact form.” A message is typed into a contact form: “We do SEO and link building. Quick 15 min chat?” and sent.
- “It gets pitched all day.” The message arrives at Doorman’s door.
- “Doorman reads every one.” It is marked Dropped, sales pitch, with the giveaway sentence underlined. A real demo request is marked Delivered.
- “In 162 ms. Pitches, bots and fraud out.” Card fraud, abuse, fake sign-ups and bot spam are kept out; real customers go to the inbox.
- “Tell your coding agent.” A Copy prompt button for Claude Code, Codex, Cursor and OpenCode is clicked.
- “It sets everything up.” The agent is asked to protect the contact form with Doorman, reads withdoorman.com/llms.txt, changes the form’s action URL and confirms a test submission was delivered.
- “Enterprise-grade. Priced for everyone.” Free: 1,000 checks a month. Pro: $12 a month. No captcha, no sales call.
- Doorman. Spam protection for every website.
One service for spam, fraud and abuse
Every form on your site gets a different kind of junk. Doorman knows what each form is for and what you sell, and judges every submission against that.
Contact and demo forms
Agency and SEO pitches, partnership spam, template outreach and bots, kept out of your sales inbox.
leadSign-ups and waitlists
Fake and throwaway accounts, disposable emails and scripted bulk sign-ups, stopped before they cost you.
signupCheckout
Card testing and stolen-card patterns, judged from signals you already have, before you capture payment.
checkoutComments and reviews
Promotion, link spam, harassment, hate and threats, removed before anyone else reads them.
commentLet your coding agent set it up
Claude Code, Codex and Cursor can set Doorman up without a browser: there's a setup guide written for agents, a signup API and a remote MCP server. Your agent asks you one question.
Add Doorman spam protection to this project's forms. Follow /llms.txt. Ask me which email should receive real submissions.
claude mcp add --transport http doorman /mcp
Step-by-step guides:
› Add Doorman spam protection to this project's forms. Follow /llms.txt ✓ Read the setup guide ✓ Found 1 form: index.html "Get a quote" ? Which email should get real submissions? owner@brightpath.co ✓ Created account and form f_qXGl50Gng1 ✓ Pointed the form at Doorman, added d.js ✓ Saved DOORMAN_KEY to .env (gitignored) ✓ Test: café asking about payroll → delivered 0.86 ✓ Test: SEO pitch → dropped 0.01
Or do it yourself in two minutes
Keep your form, your fields and your thank-you page. Doorman sits between the submit button and your inbox.
Point your form at Doorman
Swap the action URL, or call one endpoint from your backend. Field names are detected automatically.
Our models score every submission
In about 160 ms, before the thank-you page loads: is this a real customer, a pitch, a bot, a fake account or fraud?
Real ones reach you
Forwarded to email, Slack or a signed webhook. The rest wait in your inbox, one click from rescue.
- <form action="/contact.php" method="POST">
+ <form action="/f/f_yourForm" method="POST">
<input name="email" type="email" required>
<textarea name="message"></textarea>
<button>Send</button>
</form>
<!-- optional: timing and honeypot signals -->
+ <script src="/d.js" defer></script>async function onSubmit(event) {
event.preventDefault();
await fetch("/f/f_yourForm", {
method: "POST",
body: new FormData(event.currentTarget),
headers: { Accept: "application/json" },
});
setSent(true); // everyone gets the same {"ok": true}
}curl /v1/check \
-H "Authorization: Bearer $DOORMAN_KEY" \
-H "Content-Type: application/json" \
-d '{"form": "f_yourForm", "email": "jess@brightline.co",
"message": "We send 200 invoices a month. Demo?"}'
# {"route": "deliver", "action": "deliver", "p_real": 0.97, ...}import { Doorman } from "doorman-client";
const doorman = new Doorman(process.env.DOORMAN_KEY);
const r = await doorman.check({ form: "f_yourForm", email, message });
if (r.action === "drop") return thanks(); // the bot learns nothing
await saveLead({ email, message, held: r.action === "hold" });import os
import requests
try:
r = requests.post(
"/v1/check",
headers={"Authorization": f"Bearer {os.environ['DOORMAN_KEY']}"},
json={"form": "f_yourForm", "email": email, "message": message},
timeout=5,
).json()
except requests.RequestException:
r = {"action": "hold"} # never lose a lead
if r["action"] != "drop":
save_lead(email, message, held=r["action"] == "hold")require "net/http"
require "json"
res = Net::HTTP.post(
URI("/v1/check"),
{ form: "f_yourForm", email: email, message: message }.to_json,
"Authorization" => "Bearer #{ENV.fetch("DOORMAN_KEY")}",
"Content-Type" => "application/json"
)
r = JSON.parse(res.body)
save_lead(email, message, held: r["action"] == "hold") unless r["action"] == "drop"# {:req, "~> 0.5"}
{:ok, %{body: r}} =
Req.post("/v1/check",
auth: {:bearer, System.fetch_env!("DOORMAN_KEY")},
json: %{form: "f_yourForm", email: email, message: message},
receive_timeout: 5_000
)
unless r["action"] == "drop" do
save_lead(email, message, held: r["action"] == "hold")
endEvery drop comes with a reason
Rules and word lists match keywords. Doorman's models read the whole submission against what you sell, and show you the exact sentence that gave it away.
- Catches what captchas can't. A person paid to paste agency pitches passes any challenge. Doorman judges what they wrote.
- Rescue in one click. Nothing is deleted. If a real lead gets dropped, deliver it from the inbox and it's forwarded instantly.
- Unsure means held, not dropped. Borderline messages are forwarded with a flag so a person decides.

Try it on a real message
Paste something from your inbox, or pick an example. We'll judge it as if you sell invoicing software (or, for the comment, run a developer blog). Nothing is stored.
Enterprise-grade accuracy, at a price anyone can pay
Small, specialised models answer each question in milliseconds for a fraction of a cent. That's why every plan, including the free one, gets the same protection.
Test set: 104 invented but labelled submissions to a fictional invoicing company's demo form and checkout (13/13 agency pitches, 11/11 bots and 16/16 fraudulent orders dropped; 45 of 52 genuine delivered straight through, 7 held for a person), judged live. Benchmark: the UCI YouTube Spam Collection, recall 0.980, 8.8% held for a person. Sign-ups and comments: a small hand-labelled set of 25 (fake accounts, abuse, spam and genuine ones), none on the wrong side. Questions were not tuned to any of these sets.
The protection big platforms have, without the enterprise contract
Until now you could buy machine-learning fraud screening after a sales call and an integration project, or settle for captchas and word lists that miss anything a person typed.
| Question | Doorman | Enterprise fraud platform | Captcha | Honeypot + word list |
|---|---|---|---|---|
| Price | Free, then from $12 a month | Usually an annual contract | Free or low | Free |
| Getting started | One URL, or one sentence to your agent | Sales call and integration | A script and a server check | A few lines of code |
| What real visitors see | Nothing | Nothing | A challenge, sometimes | Nothing |
| Human-written pitches and abuse | Reads intent | Depends on the product | Passes | Only known phrases |
| Card testing and fake accounts | Yes | Yes | Slows it | No |
| Why it blocked something | The exact sentence | A risk score | No | No |
Built so nothing real gets lost
Fails open
Over quota, an outage or a flood from one address: submissions are held for a person, never silently dropped.
Watch mode
Judges everything but delivers what it would have dropped, tagged. Check its calls on your real traffic first.
Email, Slack, webhooks
Signed JSON webhooks, retried after 1 minute, 5 minutes, 30 minutes, 2 hours and 12 hours.
Allow and block lists
Emails or domains that are always delivered, or always dropped, without a check.
Checkout screening
Card testing and stolen-card patterns, judged from signals you already have: attempts, countries, account age.
Bots learn nothing
Delivered or dropped, the sender gets the same redirect and the same response. There's nothing to probe.
Simple pricing
Every plan gets the same models. You pay for volume, not for a sales process. Test submissions are free.
Free
For side projects and trying it on a real form.
- 1,000 checks a month
- 300 email forwards; Slack and webhooks unlimited
- API, MCP and agent setup
- 30 days of history
Pro
For a business site with a busy contact or demo form.
- 25,000 checks a month
- 5,000 email forwards
- Everything in Free
- 180 days of history
Business
For agencies and sites with many forms.
- 250,000 checks a month
- 20,000 email forwards
- Everything in Pro
- 365 days of history
Go over your plan and nothing is dropped: submissions are held and forwarded with a flag until the month resets. Confirm your email to unlock the free plan; forwarding addresses other than your own confirm once.
Frequently asked questions
How is this different from a captcha?
A captcha asks every visitor to prove they are human. Doorman lets everyone submit and then reads what they sent. A person paid to paste agency pitches passes any captcha; Doorman judges the message itself against what your business sells.
What does my agent need?
Nothing special. Any coding agent that can make an HTTP request can follow /llms.txt: it creates your account with POST /v1/signup (no browser), puts the form URL or an API call into your project, stores the key in .env and runs two free test submissions. Agents that support MCP can add the remote server at /mcp instead. The only thing it asks you is which email should receive real submissions.
What happens if Doorman is down?
If judging fails or times out, the submission is held: stored, forwarded to you flagged as held, and queued for review. The same happens over your monthly quota. Doorman never drops something it did not judge. If you call the API from your backend, the doorman-client package treats a network error or timeout as hold. If the hosted form endpoint itself cannot be reached, the visitor's form post fails the way it would with any form backend.
Is my data used for training?
No. Submissions are sent to our machine-learning provider only to be judged. We don't use them for training. We keep submissions for 30 days on Free, 180 days on Pro and 365 days on Business, then delete them automatically.
What data do you store?
For each submission: the fields your form sent, the sender's IP address, the decision (route, probability it is real, reason and evidence sentence) and where it was forwarded. File uploads are ignored. Passwords are hashed; API keys and session tokens are stored only as hashes.
Does a bot find out it was dropped?
No. Every submission gets the same response whatever the verdict: the same redirect to your thank-you page, or the same {"ok": true} for JSON requests.
Can I start without trusting it?
Yes. Watch mode judges everything but delivers what it would have dropped, tagged, so you can check its calls on real traffic. Thresholds are per form, and allow and block lists let you always deliver or always drop specific emails or domains.
Does it work in other languages?
Doorman's models judge meaning, not keywords, and Doorman's questions say that a short, badly written or non-English message is still genuine. Our published benchmark is English, so if most of your traffic is in another language, start in watch mode.
What kinds of forms does it handle?
Contact, demo and quote forms; sign-ups and waitlists; public comments; and checkouts, where card testing and stolen cards are judged from signals you pass such as payment attempts and card versus IP country.
How can protection this good cost so little?
Doorman uses small, specialised models that answer narrow questions (is this a real customer, is this a pitch, is this card testing) in milliseconds. Each check costs a tiny fraction of a cent to run, so we can give every plan the same models, including the free one, and charge for volume instead of for a sales process.
What happens if I go over my plan?
Nothing is dropped. Submissions over the monthly quota are held and forwarded unjudged, flagged as held, until the month resets or you upgrade. You get an email at 80% and at 100%.
Protection that used to need a fraud team
Set up in two minutes, or with one sentence to your coding agent. Free for your first 1,000 checks every month.
Get started free
