UserAgent
UserAgent parses an HTTP User-Agent string to determine basic device, operating system, and client application characteristics. It’s designed to be fast and reasonably accurate at identifying browsers, bots, and mobile applications with a large market share. Smaller clients will either be classified as “Other”, or as the browser they’re derived from (e.g. Waterfox will be classified as Firefox).
UserAgent is intended to help you answer questions like the following:
- What percentage of our site traffic is coming from mobile phones, tablets, and desktop/laptop computers?
- Which browsers should we be using to test our web application? Can we stop supporting Internet Explorer?
- Which browser versions are people using today? Can we use this particular CSS feature?
- If we were going to develop native application(s), which operating system(s) should we support?
If you care more about the specific make/model of the mobile device someone is using, you would be better served using something like the Matomo Analytics Device Detector. It’s an actively-maintained collection of YAML files with regular expressions focused on accurate device detection. This accuracy comes at a performance cost, though. A cascade of regular expression matches is going to be slow.
If you’d like a decent sample of real-world User-Agent strings to test with, the file user_agents.json contains a collection of 17,548 unique User-Agent strings from 458,143 webpage views in Q2 of 2022. They’re grouped, having been characterized using a Java port of the Device Detector. Note that they may have been mis-characterized in those groupings.
Installation
go get github.com/voxtechnica/user-agent
Usage
Use user_agent.Parse(header)
to create a UserAgent
, as illustrated below.
header := "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.67 Safari/537.36"
ua := user_agent.Parse(header)
fmt.Println(ua.String()) // Browser Chrome 101.0 Desktop Windows 10.0
Performance
The User-Agent parser is pretty fast. It’s based on strings.Contains
instead of using regular expressions.
It takes 3-4 microseconds to parse a User-Agent header, as indicated in the example benchmark results below.
go test -bench=. -benchmem
goos: linux
goarch: amd64
pkg: github.com/voxtechnica/user-agent
cpu: Intel(R) Core(TM) i7-10710U CPU @ 1.10GHz
BenchmarkParse/Parse-Googlebot-12 420231 2684 ns/op 835 B/op 12 allocs/op
BenchmarkParse/Parse-Chrome-12 332326 3270 ns/op 1589 B/op 15 allocs/op
BenchmarkParse/Parse-Firefox-12 373551 2997 ns/op 1200 B/op 16 allocs/op
BenchmarkParse/Parse-Safari-12 275498 4242 ns/op 2032 B/op 19 allocs/op
PASS
ok github.com/voxtechnica/user-agent 4.654s