API

Global Helpers

ua_parser.parse(ua: str) Result[source]

Parses the UserAgent, OS, and Device information using the global parser.

Equivalent to calling each of parse_user_agent(), parse_os(), and parse_device() but may be more efficient than calling them separately depending on the underlying parser.

Even in the best case, prefer the domain-specific helpers if you’re not going to use all of them.

ua_parser.parse_user_agent(ua: str) UserAgent | None[source]

Parses the browser information using the global parser.

ua_parser.parse_os(ua: str) OS | None[source]

Parses the OS information using the global parser.

ua_parser.parse_device(ua: str) Device | None[source]

Parses the Device information using the global parser.

ua_parser.parser: Parser = <ua_parser.Parser object>

Global Parser, lazy-initialised on first access, used by the global helper functions.

Can be set to configure a customised global parser.

Accessing the parser explicitely can be used eagerly force its initialisation, rather than pay for it at first call.

Core Types

class ua_parser.Resolver[source]

The resolver is the thin central abstraction of ua-parser, and used to compose various objects into the resolution stack which best fits the system’s needs.

A resolver is any callable which takes a string ua and a Domain, and returns a PartialResult with at least the requested domains marked as resolved (whether successfully or not).

A resolver may resolve more domains than requested, but it needs to resolve at least the requested domains.

See PartialResult for more information about its working.

abstractmethod __call__(ua: str, domain: Domain, /) PartialResult[source]

Resolves the ua.

class ua_parser.Domain(*values)[source]

Hint for selecting which domains are requested when asking for a PartialResult.

USER_AGENT = 1

browser (user agent) domain

OS = 2

os domain

DEVICE = 4

device domain

ALL = 7

shortcut for all three domains

class ua_parser.Parser(resolver: Resolver)[source]

Wrapper object, provides convenience methods around an underlying Resolver.

classmethod from_matchers(Matchers) Parser[source]

Instantiates a parser from the provided Matchers using the default resolver stack.

parse(ua: str) Result[source]

Convenience method for parsing all domains.

parse_device(ua: str) Device | None[source]

Convenience method for parsing the Device domain.

parse_os(ua: str) OS | None[source]

Convenience method for parsing the OS domain.

parse_user_agent(ua: str) UserAgent | None[source]

Convenience method for parsing the UserAgent domain.

Data Types

These are the various types produced by successfully resolving a user agent string. They are guaranteed to be dataclasses, and using dataclass utility functions is officially supported.

class ua_parser.PartialResult(domains: Domain, user_agent: UserAgent | None, os: OS | None, device: Device | None, string: str)[source]

Potentially partial (incomplete) result.

Domain fields (user_agent, os, and device) can be:

  • unset if not parsed yet

  • set to a parsing failure

  • set to a parsing success

The domains flags specify which is which: if a Domain flag is set, the corresponding attribute was looked up and is either None for a resolution failure (no match was found) or a value for a parsing success.

If the flag is unset, the field has not been looked up yet, in which case it can be anything (but should usually be None).

complete() Result[source]

Requires that the result be fully resolved (every attribute is set, even if to a lookup failure).

Raises:

ValueError – if the result is not fully resolved

class ua_parser.Result(user_agent: UserAgent | None, os: OS | None, device: Device | None, string: str)[source]

Complete result.

For each attribute (and domain), either the resolution was a success (a match was found) and the corresponding data is set, or it was a failure and the value is None.

with_defaults() DefaultedResult[source]

Replaces every failed domain by its default value.

Roughly matches pre-1.0 semantics, and can allow for more uniform handling by the client if they don’t want or need the lookup failure information.

class ua_parser.UserAgent(family: str = 'Other', major: str | None = None, minor: str | None = None, patch: str | None = None, patch_minor: str | None = None)[source]

Browser (“user agent” aka the software responsible for the request) information parsed from the user agent string.

class ua_parser.OS(family: str = 'Other', major: str | None = None, minor: str | None = None, patch: str | None = None, patch_minor: str | None = None)[source]

OS information parsed from the user agent string.

class ua_parser.Device(family: str = 'Other', brand: str | None = None, model: str | None = None)[source]

Device information parsed from the user agent string.

