Bot detection API
Customers in, bots out
Before a login, a sign-up, a checkout or any page bots go after, your server asks Bot Protection about the visitor and gets back a class, a score and the reasons. No proxy in front of your site, no puzzles for your customers.
14-day free trial · plans from $29 a month
# Ask before the protected action curl -X POST https://korzen.dev/v1/decide \ -H "Authorization: Bearer $KORZEN_API_KEY" \ -d '{ "ip": "203.0.113.10", "user_agent": "Mozilla/5.0 …", "token": "<_kz cookie>", "path": "/checkout" }'
// Ask before the protected action; let through on any error const d = await fetch(API + "/v1/decide", { method: "POST", headers: { Authorization: `Bearer ${KEY}` }, body: JSON.stringify({ ip, user_agent, token, path }), signal: AbortSignal.timeout(200), }).then((r) => r.json()).catch(() => null); if (d?.action === "block") return res.status(403).end();
# Ask before the protected action; let through on any error try: d = requests.post(API + "/v1/decide", headers={"Authorization": f"Bearer {KEY}"}, json={"ip": ip, "user_agent": ua, "token": token}, timeout=0.2).json() except requests.RequestException: d = {} if d.get("action") == "block": abort(403)
// Ask before the protected action; let through on any error c := &http.Client{Timeout: 200 * time.Millisecond} r, _ := http.NewRequest("POST", api+"/v1/decide", body) r.Header.Set("Authorization", "Bearer "+key) var d struct{ Action string } if res, err := c.Do(r); err == nil { json.NewDecoder(res.Body).Decode(&d) res.Body.Close() } if d.Action == "block" { http.Error(w, "try again later", 403) return }
// Ask before the protected action; let through on any error var req = HttpRequest .newBuilder(URI.create(API + "/v1/decide")) .header("Authorization", "Bearer " + KEY) .timeout(Duration.ofMillis(200)) .POST(BodyPublishers.ofString(json)).build(); String act = ""; try { var res = http.send(req, BodyHandlers.ofString()); act = mapper.readTree(res.body()) .path("action").asText(); } catch (Exception e) { /* let through */ } if (act.equals("block")) { response.sendError(403); return; }
// Ask before the protected action; let through on any error
$ch = curl_init(API . '/v1/decide');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($visitor),
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . KEY],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT_MS => 200,
]);
$d = json_decode(curl_exec($ch) ?: '{}', true);
if (($d['action'] ?? '') === 'block') {
http_response_code(403);
exit;
}
// Ask before the protected action; let through on any error // http: an HttpClient with "Authorization: Bearer KEY" var act = ""; try { using var cts = new CancellationTokenSource(200); var res = await http.PostAsJsonAsync( Api + "/v1/decide", visitor, cts.Token); var d = await res.Content .ReadFromJsonAsync<JsonElement>(cts.Token); act = d.GetProperty("action").GetString(); } catch { /* let through */ } if (act == "block") return Results.StatusCode(403);
200 OK RESPONSE
{
"request_id": "AQEAmJ3…",
"class": "bot_high",
"bot_score": 96,
"human_score": 0,
"reasons": ["behaviour", "inconsistency"],
"rules": [],
"step_up": false,
"action": "block",
"intended_action": "block",
"mode": "block",
"challenge": null,
"token_required": false,
"seen_before": 0,
"crawler": null
}What Bot Protection decides about you
Ask it about this browser, now: it runs its tag on this page and answers what your server would get, the class, the score and the reasons.
Only when you ask. The decision is kept as any other is, as the privacy policy says. Privacy
What it stops
The attacks Bot Protection is built for, at the step each one goes after.
- Sign-up Fake accounts and free-trial abuse Scripts that open accounts by the hundred for credits, promotions, trials or spam: new account fraud. Read →
- Login Credential stuffing and account takeover Leaked email and password pairs replayed against your login until some work. Read →
- Checkout Card testing Small payments with stolen cards, to find which still work before they are sold. Read →
- Any page Scraping and scalping Prices, content and limited stock taken by automation, faster than any person. Read →
Measured, not promised
The dashboard
See every decision, and why
The dashboard your team opens when traffic spikes: what Bot Protection answered, hour by hour, and the rules behind each answer.
Every answer, with its reasons
The latest decisions, newest first, refreshed every few seconds. Filter by class, path, country, reason or time, and see each rule that fired. Hover a reason to read what it means.
How it works
Two pieces of code. No change to your traffic
Add the tag
A small script in your pages sends what the browser shows about itself straight to Bot Protection and keeps a signed token in a first-party cookie.
<script src="…/v1/tag.js" data-site-key="sk_…" async></script>
Ask before the action
Before a login, a sign-up, a checkout or any page bots go after, your server sends the request's IP, User-Agent and token, with a short timeout.
POST /v1/decide {"ip": "…", "user_agent": "…", "token": "…", "path": "/checkout"}
Apply the action
Each answer says allow, challenge or block. You start in monitor mode, where it is always allow, and turn on block mode when you trust it. On any error or timeout, let the visitor through.
if d.Action == "block" { return http.StatusForbidden }
Or paste one prompt into Claude Code, Codex or Cursor and let it add both: set up with AI.
Guides for Next.js, Express, Django, Rails, Laravel, Spring Boot, ASP.NET Core, Cloudflare Workers and more, in the docs.
The answer
A class you can act on, not a number to guess at
A person, with proof from outside the session: a past order, their own card.
allowA person your own feedback vouched for.
allowNot enough evidence either way. Most first visits land here.
allowAutomation, from what the client does.
challengeAutomation, with strong evidence of behaviour.
blockWhen strong evidence points both ways, the answer says step_up: ask for a passkey or 3-D Secure, not a CAPTCHA.
What Bot Protection reads
Evidence a bot cannot fake for long
Consistency
Does the User-Agent match the client hints, the platform, the Web Worker, the GPU? A patched browser contradicts itself.
Real input
Which kinds of input the page saw: mouse, keys, touch, wheel. Scripts click without ever moving.
The network
Datacenters, a time zone far from the IP, a round trip that betrays a proxy hop.
Farms
One device behind many networks, one token on many exits, one fingerprint across sessions: groups a farm cannot avoid.
Behaviour over time
Robotic cadence, retries through refusals, requests that never load a page. Ten minutes of memory per visitor.
Your feedback
Tell Bot Protection about a completed order or a chargeback. Proof from outside the session is what makes a visitor human.
Why an API
Protection without a new point of failure
| Bot Protection | CAPTCHA | Proxy in front of your site | |
|---|---|---|---|
| Your visitors solve puzzles | Never | Every time | Sometimes |
| Your traffic goes through it | No | No, but every form waits on it | All of it |
| When it is down | Visitors go through | Forms stop | Your site stops |
| Tells you why | The class, the score and the kind of evidence | Pass or fail | A score |
| Where you decide | In your code | In their widget | In their rules |
Questions
Before you ask
Will real customers be blocked?
Being on a VPN, a mobile network or a shared office connection can raise the score but never alone reaches bot. bot needs evidence of automation in what the client does. Customers who have bought from you before come back as human high.
Does Bot Protection store personal data?
Identifiers are hashed with a key per customer that rotates every day, so they cannot be joined across customers or days. Behaviour is forgotten after ten minutes; only counts and the latest decisions are kept for your dashboard.
Does a blocked bot still see my site?
Yes. Bot Protection judges the actions your server asks about, such as a sign-up, a login or a checkout, not page loads. A bot still loads your pages in block mode; what your server refuses is the action.
Your site, without the bots
Create an account, copy two snippets, and watch the decisions arrive.