splitforms.com
All articles/ SPAM & SECURITY9 MIN READPublished May 21, 2026

How to Stop Direct-to-API Contact Form Spam

Bots can skip your webpage and POST straight to your form endpoint. Here is the server-side protection stack that actually stops direct-to-API form spam.

✶ Written by
splitforms.com / blog

Founder of splitforms — the form backend API for developers. Writes about form UX, anti-spam, and shipping web apps without backend code.

Why direct-to-API spam happens

Browser-side protection only works if the attacker loads the browser. Many form bots do not. They scrape your HTML once, extract the endpoint and access key, then send raw POST requests from scripts. That bypasses frontend reCAPTCHA widgets, JavaScript timers, and any hidden fields that are only checked in client code.

For a form backend, the submission endpoint is the security boundary. The endpoint must read the current form settings and decide whether the submission deserves delivery.

The server-side gate order

  1. Method and content type. Accept POST with JSON, urlencoded, or multipart only.
  2. IP rate limit. Start with 5 submissions per 60 seconds per IP.
  3. Origin allow-list. If domains are configured, require Origin or Referer to match the root domain or subdomain.
  4. Honeypot validation. Check fields like botcheck, website, and confirm_email on the server.
  5. Time trap. Reject submissions sent too quickly after page load or absurdly late.
  6. Optional CAPTCHA verification. If a secret key exists, verify the token server-side with a timeout.

That is the exact shape we use in splitforms spam protection. Cheap checks run first, expensive network calls run last, and the delivery system only receives submissions that pass every enabled gate.

Origin checks are opt-in for a reason

An origin allow-list is powerful, but it needs to be settings-driven. If a user has not configured allowed domains, do not block the form. Once they add example.com, enforcement should begin on the very next request.

The matching rule should be exact host or subdomain only. www.example.com should match example.com, but example.com.evil.test must not.

Why silent drops beat error messages

Returning 403, 429, or “honeypot failed” teaches the attacker which part to change. For spam gates, a benign200 { success: true } response is safer. The bot thinks the payload worked and keeps sending the same junk, while the backend simply does not deliver it.

What this means for WordPress forms

WordPress sites are frequent targets because bots know the common plugin endpoints. If you use a hosted form backend, lock the form to your domain, keep the honeypot enabled, and verify the direct download plugin or shortcode still includes a form_loaded_at field. See the WordPress setup page.

How to detect direct-to-API spam

Before you can stop direct-to-API spam, you need to know what it looks like in your logs. Legitimate users load your page, interact with JavaScript, and submit through a rendered form. Bots skip all of that.

Watch for these request fingerprints in your submission logs:

  • No Origin or Referer header. A browser always sends one or both. A scripted POST request often sends neither.
  • User-Agent is curl, wget, python-requests, or blank. Real visitors have a full browser UA string. Raw HTTP clients expose themselves immediately.
  • Submission arrives in under 1 second of page render. A human cannot fill a form that fast. If the time between page load and submission is less than 3 seconds, it is almost always a bot.
  • Same payload across different form IDs. If the same email, name, and message body arrive at five different form endpoints, a scraper extracted the access keys and is replaying payloads.
  • Payload contains SEO spam links. URLs to pharmaceutical, gambling, or adult sites embedded in the message body are a clear fingerprint of link-spam bots.
  • Multipart boundary is missing or malformed. Bots that construct raw POST bodies sometimes mess up the encoding format, producing payloads that a browser would never generate.

The key signal is the combination. A missing Origin is suspicious on its own, but combined with a 0.2-second submission time and a known bot User-Agent, it is conclusive. That is why the gate order matters: check the cheap signals first, then escalate.

Code example: rate limiting middleware

A per-IP rate limit is the single most effective gate against direct-to-API spam. Here is a minimal Node.js implementation using an in-memory map that works for a single server or serverless function warm instance:

const ipCounts = new Map<string, { count: number; resetAt: number }>();

function rateLimit(ip: string, maxRequests = 5, windowMs = 60_000): boolean {
  const now = Date.now();
  const entry = ipCounts.get(ip);

  if (!entry || now > entry.resetAt) {
    ipCounts.set(ip, { count: 1, resetAt: now + windowMs });
    return false; // allowed
  }

  entry.count++;
  return entry.count > maxRequests; // true = blocked
}

// usage in your submit handler
app.post("/api/submit", (req, res) => {
  const ip = req.headers["x-forwarded-for"] || req.socket.remoteAddress;
  if (rateLimit(ip)) {
    return res.json({ success: true }); // silent drop
  }
  // continue processing...
});

For multi-region or serverless deployments, swap the Map for a Redis counter using the INCR + EXPIRE pattern, or use Upstash Redis which works natively at the edge. The rateLimit function returns false for allowed requests and true for blocked ones, so the caller decides whether to silently drop or return an error.

Which protection stops which bot type

No single gate blocks every bot. The table below maps common bot categories to the server-side checks that stop them:

Bot typeRate limitOrigin checkHoneypotTime trapCAPTCHA
Scraped-access-key spamYesYesNoPartialYes
Generic SEO link spamYesNoYesNoPartial
Low-volume human spammerNoNoPartialNoYes
Credential-stuffing botYesPartialNoPartialYes
AI-generated content spamNoNoPartialNoYes

The takeaway: rate limiting and honeypot together catch the majority of automated spam. CAPTCHA is the only reliable gate against low-volume human spammers and AI content, but it comes at a conversion cost. Honeypot vs reCAPTCHA covers the trade-off in detail.

FAQ

Why do bots POST directly to form APIs?

Because it is cheaper than loading a browser. Once a bot sees an endpoint and access key, it can replay POST requests without loading your page, JavaScript, honeypot script, or CAPTCHA widget.

Does a frontend honeypot stop direct-to-API spam?

Not by itself. The server must validate the honeypot field and drop submissions where it is filled. Anything that only runs in the browser can be bypassed by scripted POST requests.

Should failed spam checks return an error?

Usually no. For spam gates, a silent HTTP 200 response with a fake success body is better because it does not teach bots which check failed.

What is the strongest direct-to-API protection?

Use layered server-side checks: content type, IP rate limit, origin allow-list, honeypot validation, time trap, and optional server-verified CAPTCHA. No single gate is enough.

Want a ready-made implementation of all of this? Get a free access key — splitforms applies every gate on every submission by default. See also: how to stop contact form spam and AI form spam detection benchmarks.

About the author
✻ ✻ ✻

Get your free contact form API key in 60 seconds.

500 free form submissions per month. No credit card. No SDK, no PHP, no plugin. Drop one POST endpoint in your form and submissions land in your dashboard and can notify your inbox on every plan.

Generate access key →Read the docs
founders pricing locked in · early access open