ua-parser-builtins review
Our ua-parser-builtins 202606 install took 0.2 seconds and left one 1 MB package in the sandbox. The wheel contains generated matcher data from uap-core for Python's ua-parser project. It has no supported parser API of its own. ua-parser loads the eager or lazy builtins so applications can classify browser, operating-system, and device strings without compiling regexes.yaml at startup. The calendar version marks the monthly rules snapshot, and the wheel's REVISION file records the exact uap-core commit used. A newer snapshot can change classifications even when ua-parser code stays pinned.
ua-parser-builtins 202606 installed in 0.2 seconds with zero dependencies and a 1 MB footprint in our sandbox, but it exposes no supported parsing API. Let ua-parser install it, pin the monthly snapshot when classifications feed reports, and never treat a parsed user-agent label as identity evidence.
We installed it
| Install | ✓ · 0.2s | 1 package on disk · 1 MB |
| Import | ✓ | import ua_parser_builtins in 0.01s · pure Python · py.typed · requires Python >=3.10 |
| Known vulns | 0 | (pip-audit) |
Answers from our run
Does ua-parser-builtins install cleanly?
Yes. In a fresh container with an empty cache, pip install ua-parser-builtins finished in 0.2s, leaving 1 package and 1 MB on disk. pip-audit reported no known vulnerabilities.
What does ua-parser-builtins need to run?
Python >=3.10, and nothing compiled: it is pure Python. In our run import ua_parser_builtins succeeded in 0.01s, and the package ships py.typed for type checkers.
ua-parser-builtins or ua-parser: which should you use?
ua-parser: Install this in application code for the public parser API; it already depends on ua-parser-builtins. ua-parser-builtins 202606 installed in 0.2 seconds with zero dependencies and a 1 MB footprint in our sandbox, but it exposes no supported parsing API.
When should you not use ua-parser-builtins?
You want a function that parses a header: the package README says it has no actual API, so install ua-parser
Use it if
- You depend on ua-parser and want its default precompiled uap-core rules instead of loading regexes.yaml at process start
- A lockfile should pin the recognition dataset separately from ua-parser's callable API
- CPython, PyPy, or GraalPy on Python 3.10 or newer needs the same generated rules wheel
- You understand that this package is transitively installed data and application imports should come from ua_parser
- You want a function that parses a header: the package README says it has no actual API, so install ua-parser
- Your traffic needs private client patterns or a trimmed dataset: ua-parser documents loading a custom ruleset for those cases
- Python 3.9 or older remains in production: version 202606 declares Python 3.10 or newer
- A rules update must never alter historical classifications: monthly snapshots follow uap-core and should be pinned and regression-tested
- You plan to use a browser or device label for authentication or authorization: the source string is supplied by the requester and can be spoofed
Setup reality
We installed ua-parser-builtins 202606 in 0.2 seconds under Python 3.12. The sandbox ended with one package using 1 MB. It has zero direct dependencies, is pure Python, carries py.typed, and requires Python 3.10 or newer. pip-audit reported 0 known vulnerabilities. import ua_parser_builtins completed in 0.01 seconds, though that successful namespace import does not expose an application parser.
Most projects should declare ua-parser[regex], which installs ua-parser-builtins transitively and selects the project's preferred Rust-backed resolver when a compatible wheel exists. The base ua-parser install uses the pure-Python resolver; its README calls that path significantly slower, especially away from CPython. There are no credentials or configuration files. A missing compatible native resolver falls back to another resolver instead of changing the rules package.
Version 202606 is a compiled monthly snapshot of uap-core's default branch. The wheel contains eager, lazy, and legacy generated rule modules plus a top-level REVISION file. Pin ua-parser-builtins when repeatable analytics matter, because updating only this package can rename a browser family, recognize a new bot, or turn an old unknown into a match. Keep fixture user-agent strings around reports whose categories must stay stable.
Application code should import parse, Parser, load_builtins, or load_lazy_builtins from ua_parser. Unknown browser, OS, or device fields return None, including all three for an empty string. Replacing ua_parser.parser changes the global parser for every caller in that process. Custom rules can be loaded into a separate Parser when global mutation is too broad. Parsed results remain hints from an untrusted header, never proof of a user's device or identity.
Patterns
Install the public parser and its rules install-parser-with-rules
python -m pip install 'ua-parser[regex]'ua-parser installs ua-parser-builtins transitively; the regex extra is the resolver recommended by the project.
Lock parser code and rule data pin-monthly-rules
# requirements.txt
ua-parser[regex]==1.0.2
ua-parser-builtins==202606The 202606 calendar version identifies the rules snapshot, so pinning both packages keeps classification changes reviewable.
Parse browser, OS, and device fields parse-user-agent
from ua_parser import parse
result = parse(request.headers.get('User-Agent', ''))
print(result.user_agent, result.os, result.device)parse comes from ua_parser; ua-parser-builtins supplies its default data and unmatched sections return None.
Request only browser information parse-browser-family
from ua_parser import parse_user_agent
browser = parse_user_agent(user_agent_string)
family = browser.family if browser else 'Unknown'parse_user_agent returns None when no browser rule matches, including for an empty string.
Build an OS version safely parse-operating-system
from ua_parser import parse_os
os = parse_os(user_agent_string)
if os is not None:
version = '.'.join(x for x in (os.major, os.minor, os.patch) if x)
print(os.family, version)OS version pieces are optional and must be filtered before joining them.
Read device family, brand, and model parse-device-details
from ua_parser import parse_device
device = parse_device(user_agent_string)
label = 'Unknown' if device is None else (
' '.join(x for x in (device.brand, device.model) if x) or device.family
)Desktop headers often have sparse device fields, and every result comes from a spoofable request header.
Create a parser from eager builtins load-eager-rules
from ua_parser import Parser, load_builtins
parser = Parser.from_matchers(load_builtins())
result = parser.parse(user_agent_string)load_builtins is the supported ua_parser loader; importing generated MATCHERS directly relies on package internals.
Delay matcher compilation load-lazy-rules
from ua_parser import Parser, load_lazy_builtins
parser = Parser.from_matchers(load_lazy_builtins())
result = parser.parse_user_agent(user_agent_string)load_lazy_builtins defers regex compilation, while the selected resolver and cache still determine runtime cost.
Log the active data snapshot record-rules-version
from importlib.metadata import version
rules_version = version('ua-parser-builtins')
print({'ua_rules': rules_version})Recording 202606-style versions beside analytics output makes classification shifts traceable to a rules update.
Keep unmatched traffic in its own bucket preserve-unknown-results
from ua_parser import parse
r = parse(user_agent_string or '')
row = {
'browser': r.user_agent.family if r.user_agent else 'Unknown',
'os': r.os.family if r.os else 'Unknown',
'device': r.device.family if r.device else 'Unknown',
}ua-parser returns None for unmatched domains; guessing from substrings hides changes in monthly rules coverage.
Load private rules without changing globals use-isolated-custom-parser
from ua_parser import Parser
from ua_parser.loaders import load_yaml
with open('regexes.yaml', 'rb') as rules:
parser = Parser.from_matchers(load_yaml(rules))
result = parser.parse(user_agent_string)A separate Parser avoids replacing ua_parser.parser for every caller in the process; load_yaml requires PyYAML.
Alternatives
| Package | Registry | Pick it when |
|---|---|---|
| ua-parser | PyPI | Install this in application code for the public parser API; it already depends on ua-parser-builtins. |
| user-agents | PyPI | Use it for convenience properties such as is_mobile on top of ua-parser data. |
| httpagentparser | PyPI | Use it for a separate lightweight parser with dictionary results and a different rules database. |
| device-detector | PyPI | Use it when bot and device detection features from the Matomo rules ecosystem fit better. |
More utils guides
lru-cache · ajv · type-fest · p-limit · find-up · js-yaml · the whole shelf →
How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.

