Score bot traffic
Tell scripted traffic from real visitors without a puzzle for everyone: a request sent by the curl command-line tool scores 60 and is marked as likely automated, and you decide what that score triggers. Pay per use, no subscription.
Run it online
Run this on our servers with your account. Free tools run in your browser; this one bills your KIT balance per the price above.
how likely a request is automated
Why bots are hard to tell apart
A form submission, a login attempt or a comment never announces whether a person or a script sent it. Any page reachable from the open internet will sooner or later receive traffic from scripts, headless browsers and scraping tools alongside real visitors. Blocking the obvious bots is the easy part. The hard part is separating the ones that look almost human from people who simply browse or type a little unusually, on a slow connection, an unfamiliar device or with assistive technology. If every visit is handled the same way, either the bots get in or real people face hurdles they never needed. As these tools learned to imitate real browsers, simple checks on how a browser names itself stopped being enough.
How to use the score
The score says how likely it is that a program rather than a person sent it, judging by clues the visit itself carries: whether its details fit together, how it connects and habits typical of scripted visits. It is a probability, not a certainty, so let it feed your decision rather than make it alone. Typical uses are silently dropping likely spam from contact and signup forms, asking for an extra verification step only on suspicious logins, flagging rapid repeated checkout attempts during limited product launches, and filtering likely bot-written reviews before moderation.
Why scoring beats a binary yes or no
A flat bot-or-not answer forces you into one rigid policy for every case, but a score lets you set different thresholds for different stakes: a low-value newsletter signup can tolerate a looser threshold than a password reset or a checkout attempt. That flexibility to tune per use case is really the entire point of returning a score instead of a fixed label.
What you can do with it
Form spam reduction
Score contact and signup form submissions to silently drop likely-automated spam without adding a visible CAPTCHA for everyone.
Login protection
Add step-up verification only to login attempts that score as likely automated, keeping the flow frictionless for real users.
Scalper and inventory bot defense
Flag high-speed, repetitive checkout attempts that score as automated during limited-stock product launches.
Review and comment quality
Filter out likely bot-generated reviews or comments before they reach moderation queues.
FAQ
What score counts as a bot?
There's no universal cutoff — the score is a probability, and the right threshold depends on how much risk a given action can tolerate, from loose for low-value forms to strict for logins or checkout.
Does it guarantee catching every bot?
No detection method catches everything; sophisticated automation that closely mimics real behavior can still score low, which is why the score is meant to complement other defenses, not replace them.
Is it free to use?
There's no free tier — free tiers get abused and slow everyone down. No subscription, no tokens, no invented credits, and a failed task is never charged.
Is request data kept after scoring?
No, it's deleted after the retention period and never used to train anything, and failed requests are retried up to three times and never billed.
Why get a score instead of a simple bot-or-human answer?
A score lets you set a different threshold for each risk. A newsletter signup can accept a looser limit than a password reset or a checkout attempt, while a fixed label would force one rule on all of them.
Related tools
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/verify/bot-score \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"user_agent":"curl/8.0"}'const res = await fetch("https://api.kit.forhosting.com/verify/bot-score", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"user_agent": "curl/8.0"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/verify/bot-score",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"user_agent": "curl/8.0"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/verify/bot-score", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"user_agent":"curl/8.0"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"user_agent":"curl/8.0"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/verify/bot-score", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"user_agent": "curl/8.0"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "verify.bot_score",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
Technical notes
A form submission, a login attempt or a comment doesn't announce whether a human or a script sent it, and treating every request the same way either lets bots through or annoys real people with friction they didn't need. This endpoint scores the likelihood that a given request came from automation, so you can decide what happens next.
The question every open endpoint eventually has to answer
The hard part isn't blocking the obvious bots — it's telling apart the ones that look almost human from the people who genuinely browse or type a little unusually, on a slow connection, an unfamiliar device, or through assistive technology that behaves differently from a default browser. Any form, API or login page that's reachable from the open internet will eventually receive traffic from scripts, headless browsers and scraping tools alongside real visitors.
What the score represents
The endpoint returns a numeric score reflecting how likely the request is to be automated, based on signals available in the request itself — things like header consistency, connection characteristics and patterns associated with scripted traffic versus a typical browser session. It's a probability, not a certainty, and it's deliberately designed to feed a decision your system makes, not to be the decision entirely by itself.
An arms race that automation made necessary
As scraping and credential-stuffing tools got better at mimicking real browser behavior over the years, simple checks like user-agent strings stopped being enough on their own, which is why scoring based on multiple request-level signals became the more durable approach — no single signal tells the whole story, but combined together they're substantially harder to fake convincingly.
Fitting it into your flow
Most integrations call it inline at the moment of submission and route the response into existing rate-limiting or verification logic rather than replacing that logic outright. Submit the request context, get a task_id back immediately, and receive the score through your signed webhook or a signed link valid for 24 hours, whichever fits how your system is built.
Technical questions
How does this bot detection api generate its score?
It evaluates signals present in the request itself, such as header and connection consistency and patterns typical of scripted traffic, and returns a numeric score reflecting how likely the request is automated.
Is a bot score the same as a CAPTCHA?
No. A CAPTCHA interrupts the user to prove they're human; this endpoint scores a request silently in the background, letting you decide whether to add friction only when the score warrants it.
Can I score requests in bulk?
Each call scores one request; for high traffic, send a request per event and let the asynchronous model handle throughput in parallel.
How quickly do I get the score?
A task_id returns immediately, and the score arrives via your signed webhook or a signed link valid for 24 hours.