class ua_parser.DefaultedResult(user_agent: UserAgent, os: OS, device: Device, string: str)[source]

Variant of Result where attributes are set to a default value if their resolution failed.

For all domains, the default value has family set to "Other" and every other attribute set to None.

Base Resolvers

Base resolvers take sets of Matchers generated by loaders, and use them to extract data from user agent strings.

class ua_parser.basic.Resolver(Matchers)[source]

A simple pure-python resolver based around trying a number of regular expressions in sequence for each domain, and returning a result when one matches.

class ua_parser.re2.Resolver(Matchers)

An advanced resolver based around google-re2’s FilteredRE2 feature, which efficiently prunes the number of possibly matching matchers before actually running them.

Sufficiently fast that a cache may not be necessary, and may even be detrimental at smaller cache sizes

Warning

Only available if google-re2 is installed.

class ua_parser.regex.Resolver(Matchers)

An advanced resolver based on Rust’s regex and a bespoke implementation of regex prefiltering, by the sibling project uap-rust.

Sufficiently fast that a cache may not be necessary, and may even be detrimental at smaller cache sizes

Warning

Only available if ua-parser-rs <https://pypi.org/project/ua-parser-rs/>_ is installed.

Eager Matchers

class ua_parser.matchers.DeviceMatcher(regex: str, regex_flag: Literal['i'] | None = None, family: str | None = None, brand: str | None = None, model: str | None = None)[source]

Bases: Matcher[Device]

Eager device matcher, compiles the input regex at initialisation.

property regex: str

Returns the matcher’s pattern.

property flags: int

Returns the matcher’s pattern flags (only re.IGNORECASE is supported, and only for Matcher [Device])

class ua_parser.matchers.OSMatcher(regex: str, family: str | None = None, major: str | None = None, minor: str | None = None, patch: str | None = None, patch_minor: str | None = None)[source]

Bases: Matcher[OS]

Eager OS matcher, compiles the input regex at initialisation.

property regex: str

Returns the matcher’s pattern.

class ua_parser.matchers.UserAgentMatcher(regex: str, family: str | None = None, major: str | None = None, minor: str | None = None, patch: str | None = None, patch_minor: str | None = None)[source]

Bases: Matcher[UserAgent]

Eager user agent matcher, compiles the input regex at initialisation.

property regex: str

Returns the matcher’s pattern.

Lazy Matchers

These matchers will lazily compile their pattern to an re.Pattern.

While this saves CPU upfront, this is most useful with resolvers which likely will not need to apply most of them, like ua_parser.re2.Resolver. If the resolver will very likely need to apply (and thus compile) every pattern like ua_parser.basic.Resolver, then lazy compilation has a higher overhead.

class ua_parser.lazy.DeviceMatcher(regex: str, regex_flag: Literal['i'] | None = None, family: str | None = None, brand: str | None = None, model: str | None = None)[source]

Bases: Matcher[Device]

Lazy device matcher, compiles the input regex on first use.

Requires slightly more memory as it needs to reference both the pattern string and the compiled pattern.

property flags: int

Returns the matcher’s pattern flags (only re.IGNORECASE is supported, and only for Matcher [Device])

class ua_parser.lazy.OSMatcher(regex: str, family: str | None = None, major: str | None = None, minor: str | None = None, patch: str | None = None, patch_minor: str | None = None)[source]

Bases: Matcher[OS]

Lazy OS matcher, compiles the input regex on first use.

Requires slightly more memory as it needs to reference both the pattern string and the compiled pattern.

class ua_parser.lazy.UserAgentMatcher(regex: str, family: str | None = None, major: str | None = None, minor: str | None = None, patch: str | None = None, patch_minor: str | None = None)[source]

Bases: Matcher[UserAgent]

Lazy user agent matcher, compiles the input regex on first use.

Requires slightly more memory as it needs to reference both the pattern string and the compiled pattern.

Caching

Web clients commonly have multiple interactions with a given system, leading to significant repetition in user agents encountered. A cache allows making use of that to avoid redundant parses, at the cost of memory. This is most useful for slow base resolvers like the basic resolver.

class ua_parser.caching.Cache[source]

Cache abstract protocol. The CachingResolver will look values up, merge what was returned (possibly nothing) with what it got from its actual parser, and re-set the result.

