Parse a user agent
A raw user agent string is dense, inconsistent across vendors, and changes shape every browser release, which makes hand-written parsing rules go stale fast. This user agent parser api breaks any UA string into browser, engine, operating system, device type and a bot classification, so your logs and analytics stop guessing.
Run — free
Runs in your browser. Free, unlimited — your data never leaves this page.
Why the string itself is such a mess
The user agent header has never followed a strict specification, it evolved as a chain of browsers pretending to be other browsers for compatibility reasons dating back to the 1990s browser wars. That's why a modern Chrome UA string still contains the word 'Mozilla' and often 'like Gecko' and 'Safari' even though it's neither. Parsing it correctly means knowing that history, not just splitting on spaces, which is why naive regex approaches break the moment a new browser version or a new device line ships.
What POST /verify/user-agent returns
Send the raw UA string and the task extracts the browser family and version, the rendering engine, the operating system and its version, the device type (desktop, mobile, tablet, or unrecognized), and a classification flag indicating whether the string matches a known automated client, crawler or bot pattern. You get structured fields instead of a string you'd otherwise have to reverse-engineer yourself.
Who actually needs this
Analytics teams tired of 'unknown device' buckets skewing their dashboards, ad platforms that need to separate human traffic from crawler traffic before billing a client, and support teams trying to reproduce a bug reported against a specific browser version all rely on the same underlying task: turning an opaque string into something queryable. It's a small piece of infrastructure that quietly sits behind a surprising amount of decision-making.
How it slots into an existing pipeline
Because every call is asynchronous, you can log raw UA strings as they arrive and parse them in a batch afterward rather than on the request's critical path, or submit them one at a time if you need the classification before deciding how to respond. Results come back through a signed webhook or a signed link valid for 24 hours, and nothing you send is retained past the stated retention window or used to train anything.
Where the limits are
A user agent string can be spoofed, so bot detection based on it alone is a signal, not a guarantee. Sophisticated automated traffic can present a legitimate-looking UA, which is exactly why this endpoint is best used as one layer among several, not the sole gate for anything security-critical.
What you can do with it
Analytics dashboard cleanup
Replace 'unknown browser' and 'unknown device' buckets with structured, accurate breakdowns pulled straight from raw request logs.
Bot traffic segregation
Flag requests matching known crawler and automated-client patterns before they're counted as human sessions in a reporting pipeline.
Bug reproduction support
Turn a customer's pasted user agent string into a clear browser version and OS so a support engineer can reproduce the exact environment.
Device-targeted content decisions
Classify incoming traffic by device type in bulk to decide which historical requests should have received a mobile-optimized response.
FAQ
What exactly does this user agent parser api extract?
Browser family and version, rendering engine, operating system and version, device type, and a bot or automated-client classification, all from a single raw UA string.
Can it detect bots and crawlers?
It flags strings that match known bot and crawler patterns, but since a user agent header can be spoofed, treat it as one signal among several rather than definitive proof.
Does it support unusual or outdated browsers?
It parses the wide range of browser, OS and device patterns in active and historical use, though a truly novel or malformed string may return a partial or unrecognized classification.
Is there a free tier?
The tool above runs free in your browser. The API is paid — each call draws from your prepaid ForHosting KIT balance: top up from $10.00 (it never expires), pay each request's published price, and a call with no balance returns HTTP 402. No subscription, no tokens, and a failed task is never charged.
What's the price per parse?
$0.002 per request, charged only for tasks that complete successfully.
Can I parse user agent strings in bulk?
Yes, since parsing runs asynchronously, you can submit large batches from stored logs without blocking anything on your end.
How do results come back?
POST /verify/user-agent returns a task_id immediately, and the parsed result is delivered via signed webhook or a signed link valid for 24 hours.
What happens to the UA strings I submit?
They're deleted after the stated retention period and are never used to train any model.
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, and soon from our app, email and Telegram.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/verify/user-agent \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"items":["valor-1","valor-2"]}'const res = await fetch("https://api.kit.forhosting.com/verify/user-agent", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"items": [
"valor-1",
"valor-2"
]
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/verify/user-agent",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"items": [
"valor-1",
"valor-2"
]
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/verify/user-agent", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"items":["valor-1","valor-2"]}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"items":["valor-1","valor-2"]}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/verify/user-agent", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"items": [
"valor-1",
"valor-2"
]
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "verify.user_agent",
"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. |