Overview
The client package provides sophisticated TLS and HTTP/2 fingerprinting capabilities to mimic real browsers. This allows HTTP clients to appear as legitimate browser traffic to servers that perform fingerprint analysis.
Browser Enum
Browser identifies the browser for TLS and HTTP/2 fingerprinting.
Supported Browsers
Google Chrome - uses HelloChrome_Auto TLS fingerprint
Microsoft Edge - uses HelloChrome_Auto with Edge branding
Brave browser - uses HelloChrome_Auto with Brave branding
Apple Safari - uses HelloSafari_Auto or HelloIOS_Auto TLS fingerprint
Mozilla Firefox - uses HelloFirefox_Auto TLS fingerprint
Source: /home/daytona/workspace/source/pkg/client/fingerprint.go:16
Constants
const (
BrowserChrome Browser = "chrome"
BrowserEdge Browser = "edge"
BrowserBrave Browser = "brave"
BrowserSafari Browser = "safari"
BrowserFirefox Browser = "firefox"
)
Platform identifies the OS platform for TLS and HTTP/2 fingerprinting.
Windows operating system - “Windows NT 10.0; Win64; x64” in User-Agent
macOS - “Macintosh; Intel Mac OS X 10_15_7” in User-Agent
Linux - “X11; Linux x86_64” in User-Agent
iOS - “iPhone; CPU iPhone OS” in User-Agent
iPadOS - “iPhone; CPU iPhone OS” in User-Agent (Safari only)
Source: /home/daytona/workspace/source/pkg/client/fingerprint.go:32
Constants
const (
PlatformWindows Platform = "windows"
PlatformMac Platform = "mac"
PlatformLinux Platform = "linux"
PlatformIOS Platform = "ios"
PlatformIPadOS Platform = "ipados"
)
H2Profile Type
type H2Profile struct {
Settings []http2.Setting
ConnectionWindow uint32
Priority http2.PriorityParam
PseudoOrder []string
}
H2Profile contains HTTP/2 connection settings that control the fingerprint of the HTTP/2 SETTINGS frame and WINDOW_UPDATE.
HTTP/2 SETTINGS frame parameters sent during connection preface
Initial connection window size (triggers WINDOW_UPDATE if > 65535)
Stream priority parameters for the HEADERS frame
Order of pseudo-headers (“:method”, “:authority”, “:scheme”, “:path”)
Source: /home/daytona/workspace/source/pkg/client/fingerprint.go:47
BrowserProfile Type
type BrowserProfile struct {
ClientHelloID utls.ClientHelloID
H2 H2Profile
DefaultHeaders http.Header
}
BrowserProfile combines a TLS ClientHelloID with HTTP/2 settings and default request headers for a specific browser identity.
TLS ClientHello fingerprint from the utls library
HTTP/2 profile with SETTINGS, window size, and pseudo-header order
Default HTTP headers automatically added to requests
Source: /home/daytona/workspace/source/pkg/client/fingerprint.go:56
Chrome/Edge/Brave Profile
var h2Chrome = H2Profile{
Settings: []http2.Setting{
{ID: http2.SettingHeaderTableSize, Val: 65536},
{ID: http2.SettingEnablePush, Val: 0},
{ID: http2.SettingInitialWindowSize, Val: 6291456},
{ID: http2.SettingMaxHeaderListSize, Val: 262144},
},
ConnectionWindow: 15663105,
Priority: http2.PriorityParam{
Weight: 255,
},
PseudoOrder: []string{":method", ":authority", ":scheme", ":path"},
}
Characteristics:
- Large initial window (6MB)
- Large connection window (15MB)
- Maximum priority weight (255)
- Push disabled
Source: /home/daytona/workspace/source/pkg/client/fingerprint.go:66
Safari Profile
var h2Safari = H2Profile{
Settings: []http2.Setting{
{ID: http2.SettingHeaderTableSize, Val: 4096},
{ID: http2.SettingEnablePush, Val: 0},
{ID: http2.SettingInitialWindowSize, Val: 2097152},
{ID: http2.SettingMaxConcurrentStreams, Val: 100},
{ID: settingEnableConnectProtocol, Val: 1},
},
ConnectionWindow: 10485760,
Priority: http2.PriorityParam{
Weight: 254,
},
PseudoOrder: []string{":method", ":scheme", ":path", ":authority"},
}
Characteristics:
- Smaller header table (4KB)
- Medium initial window (2MB)
- Different pseudo-header order (
:authority last)
- CONNECT protocol enabled
- Max concurrent streams limit (100)
Source: /home/daytona/workspace/source/pkg/client/fingerprint.go:80
Firefox Profile
var h2Firefox = H2Profile{
Settings: []http2.Setting{
{ID: http2.SettingHeaderTableSize, Val: 65536},
{ID: http2.SettingInitialWindowSize, Val: 131072},
{ID: http2.SettingMaxFrameSize, Val: 16384},
},
ConnectionWindow: 12517377,
Priority: http2.PriorityParam{
StreamDep: 13,
Weight: 41,
},
PseudoOrder: []string{":method", ":path", ":authority", ":scheme"},
}
Characteristics:
- Small initial window (128KB)
- Stream dependency (13)
- Lower priority weight (41)
- Different pseudo-header order (
:path before :authority)
Source: /home/daytona/workspace/source/pkg/client/fingerprint.go:95
User-Agent Strings
Chrome on Windows
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
Source: /home/daytona/workspace/source/pkg/client/fingerprint.go:132
Chrome on macOS
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
Source: /home/daytona/workspace/source/pkg/client/fingerprint.go:128
Chrome on Linux
Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
Source: /home/daytona/workspace/source/pkg/client/fingerprint.go:130
Edge on Windows
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0
Source: /home/daytona/workspace/source/pkg/client/fingerprint.go:136
Safari on macOS
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15
Source: /home/daytona/workspace/source/pkg/client/fingerprint.go:187
Safari on iOS
Mozilla/5.0 (iPhone; CPU iPhone OS 17_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.1 Mobile/15E148 Safari/604.1
Source: /home/daytona/workspace/source/pkg/client/fingerprint.go:184
Firefox on Windows
Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:120.0) Gecko/20100101 Firefox/120.0
Source: /home/daytona/workspace/source/pkg/client/fingerprint.go:209
Firefox on macOS
Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:120.0) Gecko/20100101 Firefox/120.0
Source: /home/daytona/workspace/source/pkg/client/fingerprint.go:205
Firefox on Linux
Mozilla/5.0 (X11; Linux x86_64; rv:120.0) Gecko/20100101 Firefox/120.0
Source: /home/daytona/workspace/source/pkg/client/fingerprint.go:207
For Chromium-based browsers (Chrome, Edge, Brave), the following headers are automatically set:
sec-ch-ua
"Chromium";v="131", "Google Chrome";v="131", "Not/A)Brand";v="8"
Brand varies by browser:
- Chrome:
"Google Chrome"
- Edge:
"Microsoft Edge"
- Brave:
"Brave"
Source: /home/daytona/workspace/source/pkg/client/fingerprint.go:149
sec-ch-ua-mobile
Indicates non-mobile browser.
Source: /home/daytona/workspace/source/pkg/client/fingerprint.go:164
Platform-specific:
- Windows:
"Windows"
- macOS:
"macOS"
- Linux:
"Linux"
Source: /home/daytona/workspace/source/pkg/client/fingerprint.go:152
const HeaderOrderKey = "Header-Order"
Magic header key that controls the order of regular headers in HTTP/2 HEADERS frames and HTTP/1.1 requests. Its values specify header names in the desired wire order. The key itself is never sent.
Example:
req.Header[client.HeaderOrderKey] = []string{
"accept",
"accept-language",
"user-agent",
"referer",
}
If not set, headers are shuffled randomly (matching Chrome v106+ behavior).
Source: /home/daytona/workspace/source/pkg/client/header.go:11
const PseudoHeaderOrderKey = "Psuedo-Header-Order"
Magic header key that overrides the browser profile’s pseudo-header order for a single request. Values are pseudo-header names such as :method, :authority, :scheme, and :path.
Example:
req.Header[client.PseudoHeaderOrderKey] = []string{
":method",
":scheme",
":path",
":authority",
}
Source: /home/daytona/workspace/source/pkg/client/header.go:16
Usage Examples
Standard Browser Profiles
// Chrome on Windows (default)
c1, _ := client.New()
// Safari on macOS
c2, _ := client.New(
client.WithBrowser(client.BrowserSafari),
client.WithPlatform(client.PlatformMac),
client.WithBrowserVersion("17.0"),
)
// Firefox on Linux
c3, _ := client.New(
client.WithBrowser(client.BrowserFirefox),
client.WithPlatform(client.PlatformLinux),
client.WithBrowserVersion("120.0"),
)
// Edge on Windows
c4, _ := client.New(
client.WithBrowser(client.BrowserEdge),
client.WithBrowserVersion("120.0.0.0"),
)
Custom HTTP/2 Profile
import "golang.org/x/net/http2"
customH2 := client.H2Profile{
Settings: []http2.Setting{
{ID: http2.SettingHeaderTableSize, Val: 4096},
{ID: http2.SettingInitialWindowSize, Val: 65536},
},
ConnectionWindow: 1048576,
Priority: http2.PriorityParam{
Weight: 128,
},
PseudoOrder: []string{":method", ":path", ":authority", ":scheme"},
}
c, _ := client.New(
client.WithH2Profile(customH2),
)
Custom TLS Fingerprint
import utls "github.com/refraction-networking/utls"
c, _ := client.New(
client.WithClientHelloID(utls.HelloFirefox_105),
)
c, _ := client.New()
req, _ := http.NewRequest("GET", "https://example.com", nil)
req.Header.Set("accept", "text/html")
req.Header.Set("accept-language", "en-US")
req.Header.Set("cache-control", "no-cache")
// Control header wire order
req.Header[client.HeaderOrderKey] = []string{
"accept",
"cache-control",
"accept-language",
}
resp, _ := c.Do(req)
Safari iOS Profile
c, _ := client.New(
client.WithBrowser(client.BrowserSafari),
client.WithPlatform(client.PlatformIOS),
client.WithBrowserVersion("17.1"),
)
fmt.Println(c.UserAgent())
// Output: Mozilla/5.0 (iPhone; CPU iPhone OS 17_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.1 Mobile/15E148 Safari/604.1
Implementation Details
Profile Resolution
The resolveProfile function combines browser, version, and platform to generate a complete BrowserProfile:
- Select base profile (Chrome, Safari, or Firefox)
- Generate platform-specific User-Agent string
- Generate client hints for Chromium browsers
- Apply custom overrides if provided
Source: /home/daytona/workspace/source/pkg/client/fingerprint.go:111
TLS Handshake
TLS connections use the utls library to mimic browser TLS fingerprints:
- Chrome/Edge/Brave:
utls.HelloChrome_Auto
- Safari macOS:
utls.HelloSafari_Auto
- Safari iOS:
utls.HelloIOS_Auto
- Firefox:
utls.HelloFirefox_Auto
Source: /home/daytona/workspace/source/pkg/client/fingerprint.go:168
HTTP/2 Connection Preface
When negotiating HTTP/2 via ALPN, the client sends:
- HTTP/2 connection preface:
"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
- SETTINGS frame with browser-specific settings
- WINDOW_UPDATE frame if connection window > 65535
Source: /home/daytona/workspace/source/pkg/client/h2.go:48