abstractmethod __getitem__(key: str) PartialResult | None[source]

Returns a partial result for key if there is any.

abstractmethod __setitem__(key: str, value: PartialResult) None[source]

Adds or replace value to the cache at key key.

class ua_parser.CachingResolver(resolver: Resolver, cache: Cache)[source]

A wrapper resolver which takes an underlying concrete Cache for the actual caching and cache strategy.

This resolver only interacts with the Cache and delegates to the wrapped resolver in case of lookup failure.

CachingParser will set entries back in the cache when filling them up, it does not update results in place (and can’t really, they’re immutable).

ua_parser.Cache[source]

alias of S3Fifo

class ua_parser.caching.S3Fifo(maxsize: int)[source]

FIFO-based quick-demotion lazy-promotion cache [S3-FIFO].

Experimentally provides excellent hit rate at lower cache sizes, for a relatively simple and efficient implementation. Notably excellent at handling “one hit wonders”, aka entries seen only once during a work-set (or reasonable work window).

class ua_parser.caching.Sieve(maxsize: int)[source]

FIFO-based quick-demotion cache [SIEVE].

Simpler FIFO-based cache, cousin of S3Fifo. Experimentally slightly lower hit rates than S3Fifo (if way superior to LRU still), but much more compact (~50% lower memory overhead at larger cache sizes, up to 100% at very small cache sizes).

Can be an interesting candidate when trying to save on memory, although the contained entries will generally be much larger than the cache itself.

class ua_parser.caching.Lru(maxsize: int)[source]

Cache following a least-recently used replacement policy: when there is no more room in the cache, whichever entry was last seen the least recently is removed.

Simple LRUs are generally outdated and to avoid as they have relatively low hit rates for modern caches (at lower sizes). The main use case here is if the workload can lead to the cache being full of popular items then all of them being replaced at once: S3Fifo and Sieve are FIFO-based caches and have worst-case O(n) eviction.

class ua_parser.caching.Local(factory: Callable[[], Cache])[source]

Thread local cache decorator. Takes a cache factory and lazily instantiates a cache for each thread it’s accessed from.

This means the cache capacity and memory consumption is figuratively multiplied by however many threads the cache is used from, but those threads don’t share their caching, and thus don’t contend on cache use.

Loading

ua_parser.core.Matchers

alias of Tuple[List[Matcher[UserAgent]], List[Matcher[OS]], List[Matcher[Device]]]

class ua_parser.core.Matcher[source]

A matcher is an individual pattern-rule, able to match a user agent string and in case of success extract the relevant data.

Matchers need to expose their pattern for bulk resolvers.

abstractmethod __call__(ua: str) T | None[source]

Applies the matcher to an input.

property flags: int

Returns the matcher’s pattern flags (only re.IGNORECASE is supported, and only for Matcher [Device])

abstract property regex: str

Returns the matcher’s pattern.

ua_parser.load_builtins() Matchers[source]

Loads the pre-compiled matcher data into eager matchers.

The matchers data is imported lazily, and cached after imports, further imports simply reference the existing datas.

ua_parser.load_lazy_builtins() Matchers[source]

Loads the pre-compiled matcher data into lazy matchers.

The matchers data is imported lazily, and cached after imports, further imports simply reference the existing datas.

Custom regexes.yaml data

ua_parser.loaders.load_data(MatchersData) Matchers[source]

Loads the input data set into eager matchers.

ua_parser.loaders.load_lazy(MatchersData) Matchers[source]

Loads the input data set into lazy matchers.

ua_parser.loaders.load_json(f: PathOrFile, loader: DataLoader = <function load_data>) Matchers[source]

Loads JSON data following the regexes.yaml structure.

The loader parameter customises which matcher variant is generated, by default load_data() is used to generate eager matchers, load_lazy() can be used to generate lazy matchers instead.

ua_parser.loaders.load_yaml(f: PathOrFile, loader: DataLoader = load_data) Matchers[source]

Loads YAML data following the regexes.yaml structure.

The loader parameter customises which matcher variant is generated, by default load_data() is used to generate eager matchers, load_lazy() can be used to generate lazy matchers instead.

Warning

Only available if PyYaml is installed.