npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ua-lite

v1.0.0

Published

Fast, dependency-free JavaScript user agent parser — browser, engine, OS, CPU, and device detection, plus built-in bot, AI-crawler, and in-app-browser classification and Client Hints support.

Readme

ua-lite

A compact, dependency-free, MIT-licensed user agent parser for JavaScript. Detects browser, engine, OS, CPU, and device — plus first-class classification of bots, AI training crawlers, and in-app browsers, and support for User-Agent Client Hints.

No build step. src/ua-lite.js is the distributable — drop it straight into a <script> tag, require() it in Node, or import it.

Install

npm install ua-lite

Or drop the file directly into a page:

<script src="ua-lite.js"></script>
<script>
  const result = UALite.parse(navigator.userAgent);
</script>

Quick start

const { parse } = require('ua-lite');

const result = parse('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36');
console.log(result.browser.name); // 'Chrome'

Full example output

parse('Mozilla/5.0 (Linux; Android 14; Pixel 8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6367.82 Mobile Safari/537.36');
{
  "ua": "Mozilla/5.0 (Linux; Android 14; Pixel 8) AppleWebKit/537.36 ...",
  "browser": { "name": "Chrome", "version": "124.0.6367.82" },
  "engine":  { "name": "Blink", "version": "124.0.6367.82" },
  "os":      { "name": "Android", "version": "14" },
  "cpu":     { "architecture": null },
  "device":  { "type": "mobile", "vendor": "Google", "model": "Pixel 8" },
  "agent":   { "type": "browser", "name": "Chrome" }
}

parse() never throws and never returns undefined fields — every key is present, with null where nothing was detected.

API reference

parse(ua, hints?)

Synchronously parses a UA string. ua is trimmed to 500 characters. Pass an optional hints object (see Client hints) to merge Client Hints data into the result in one call.

parseAsync(ua?)

Returns a Promise<UAResult>. In a browser, automatically collects navigator.userAgentData (including high-entropy values like platformVersion, architecture, and model) and merges them into the result. Falls back to a plain parse() when the Client Hints API isn't available. ua defaults to navigator.userAgent.

resolveHints(hints, result)

Merges a Client Hints header object into an existing UAResult, returning a new object — the input result is never mutated.

collectHints()

Browser-only. Reads navigator.userAgentData synchronously and returns a hints object (low-entropy only — brands, mobile flag, platform). Returns null if the API isn't available.

Client hints

Browser-side

const { parse, collectHints } = require('ua-lite');

const result = parse(navigator.userAgent, collectHints());

Or use parseAsync() to also pick up high-entropy values (platformVersion, architecture, model, full version list):

const { parseAsync } = require('ua-lite');
const result = await parseAsync();

Server-side

Pass the raw Sec-CH-UA-* request headers straight through:

const { parse } = require('ua-lite');

app.get('/', (req, res) => {
  const result = parse(req.headers['user-agent'], req.headers);
  res.json(result);
});

Recognized header keys (case-insensitive):

| Header | Effect | | --- | --- | | sec-ch-ua | Overrides browser.name from the brand list (skips Chromium/Not-A.Brand noise entries) | | sec-ch-ua-full-version-list | Overrides browser.name and browser.version with the full version | | sec-ch-ua-platform | Overrides os.name | | sec-ch-ua-platform-version | Overrides os.version | | sec-ch-ua-mobile | ?1 sets device.type to mobile, ?0 sets it to desktop | | sec-ch-ua-arch | Overrides cpu.architecture | | sec-ch-ua-model | Overrides device.model (only when non-empty) |

Agent types explained

agent.type classifies what kind of client is making the request — independent of, and detected before, browser parsing:

| Type | Covers | Examples | | --- | --- | --- | | ai | Crawlers that train or answer from AI models | GPTBot, ClaudeBot, Google-Extended, PerplexityBot, CCBot, Bytespider | | crawler | Traditional search/indexing/SEO crawlers | Googlebot, Bingbot, AhrefsBot, Twitterbot | | bot | Generic scripts and HTTP clients | curl, wget, python-requests, axios, Go-http-client | | app | In-app / wrapper browsers | Instagram, Facebook, TikTok, Twitter, WhatsApp, Electron | | browser | Everything else — a regular end-user browser | Chrome, Firefox, Safari, Edge |

When agent.type is browser, agent.name mirrors browser.name. device.type is forced to 'bot' whenever agent.type is anything other than browser or app.

How to extend

All detection rules live in flat, ordered tables inside src/ua-lite.js — no build step, so edits take effect immediately.

To add a new agent pattern (e.g. a new AI crawler), find the AGENT_RULES array and add a [regex], [['type', 'ai'], ['name', 'YourBotName']], pair in the appropriate tier. Order matters — rules are tried top to bottom and the first match wins, so put more specific patterns before generic ones.

The same pattern applies to BROWSER_RULES, OS_RULES(), CPU_RULES, and DEVICE_RULES_PASS1.

Benchmarked against other popular parsers

ua-lite's domain knowledge (regex ordering, the Windows NT version map, the rgxMapper pattern) was studied from ua-parser-js — see src/ua-lite.js for the disclosure. No code was copied; all patterns here are written fresh. We benchmarked ua-lite against that library (both major versions) plus four other widely used UA-parsing libraries on npm: bowser, platform.js, express-useragent, and mobile-detect.

All figures below are real measurements: each package was installed fresh from npm, required directly (no bundler), and run through the same 12-UA mix (desktop/mobile/tablet/bot) on Node 22.

