ua-parser
Parse browser, OS, and device data out of raw user agent strings, with pluggable fast-path resolvers.
Repository Health
Technical Analysis
ua-parser is the official Python implementation of the ua-parser project, a cross-language user agent string parser used to extract structured browser, operating system, and device information from raw HTTP user agent headers. It ships a pure-Python fallback resolver alongside optional RE2 and Rust-backed (ua-parser-rs) resolvers, so callers can trade install complexity for parsing throughput depending on their deployment constraints.
The library exposes both a simple top-level functional API (parse, parse_user_agent, parse_os, parse_device) backed by a lazily-initialised global parser, and a lower-level Parser/Resolver abstraction for callers who want to compose their own resolver stack (custom matcher sets, custom caches, or a specific regex engine). Results are returned as frozen dataclasses (UserAgent, OS, Device) that clearly separate lookup failures (None) from default values, avoiding the ambiguity common in older user-agent-parsing libraries.
What You Get
- A functional top-level API (
parse,parse_user_agent,parse_os,parse_device) backed by a lazily-initialised, thread-safe global parser - Frozen, typed result dataclasses (
UserAgent,OS,Device,Result,PartialResult,DefaultedResult) that distinguish ‘not found’ from ‘not looked up’ - Three interchangeable resolver backends: a pure-Python
BasicParser, an RE2-backed resolver, and a Rust-backed resolver (ua-parser-rs) for higher throughput - A built-in S3-FIFO
CacheandCachingResolverwrapper for keying repeated lookups on the same user agent string - Domain-scoped parsing via the
Domainflag enum, so callers can resolve onlyUSER_AGENT,OS, orDEVICEinstead of paying for all three - A CLI (
python -m ua_parser) for ad hoc parsing and regenerating/updating the bundled matcher data
Common Use Cases
- Server-side analytics pipelines that need to bucket incoming traffic by browser family, OS, or device type
- Bot/crawler and client-capability detection in request-handling middleware
- Responsive or adaptive content serving decisions based on parsed device data
- Log enrichment jobs that attach structured browser/OS/device fields to raw access logs
Under The Hood
Architecture The package centers on a small Resolver protocol (core.py): any callable taking a user agent string and a Domain flag and returning a PartialResult. Parser (__init__.py) is a thin convenience wrapper that composes a CachingResolver around a BestAvailableResolver — the first of RegexResolver (Rust), Re2Resolver, or BasicResolver (pure Python) that is importable in the environment — instantiated from Matchers data loaded via loaders.py. Matcher data is either loaded eagerly (load_builtins, from the ua_parser_builtins package) or lazily as YAML/JSON (load_lazy_builtins) for backends that construct their own compiled state (RE2, Rust). Module-level __getattr__ in __init__.py lazily constructs the global parser singleton on first access under a threading.Lock, avoiding upfront resolver/matcher construction cost for callers who only import the module.
Tech Stack Core package is pure Python (3.10+, also PyPy and GraalPy) with zero required runtime dependencies beyond ua-parser-builtins (the compiled matcher data, split out as its own package). Optional extras pull in PyYaml ([yaml]), google-re2 ([re2]), or the sibling Rust crate ua-parser-rs via PyO3 bindings ([regex], the recommended install per the README). The repo also vendors uap-core (the shared cross-language regex ruleset) as a git submodule and a ua-parser-rs Rust workspace member for the compiled resolver.
Code Quality Seven test files (625 lines) under tests/ cover core types, the convenience Parser API, caching behaviour, the RE2 resolver, legacy-API compatibility, and the automaton simplifier used to compile matcher data — each resolver backend and the caching layer has dedicated coverage. The codebase uses frozen slots=True dataclasses for all result types, full type hints checked under a fairly strict mypy configuration (disallow_untyped_defs, disallow_any_generics, check_untyped_defs), and ruff for linting/import sorting. pyproject.toml config is explicit and the CI workflow runs on GitHub Actions.
API Design The public surface is deliberately small and layered: four top-level functions cover the common case with no setup, while Parser/Resolver/Domain give power users composability without extra ceremony. Docstrings are thorough and Sphinx-rendered to readthedocs.io with a quickstart and migration guide from the pre-1.0 API, and the Domain flag lets callers avoid paying for unneeded parses. The one added-complexity is the multi-backend resolver selection (Regex/RE2/Basic), which is mostly invisible unless you need to control it directly.
Used by 3 apps in this directory
authentik
Authentication · Security
The self-hosted Identity Provider that replaces Okta, Auth0, and Entra ID with a unified SSO platform supporting SAML, OAuth2/OIDC, LDAP, RADIUS, and WebAuthn.
Redash
Analytics · Data Engineering
Redash lets anyone connect to 35+ SQL and NoSQL data sources, write a query in the browser, and turn the result into a shared dashboard — no separate BI suite required.
Sentry
Security · Developer Tools · Monitoring
Developer-first error tracking and performance monitoring platform with AI-powered root-cause analysis across 20+ languages and frameworks.