Skip to content

medama-io/go-useragent

Repository files navigation

go-useragent

go-useragent is a high-performance 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.

Installation

go get -u github.com/medama-io/go-useragent

Usage

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.

Example

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

Benchmarks were performed against ua-parser/uap-go and mileusena/useragent on an AMD Ryzen 7 5800X 8 Core Processor.

cd ./benchmarks
go test -bench=. -benchmem ./...

MedamaParserGetSingle-16        2685813             440.2 ns/op              24 B/op          2 allocs/op
UAPParserGetSingle-16           1025696              1205 ns/op             233 B/op          8 allocs/op
MileusnaParserGetSingle-16       959205              1215 ns/op             600 B/op         16 allocs/op

MedamaParserGetAll-16             64491             18114 ns/op             576 B/op         55 allocs/op
UAPParserGetAll-16                25078             47720 ns/op            8425 B/op        288 allocs/op
MileusnaParserGetAll-16           22962             51956 ns/op           23735 B/op        596 allocs/op

Acknowledgements

  • The library draws inspiration from the techniques outlined in this Raygun blog post.