Detect bots and parse user agents, then combine every signal

The user agent is the client describing itself, which makes it useful and untrustworthy at once. Learn to read it, catch the bots that announce themselves, expose the ones that lie, and fold it all into one decision.

Here is an experiment worth running before you read anything else. Send the string Googlebot/2.1 (+http://www.google.com/bot.html) to a bot detector twice: once with the address 66.249.66.1, once with 185.220.101.1. Both calls report a known, trusted search engine crawler. Only one of them is Google. The first comes from Google's published crawler range and the detector marks it verified: true with a risk score of 0. The second comes from the Tor exit you met in lessons 2 and 3, and the same user agent earns verified: false, a risk score of 70 and a high risk level.

That is the whole lesson in miniature. A user agent is text the client chooses to send. Honest software uses it to describe itself; dishonest software uses it to describe whatever gets it through your door. You will learn to read it for what it is worth, catch the automation that does not bother to hide, verify the crawlers that claim to be someone important, and then put every signal from this course into one scoring function.

A user agent is a claim

The User-Agent header arrives with every HTTP request. Browsers fill it in; so do curl, Python's requests, headless Chrome, search engine crawlers and every scraping framework. Changing it is a single line of configuration in all of them, which gives you two populations to think about:

  • Clients that tell the truth. Real browsers, well-behaved crawlers, monitoring tools, libraries left on their defaults. For these the user agent is accurate and genuinely useful: analytics, compatibility decisions, spotting a script that someone forgot to disguise.
  • Clients that lie. Scrapers and fraud tools that copy a current Chrome string, or claim to be Googlebot because some sites wave Googlebot through.

So user agent analysis has a strange property: it is excellent at catching careless automation and nearly useless against careful automation. That is still worth a lot, since most abuse is careless. But it means a browser-looking user agent proves nothing, and a decision that rests on the user agent alone is one that a determined attacker controls.

Parse what the client claims

User Agent Parser (useragentparser) turns the string into structured fields. It is a POST with a ua field and costs 2 credits, the cheapest call in this course.

Try it liveUser Agent Parser2 credits
POSThttps://api.apiverve.com/v1/useragentparser
curl -X POST "https://api.apiverve.com/v1/useragentparser" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"ua":"Mozilla/5.0 (iPhone; CPU iPhone OS 17_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1"}'
Sign in or create a free account to run this with your own key.

browser.name is Mobile Safari, os is iOS 17.4, deviceType is mobile.

On every plan you get browser.name and browser.version, os.name and os.version, the device object (vendor, model, type when known), cpu, isMobile, isBot and deviceType, which is one of desktop, mobile, tablet, console, smarttv, wearable, embedded, xr or bot. Premium plans add browser.major, the engine name and version, and a human-readable summary such as Chrome 120 on Windows 10.

Two things in modern browser strings will catch you out if you read them literally.

Windows 11 says it is Windows 10. Browsers on Windows 11 still send Windows NT 10.0, so the parser reports os.version: "10" for both. There is no way to tell them apart from the user agent; browsers that support client hints expose the real platform version in the Sec-CH-UA-Platform-Version header if you request it.

Chrome versions end in zeros. Chrome reduced the detail in its user agent, so a desktop Chrome string carries Chrome/120.0.0.0: the major version is real and the rest is frozen. The parser reports browser.version: "120.0.0.0". Do not build logic on minor or build numbers you will never see.

The parser is built for browser strings. Give it something that is not a browser, such as python-requests/2.31.0, and it returns empty browser and os objects and isBot: false, because it is not designed to identify HTTP libraries. That is not a failure of the parser so much as a sign you asked the wrong tool. Bot questions go to the bot detector.

Check yourself

Your analytics shows zero Windows 11 users and many Windows 10 users, all from parsed user agents. What is the most likely explanation?

Answer the check above to continue.

Run every example on your own key. Free plan, no card.

Scaling up?

Volume pricing, custom SLAs, and dedicated support for high-traffic teams.

Contact sales