ua-parser

Parse browser, OS, and device data out of raw user agent strings, with pluggable fast-path resolvers.

Library
PyPI
v1.0.2
648stars
Apache License 2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
52/100Fair
Development Activity24
Maintenance24
Community80
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
75/100Good
Architecture80
Code Quality78
Innovation68
Learning Curve75

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 Cache and CachingResolver wrapper for keying repeated lookups on the same user agent string
  • Domain-scoped parsing via the Domain flag enum, so callers can resolve only USER_AGENT, OS, or DEVICE instead 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.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search