NNeXsoft
EngineeringVercelAI

BotID gegen AI-Budget-Abuse

Wie wir unseren öffentlichen AI-Chat vor automatisierten Budget-Drain-Angriffen schützen — ohne CAPTCHA und ohne UX-Reibung.

27. Mai 2026·7 min Lesezeit

Jeder POST gegen unseren /api/chat kostet uns Geld — er löst eine billable streamText()-Call gegen das Vercel AI Gateway aus. Ohne Schutz reicht ein simples Bash-Script und ein Stündchen Wartezeit, um $50 Cloud-Budget zu verbrennen. Hier ist, wie wir das gelöst haben.

Das Problem

Unser AI-Chat-Widget steht öffentlich auf der Website. Der Use-Case ist klar: ein:e Besucher:in fragt „passt Ihr Pricing zu meinem Projekt?", das Modell antwortet mit Vorschlägen, das Lead kommt qualifiziert. Funktioniert.

Das Problem: der Endpoint ist öffentlich. Jede:r kann posten. Im Sommer hatten wir einen Test-Lauf mit einem Bot-Script, der 1000 Anfragen in 10 Minuten geschickt hat — Resultat: $8 AI-Cost in einer Stunde, alles Müll-Anfragen. Bei einer Dauerwelle wären das pro Tag dreistellig.

Was wir zuerst probiert haben

Rate Limits per IP

Klassisch: pro IP nur N Requests in T Sekunden. Funktioniert für naive Bots, scheitert bei distributed Botnets. Ein billiges Residential-Proxy-Subscription kostet $20/Monat und liefert tausende rotierende IPs. Die Ökonomie ist gegen uns.

Honeypot Field

Ein verstecktes Form-Feld, das echte User nie ausfüllen. Manche Scraper schon. Hilft gegen die Hälfte der naiven Bots, gegen Headless-Chrome aber gar nicht.

reCAPTCHA / hCaptcha

Funktioniert, aber: jede:r echte User muss klicken. UX-Drop messbar. Und für DSGVO-Compliance mit US-CAPTCHA-Anbietern ist Auftragsverarbeitung notwendig. Wollten wir nicht.

Was wir gemacht haben: Vercel BotID

BotID ist Vercels Bot-Detection-Service, powered by Kasada. Drei Eigenschaften, die für uns entschieden haben:

  • Invisible: kein CAPTCHA, kein „I'm not a robot"-Klick. Erkennt anhand von Browser-Fingerprint + Interaction-Signals (Mouse-Movement-Pattern, Keyboard-Timing).
  • Dynamic: Detection-Methoden rotieren pro Page-Load. Macht Reverse-Engineering durch Angreifer extrem aufwendig.
  • EU-konform: Vercel als Auftragsverarbeiter mit AVV-Coverage.

Integration in 4 Schritten

1. Package installieren:

npm install botid

2. next.config.ts wrappen — das wired Middleware-Signals:

import { withBotId } from "botid/next/config";

const nextConfig: NextConfig = { /* … */ };
export default withBotId(nextConfig);

3. <BotIdClient> ins app/layout.tsx einbauen — das sammelt Client-Signals und attached sie an Fetches gegen die geschützten Routen:

import { BotIdClient } from "botid/client";

const PROTECT = [
  { path: "/api/chat", method: "POST" as const },
  { path: "/api/contact", method: "POST" as const },
];

export default function Layout({ children }) {
  return (
    <html>
      <body>
        <BotIdClient protect={PROTECT} />
        {children}
      </body>
    </html>
  );
}

4. Im Route-Handler checkBotId() aufrufen, vor jeglichem teuren Call:

import { checkBotId } from "botid/server";

export async function POST(req: Request) {
  const bot = await checkBotId();
  if (bot.isBot && !bot.bypassed) {
    return Response.json(
      { error: "rate_limited" },
      { status: 429 }
    );
  }

  // teurer streamText() Call läuft nur für Menschen
  const result = streamText({ model: "openai/gpt-5-mini", ... });
  return result.toUIMessageStreamResponse();
}

Wichtig: das richtige Verhalten bei Bot-Detection

Wir geben Bots 200 OK mit benigner JSON-Antwort oder 429 — nie 401/403. Wenn der Bot weiß dass er erkannt wurde, optimiert er. Wenn er denkt er kommt durch, ist's ihm schlicht egal — er bekommt nur keinen AI-Output.

Pretend success. Lassen Sie den Bot in den Sand laufen, statt ihm zu sagen, warum.

Was wir gelernt haben

Server-only Detection ist schwach

Wer nur checkBotId() aufruft ohne <BotIdClient> einzubauen, kriegt nur UA + Header-basierte Detection. Headless-Chrome mit gespoofter UA kommt da locker durch. Erst der Client-Layer macht's robust.

Listen geschützter Routen einmal pflegen

Zentral in app/layout.tsx. Wenn ein neuer expensive Endpoint dazukommt, in beiden Stellen ergänzen: BotIdClient.protect[] + checkBotId()-Call im Route-Handler.

Test mit echtem cURL

Nach Deploy: curl -X POST https://ihre-domain.example/api/chat -d '{...}' — sollte 429 zurückgeben (kein Browser-Signal vorhanden). Wenn da 200 mit AI-Antwort kommt, ist die Detection nicht aktiv.

Was es uns gekostet hat

BotID ist bei Vercel im Pro-Plan inkludiert (Deep-Analysis kostet extra für sehr hohe Volumes). Setup-Zeit: 20 Minuten. Wartung: null. Kein eigener Anti-Abuse-Code, kein CAPTCHA-Service, kein User-Friction.

Ergebnis auf dieser Website nach vier Wochen: die täglichen Gateway-Kosten liegen stabil im Cent-Bereich statt in unregelmäßigen Ausschlägen. Der eigentliche Gewinn ist aber nicht die Ersparnis, sondern dass der Endpunkt dauerhaft verteidigbar ist.

Wenn Ihr API-Endpoint pro Call mehr kostet als 0,1¢ und öffentlich ist, brauchen Sie Bot-Detection — vor dem ersten Missbrauch, nicht danach.

Fachbeiträge per E-Mail

Wie technische Entscheidungen zustande kommen — unregelmäßig und nur dann, wenn es etwas zu berichten gibt. Jederzeit abbestellbar. Sie erhalten zuerst eine Mail mit Bestätigungslink.

Hilft das Ihrem Vorhaben weiter?

Sprechen wir 30 Minuten darüber — konkret zu Ihrem Vorhaben.

NX
NeXsoft
Geschäftsleitung
Koblenz·Antwort < 24 h werktags
Direkt mit der Geschäftsleitung sprechen

Ohne Zwischenstationen. Sie sprechen direkt mit der Geschäftsleitung.

Wir hören Ihnen 30 Minuten zu, stellen ein paar gezielte Fragen und sagen Ihnen am Ende offen, ob — und wie — wir Ihnen helfen können. Wenn nicht, erhalten Sie mindestens zwei Empfehlungen, wer es könnte.

  • 30 Minuten, ohne Verkaufsgespräch
  • Konkrete Einschätzung Ihres Vorhabens
  • Klare Einordnung, welcher Projektrahmen passt
Lieber per Mail schreiben →