go-useragent
is a high-performance zero-allocation Go library designed to parse browser name and version, operating system, and device type information from user-agent strings with sub-microsecond parsing times.
It achieves this efficiency by using a modified hybrid trie data structure to store and rapidly look up user-agent tokens. It utilizes heuristic rules, tokenizing a list of user-agent strings into a trie during startup. During runtime, the parsing process involves a straightforward lookup operation.
This project is actively maintained and used by the lightweight website analytics project Medama.
go get -u github.com/medama-io/go-useragent
This type of parser is typically initialized once at application startup and reused throughout the application's lifecycle. While it doesn't offer the exhaustive coverage of traditional regex-based parsers, it can be paired with one to handle unknown edge cases, where the trie-based parser acts as a fast path for the majority of user-agents.
package main
import (
"fmt"
"github.com/medama-io/go-useragent"
)
func main() {
// Create a new parser. Initialize only once during application startup.
ua := useragent.NewParser()
// Example user-agent string.
str := "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36"
// Parse the user-agent string.
agent := ua.Parse(str)
// Access parsed information using agent fields.
fmt.Println(agent.GetBrowser()) // Chrome
fmt.Println(agent.GetOS()) // Windows
fmt.Println(agent.GetVersion()) // 118.0.0.0
fmt.Println(agent.IsDesktop()) // true
fmt.Println(agent.IsMobile()) // false
fmt.Println(agent.IsTablet()) // false
fmt.Println(agent.IsTV()) // false
fmt.Println(agent.IsBot()) // false
// Helper functions.
fmt.Println(agent.GetMajorVersion()) // 118
}
Refer to the pkg.go.dev documentation for more details on available fields and their meanings.
Benchmarks were performed against ua-parser/uap-go
and mileusena/useragent
on an Apple M3 Pro Processor.
cd ./benchmarks
go test -bench=. -benchmem ./...
MedamaParserGetSingle-12 2916867 408.5 ns/op 0 B/op 0 allocs/op
MileusnaParserGetSingle-12 1322602 917.3 ns/op 600 B/op 16 allocs/op
UAPParserGetSingle-12 986428 1159 ns/op 233 B/op 8 allocs/op
MedamaParserGetAll-12 57078 20037 ns/op 0 B/op 0 allocs/op
MileusnaParserGetAll-12 28375 42301 ns/op 28031 B/op 716 allocs/op
UAPParserGetAll-12 18645 56951 ns/op 10179 B/op 344 allocs/op
- The library draws inspiration from the techniques outlined in this Raygun blog post.