ua-parser-js v1 and v2 are shown separately because their license terms differ sharply — that difference is the main reason ua-lite exists.

| | ua-lite | ua-parser-js v1 | ua-parser-js v2 | | --- | --- | --- | --- | | License | MIT | MIT (unmaintained) | AGPL-3.0 (commercial tiers available) | | Bot/AI agent detection | ✅ built-in, free | ❌ | ✅, but gated behind AGPL copyleft or a paid commercial license | | Client Hints | ✅ built-in | ➖ separate package | ✅ | | Build step | None | None | Requires build | | Bundle | Single file | Single file | Multi-file, plus a large bundled icon set |

Bundle size (gzip, the actual file require() resolves to):

| | ua-lite | bowser | platform.js | express-useragent | mobile-detect | ua-parser-js v1 | ua-parser-js v2 | | --- | --- | --- | --- | --- | --- | --- | --- | | gzip size | 6.0 KB | 7.6 KB | 11.9 KB | 8.4 KB | 22.5 KB | 8.7 KB | 13.6 KB |

Parse throughput (50,000 parses, warm, parses/sec):

| | ua-lite | bowser | platform.js | express-useragent | mobile-detect | ua-parser-js v1 | ua-parser-js v2 | | --- | --- | --- | --- | --- | --- | --- | --- | | parses/sec | 292,000 | 256,000 | 22,000 | 380,000 | 119,000 | 88,600 | 21,500 |

express-useragent edges out ua-lite on raw throughput — it returns a flatter, simpler object (mostly boolean flags) with less string-shaping per parse. platform.js is by far the slowest of the group, at roughly 1/17th of express-useragent's throughput.

Feature coverage — this is where the field narrows fast:

| | ua-lite | bowser | platform.js | express-useragent | mobile-detect | | --- | --- | --- | --- | --- | --- | | License | MIT | MIT | MIT | MIT | MIT | | Browser name/version | ✅ | ✅ | ✅ | ✅ | ❌ | | Engine (Blink/Gecko/WebKit) | ✅ | ✅ | ✅ (as "layout") | ❌ | ❌ | | OS name/version | ✅ | ✅ (empty for bot UAs, correctly — no OS token to find) | ✅ | ✅ | ✅ (OS family only) | | CPU architecture | ✅ (arch family: amd64/arm64/arm/...) | ❌ | ➖ (bit-width only — 32/64, misses arch family entirely, even for aarch64) | ❌ | ❌ | | Device type (mobile/tablet/desktop/tv/console) | ✅ | ➖ (type: "bot" only) | ❌ | ➖ (boolean flags, no unified type) | ➖ (mobile/tablet booleans only) | | Traditional crawler detection (Googlebot, Bingbot) | ✅ | ✅ (with vendor) | ❌ | ✅ | ❌ | | AI-crawler detection (GPTBot, ClaudeBot, PerplexityBot) | ✅ | ✅ (with vendor) | ❌ | ❌ | ❌ | | Generic script detection (curl, python-requests) | ✅ | ❌ | ❌ | ✅ | ❌ | | In-app browser detection (Instagram, Facebook, TikTok) | ✅ | ➖ (device only, no wrapper flag) | ❌ | ➖ (Facebook flag only) | ❌ | | Client Hints (sec-ch-ua-*) parsing | ✅ | ❌ | ❌ | ➖ (field exists, must be fed manually) | ❌ |

Takeaways from actually running these side by side:

  • bowser is the strongest of the four alternatives on bot detection — it tags many known AI crawlers with a vendor field ("Anthropic", "OpenAI") and returns proper OS name/version for regular browsers — but it has no CPU architecture at all, and no generic-script detection (curl, python-requests come back with an empty browser name, not flagged as bots).
  • platform.js is a legacy general-purpose detector: solid browser/OS fields, a CPU field that only reports 32/64-bit (never resolves aarch64 to an actual arm64 family), no bot detection of any kind, and it's ~13–17x slower than the others in this table — it does noticeably more string work per parse than the others.
  • express-useragent is the fastest here and has real crawler/script detection (isBot, botName, isCurl), but it predates the AI-crawler wave — it correctly flags Googlebot and curl, but returns nothing for GPTBot or ClaudeBot. It also has a clientHints field in its output shape, but nothing parses sec-ch-ua-* headers into it automatically.
  • mobile-detect is a mobile-detection specialist, not a general UA parser — no browser name, no engine, no bot detection at all. It answers one question well ("is this a phone/tablet?") and nothing else.
  • ua-parser-js v1 returns full browser/engine/OS/CPU/device fields under a permissive MIT license, but is unmaintained and has no bot or AI-agent classification at all — the gap ua-lite was built to fill.
  • ua-parser-js v2 does have AI-crawler pattern lists as rich as ua-lite's, but the whole package (including that submodule) ships under AGPL-3.0. Using it in a closed-source service means either open-sourcing that service or buying a commercial license — a legal cost, not a runtime one. It's also the heaviest and slowest option in this whole comparison.

ua-lite is the only one of the six that combines full field coverage (browser/engine/OS/CPU/device), tiered bot/AI/app classification, and native Client Hints resolution in a single MIT-licensed file with no copyleft strings attached — the closest alternative on features (bowser) still needs OS/CPU data filled in from elsewhere, the fastest alternative (express-useragent) needs AI-crawler patterns added by hand, and the only other option with comparable AI-crawler coverage (ua-parser-js v2) requires either open-sourcing your own product or paying for a license.

License

MIT