fingerprint

package
v1.6.8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 12, 2026 License: MIT Imports: 18 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ApplySignatureAlgorithms added in v1.6.8

func ApplySignatureAlgorithms(exts []tls.TLSExtension, algs []tls.SignatureScheme)

ApplySignatureAlgorithms replaces the signature_algorithms extension's list in exts with algs when algs is non-empty. It operates on the shared []TLSExtension slice, so the ClientHelloID-direct path (H1, mutating a live UConn's Extensions) and the generated-spec path (H2/H3) use one override.

func Available

func Available() []string

Available returns a list of available preset names

func AvailableWithInfo added in v1.6.0

func AvailableWithInfo() map[string]PresetInfo

AvailableWithInfo returns a map of preset names to their supported protocols.

func ClientHelloIDName added in v1.6.5

func ClientHelloIDName(id tls.ClientHelloID) (string, bool)

ClientHelloIDName returns the canonical string name for a utls ClientHelloID. Suitable for round-trip JSON via Describe. Concrete names are preferred over "-auto" aliases that resolve to the same (Client, Version) pair.

Returns ("", false) for the zero-value ID and for IDs not registered in clientHelloIDs (e.g., randomized variants or hand-built IDs).

func DefaultPriorityTable added in v1.6.5

func DefaultPriorityTable() map[string]ResourcePriority

DefaultPriorityTable returns a copy of the package-level default priority table. Callers can use this as a starting point when constructing custom per-preset tables, or to inspect the values that will be emitted for presets that don't define their own.

The returned map is a fresh copy; mutating it does not affect future preset lookups.

func Describe added in v1.6.5

func Describe(name string) (string, error)

Describe returns a fully-resolved JSON dump of a preset's effective state.

All inheritance is flattened (no based_on in output). Default values produced by H2Config / H3Config getters are emitted explicitly, so a preset built with H2Config=nil and one built with H2Config set to the equivalent Chrome defaults describe to byte-identical JSON.

The result is suitable for round-tripping through LoadAndBuildPresetFromJSON to reconstruct an equivalent preset:

JSON1 := Describe(name)
p, _ := LoadAndBuildPresetFromJSON([]byte(JSON1))
Register(p.Name, p)
JSON2 := Describe(p.Name)
// JSON1 == JSON2 byte-for-byte

Returns an error if the preset is not registered or if it references a utls ClientHelloID that is not in the canonical name registry.

func JA3HasExtension added in v1.6.5

func JA3HasExtension(ja3, extID string) bool

JA3HasExtension checks if a JA3 string contains a specific TLS extension ID. The extensions field is the third comma-separated part, with dash-separated IDs.

func ParseJA3 added in v1.6.1

func ParseJA3(ja3 string, extras *JA3Extras) (*tls.ClientHelloSpec, error)

ParseJA3 parses a JA3 fingerprint string into a *tls.ClientHelloSpec. Format: TLSVersion,CipherSuites,Extensions,EllipticCurves,PointFormats Fields use dash-separated decimal values. If extras is nil, sensible defaults (matching modern Chrome) are used.

func PriorityFromUrgency added in v1.6.5

func PriorityFromUrgency(urgency uint8) uint16

PriorityFromUrgency converts an RFC 9218 urgency value into the RFC 7540 stream weight Chrome emits on the H2 HEADERS frame. Verified against Chrome 147 captures for urgency 0–4; the formula extrapolates linearly for 5–7 (Chrome doesn't emit those values in practice).

Formula: weight = 256 - (urgency * 73) / 2 (integer division).

Mapping: 0→256, 1→220, 2→183, 3→147, 4→110, 5→74, 6→37, 7→1.

The returned weight is the *effective* weight (1–256). Wire format uses weight-1; conversion happens at the transport boundary.

func PriorityHeaderFromResource added in v1.6.5

func PriorityHeaderFromResource(rp ResourcePriority) string

PriorityHeaderFromResource renders the RFC 9218 priority: HTTP header value for a ResourcePriority, applying Chrome's emission rules:

urgency=3 (default) + !incremental → ""        (omit the header)
urgency=3 (default) +  incremental → "i"
urgency≠3           + !incremental → "u=N"
urgency≠3           +  incremental → "u=N, i"

EmitHeader=false short-circuits to "" regardless of urgency/incremental (Chrome's async/defer-script behaviour). Caller must skip injection when the result is empty.

func Register added in v1.6.5

func Register(name string, preset *Preset)

Register adds a custom preset to the registry. It will be found by Get(). Nil presets are ignored. Silently overwrites any existing entry with the same name — use RegisterStrict to surface name collisions instead.

func RegisterStrict added in v1.6.5

func RegisterStrict(name string, preset *Preset) error

RegisterStrict adds a custom preset to the registry but errors out if the name is already taken — by another custom preset OR by a built-in. JSON loader paths use this so that user-supplied specs can't accidentally shadow a shipped preset like "chrome-latest". Callers who want to update a registered preset should call Unregister(name) first.

func ResolveClientHelloID added in v1.6.5

func ResolveClientHelloID(name string) (tls.ClientHelloID, error)

ResolveClientHelloID resolves a string name to a utls ClientHelloID. Names use lowercase-hyphenated convention (e.g., "chrome-146-windows").

func SpecFor added in v1.6.8

func SpecFor(id tls.ClientHelloID, seed int64, sigAlgs []tls.SignatureScheme) (*tls.ClientHelloSpec, error)

SpecFor generates the uTLS ClientHelloSpec for id at the given shuffle seed and overrides its signature_algorithms with sigAlgs (a no-op when sigAlgs is empty, so a stock preset keeps its byte-exact base). Callers pass the TCP list (Preset.SignatureAlgorithms) or the QUIC list (Preset.QUICSignatureAlgorithms). A drop-in replacement for tls.UTLSIdToSpecWithSeed so every transport spec path (H2/H3, fresh and PSK) can share one override point.

func Unregister added in v1.6.5

func Unregister(name string)

Unregister removes a custom preset from the registry.

Types

type AkamaiPresence added in v1.6.5

type AkamaiPresence struct {
	Settings        *HTTP2Settings
	PseudoOrder     []string
	SeenSettings    map[uint16]bool // SETTINGS IDs that appeared in the string
	HasWindowUpdate bool            // WINDOW_UPDATE field had a value
	HasStreamWeight bool            // PRIORITY field had a non-zero weight
}

AkamaiPresence reports which fields a parsed Akamai shorthand actually specified, so callers can distinguish "set to value X" from "absent / default zero". Without this distinction, applyHTTP2 cannot tell whether to let the akamai value override an inherited discrete-field value.

func ParseAkamaiDetailed added in v1.6.5

func ParseAkamaiDetailed(akamai string) (*AkamaiPresence, error)

ParseAkamaiDetailed parses an Akamai shorthand and reports which fields were actually present. The plain ParseAkamai delegates to this. Callers that need to overlay an akamai shorthand on top of inherited / discrete fields use this so they only override the slots the shorthand specifies.

type ClientHints added in v1.0.1

type ClientHints struct {
	// Low-entropy hints (always sent by Chrome)
	UA         string // Sec-Ch-Ua
	UAMobile   string // Sec-Ch-Ua-Mobile
	UAPlatform string // Sec-Ch-Ua-Platform

	// High-entropy hints (only sent after Accept-CH)
	UAArch            string // Sec-Ch-Ua-Arch
	UABitness         string // Sec-Ch-Ua-Bitness
	UAFullVersionList string // Sec-Ch-Ua-Full-Version-List
	UAModel           string // Sec-Ch-Ua-Model
	UAPlatformVersion string // Sec-Ch-Ua-Platform-Version
	UAWow64           string // Sec-Ch-Ua-Wow64
}

ClientHints contains browser client hint headers

func GenerateClientHints deprecated added in v1.0.1

func GenerateClientHints(chromeVersion string, platform PlatformInfo, includeHighEntropy bool) ClientHints

GenerateClientHints generates client hint headers for Chrome.

Deprecated: this builds the hints from a bare version + platform and so cannot keep the GREASE brand token / order in sync with a preset's sec-ch-ua. It is no longer used in production. Use Preset.ResolveClientHints, which derives coherent hints from the preset itself.

type ClientHintsProfile added in v1.6.8

type ClientHintsProfile struct {
	FullVersionList string // sec-ch-ua-full-version-list; "" -> derived from sec-ch-ua (brands/order/GREASE preserved, versions expanded)
	PlatformVersion string // sec-ch-ua-platform-version override; "" -> platform default (Linux is "")
	Arch            string // sec-ch-ua-arch; "" -> platform default
	Bitness         string // sec-ch-ua-bitness; "" -> platform default
	Model           string // sec-ch-ua-model; "" -> platform default (desktop is "")
	Wow64           string // sec-ch-ua-wow64; "" -> "?0"
}

ClientHintsProfile holds preset-level values for the high-entropy UA client hints (the ones Chrome only sends after a host advertises Accept-CH). Every field is optional: an empty field is derived coherently from the preset's low-entropy sec-ch-ua trio and platform (see Preset.ResolveClientHints), so a preset only needs to spell out what differs from the coherent default. This is the single source of truth that keeps full-version-list, arch, platform-version etc. in lockstep with sec-ch-ua + User-Agent.

type ClientHintsSpec added in v1.6.8

type ClientHintsSpec struct {
	FullVersionList string `json:"full_version_list,omitempty"` // sec-ch-ua-full-version-list (exact build from a real capture)
	PlatformVersion string `json:"platform_version,omitempty"`  // sec-ch-ua-platform-version override
	Arch            string `json:"arch,omitempty"`              // sec-ch-ua-arch
	Bitness         string `json:"bitness,omitempty"`           // sec-ch-ua-bitness
	Model           string `json:"model,omitempty"`             // sec-ch-ua-model
	Wow64           string `json:"wow64,omitempty"`             // sec-ch-ua-wow64
}

ClientHintsSpec defines high-entropy UA client hint overrides for a preset. Every field is optional; an omitted field is derived from the sec-ch-ua trio (see Preset.ResolveClientHints) so a preset only needs to spell out what differs from the coherent default. Inherited via based_on like other blocks.

type FetchDest added in v1.0.1

type FetchDest string

FetchDest represents the Sec-Fetch-Dest header value

const (
	FetchDestDocument      FetchDest = "document"
	FetchDestEmbed         FetchDest = "embed"
	FetchDestFont          FetchDest = "font"
	FetchDestImage         FetchDest = "image"
	FetchDestManifest      FetchDest = "manifest"
	FetchDestMedia         FetchDest = "media"
	FetchDestObject        FetchDest = "object"
	FetchDestReport        FetchDest = "report"
	FetchDestScript        FetchDest = "script"
	FetchDestServiceWorker FetchDest = "serviceworker"
	FetchDestSharedWorker  FetchDest = "sharedworker"
	FetchDestStyle         FetchDest = "style"
	FetchDestWorker        FetchDest = "worker"
	FetchDestXHR           FetchDest = "empty" // XHR/fetch uses "empty"
)

type FetchMode added in v1.0.1

type FetchMode string

FetchMode represents the Sec-Fetch-Mode header value

const (
	// FetchModeNavigate is for document navigation (clicking links, typing URLs)
	FetchModeNavigate FetchMode = "navigate"
	// FetchModeCORS is for cross-origin requests (fetch API with CORS)
	FetchModeCORS FetchMode = "cors"
	// FetchModeNoCORS is for simple requests that don't trigger CORS
	FetchModeNoCORS FetchMode = "no-cors"
	// FetchModeSameOrigin is for same-origin requests
	FetchModeSameOrigin FetchMode = "same-origin"
	// FetchModeWebSocket is for WebSocket connections
	FetchModeWebSocket FetchMode = "websocket"
)

type FetchSite added in v1.0.1

type FetchSite string

FetchSite represents the Sec-Fetch-Site header value

const (
	FetchSiteNone       FetchSite = "none"        // Direct navigation (typing URL)
	FetchSiteSameOrigin FetchSite = "same-origin" // Same origin request
	FetchSiteSameSite   FetchSite = "same-site"   // Same site but different subdomain
	FetchSiteCrossSite  FetchSite = "cross-site"  // Different site entirely
)

type H2FingerprintConfig added in v1.6.5

type H2FingerprintConfig struct {
	HPACKHeaderOrder    []string // HPACK wire encoding order. nil = Chrome 143 default.
	HPACKIndexingPolicy string   // "chrome"/"never"/"always"/"default". "" = "chrome".
	HPACKNeverIndex     []string // Headers never HPACK-indexed. nil = Chrome default.
	StreamPriorityMode  string   // "chrome"/"default". "" = "chrome".
	DisableCookieSplit  *bool    // nil = true (single field). Chrome+Firefox crumble (false); Safari single (true).
	SettingsOrder       []uint16 // H2 SETTINGS frame ID order. nil = dynamic from HTTP2Settings.
	PseudoHeaderOrder   []string // Pseudo-header order. nil = heuristic (Chrome m,a,s,p / Safari m,s,p,a).

	// PriorityTable maps sec-fetch-dest values to RFC 7540 stream priorities and
	// the matching RFC 9218 priority: header value. Populated for browsers (e.g.
	// Chrome 147 desktop) that emit a different urgency per resource type.
	//
	// When nil, the transport uses HTTP2Settings.StreamWeight / StreamExclusive
	// for every request — the legacy single-weight behaviour. When non-nil, the
	// transport selects an entry based on the request's sec-fetch-dest header,
	// derives the H2 wire weight from urgency via PriorityFromUrgency, and
	// injects the priority: header per the RFC 9218 emission rules.
	//
	// Map keys are sec-fetch-dest values exactly as Chrome emits them
	// ("document", "image", "script", "empty", etc.). Lookups are case-sensitive.
	PriorityTable map[string]ResourcePriority
}

H2FingerprintConfig controls HTTP/2 fingerprinting behavior beyond SETTINGS frame values. When nil on a Preset, all getters return Chrome defaults. Individual nil/zero fields also fall back to Chrome defaults, so you can override just the fields you need.

type H3FingerprintConfig added in v1.6.5

type H3FingerprintConfig struct {
	QPACKMaxTableCapacity     *uint64 // nil = 65536 (Chrome). Safari heuristic fallback.
	QPACKBlockedStreams       *uint64 // nil = 100
	MaxFieldSectionSize       *uint64 // nil = 262144 (Chrome). 0 to omit (Safari).
	EnableDatagrams           *bool   // nil = true (Chrome). Safari heuristic fallback.
	QUICInitialPacketSize     *uint16 // nil = 1250 (Chrome). MASQUE overrides to 1350.
	QUICMaxIncomingStreams    *int64  // nil = 100
	QUICMaxIncomingUniStreams *int64  // nil = 103
	QUICAllow0RTT             *bool   // nil = true
	QUICChromeStyleInitial    *bool   // nil = true
	QUICDisableHelloScramble  *bool   // nil = true
	QUICTransportParamOrder   string  // "chrome"/"random". "" = "chrome".
	QUICConnectionIDLength    *int    // nil = 0 (Chrome empty SCID). Firefox uses 8.
	QUICMaxDatagramFrameSize  *uint64 // nil = 65536 (Chrome). 0 to use quic-go default (16383).
	MaxResponseHeaderBytes    *uint64 // nil = 262144
	SendGreaseFrames          *bool   // nil = true

	// QUIC flow-control windows. quic-go translates these to wire transport
	// parameters initial_max_data (4) and initial_max_stream_data_* (5/6/7).
	// nil = quic-go default (~7.5 MB conn, ~512 KB stream). Safari/iOS Chrome
	// uses larger conn (16 MB) and smaller per-stream (2 MB) — set both to
	// match.
	QUICInitialStreamReceiveWindow     *uint64 // nil = quic-go default. iOS Chrome sends 2097152.
	QUICInitialConnectionReceiveWindow *uint64 // nil = quic-go default. iOS Chrome sends 16777216.
}

H3FingerprintConfig controls HTTP/3 and QUIC fingerprinting behavior. When nil on a Preset, all getters return Chrome defaults (with Safari fallback for presets that have NoRFC7540Priorities set). Individual nil fields fall back to Chrome defaults independently.

type HTTP2SettingSpec added in v1.6.5

type HTTP2SettingSpec struct {
	ID    uint16 `json:"id"`
	Value uint32 `json:"value"`
}

HTTP2SettingSpec represents a single HTTP/2 SETTINGS frame entry.

type HTTP2Settings

type HTTP2Settings struct {
	HeaderTableSize      uint32
	EnablePush           bool
	MaxConcurrentStreams uint32
	InitialWindowSize    uint32
	MaxFrameSize         uint32
	MaxHeaderListSize    uint32
	// Window update and stream settings
	ConnectionWindowUpdate uint32
	StreamWeight           uint16 // Chrome sends 255 on wire (set to 256, code does -1)
	StreamExclusive        bool
	// RFC 9218 - disables RFC 7540 stream priorities
	NoRFC7540Priorities bool
}

HTTP2Settings contains HTTP/2 connection settings

func ParseAkamai added in v1.6.1

func ParseAkamai(akamai string) (*HTTP2Settings, []string, error)

ParseAkamai parses an Akamai HTTP/2 fingerprint string into HTTP2Settings and pseudo-header order.

Format: SETTINGS|WINDOW_UPDATE|PRIORITY|PSEUDO_HEADER_ORDER

SETTINGS: semicolon-separated "id:value" pairs (e.g., "1:65536;3:1000;4:6291456") WINDOW_UPDATE: connection-level window update value PRIORITY: "weight" or "0" (stream weight; 0 means default/not sent) PSEUDO_HEADER_ORDER: comma-separated single-char pseudo-header identifiers

m = :method, a = :authority, s = :scheme, p = :path

Example (Chrome): "1:65536;2:0;4:6291456;6:262144|15663105|0|m,a,s,p"

type HTTP2Spec added in v1.6.5

type HTTP2Spec struct {
	// Akamai string (parsed first, then individual fields overlay)
	Akamai string `json:"akamai,omitempty"`

	// Individual SETTINGS fields (overlay on top of akamai if both set)
	HeaderTableSize        *uint32 `json:"header_table_size,omitempty"`
	EnablePush             *bool   `json:"enable_push,omitempty"`
	MaxConcurrentStreams   *uint32 `json:"max_concurrent_streams,omitempty"`
	InitialWindowSize      *uint32 `json:"initial_window_size,omitempty"`
	MaxFrameSize           *uint32 `json:"max_frame_size,omitempty"`
	MaxHeaderListSize      *uint32 `json:"max_header_list_size,omitempty"`
	ConnectionWindowUpdate *uint32 `json:"connection_window_update,omitempty"`
	StreamWeight           *uint16 `json:"stream_weight,omitempty"`
	StreamExclusive        *bool   `json:"stream_exclusive,omitempty"`
	NoRFC7540Priorities    *bool   `json:"no_rfc7540_priorities,omitempty"`

	// H2 fingerprinting config
	Settings      []HTTP2SettingSpec `json:"settings,omitempty"`
	SettingsOrder []uint16           `json:"settings_order,omitempty"`
	PseudoOrder   []string           `json:"pseudo_order,omitempty"`

	// HPACK config
	HPACKHeaderOrder    []string `json:"hpack_header_order,omitempty"`
	HPACKIndexingPolicy *string  `json:"hpack_indexing_policy,omitempty"` // "chrome","never","always","default"
	HPACKNeverIndex     []string `json:"hpack_never_index,omitempty"`
	StreamPriorityMode  *string  `json:"stream_priority_mode,omitempty"` // "chrome","default"
	DisableCookieSplit  *bool    `json:"disable_cookie_split,omitempty"`

	// PriorityTable maps sec-fetch-dest values to per-resource priority
	// settings. When populated, the transport emits a per-request RFC 7540
	// stream weight (derived from urgency) and RFC 9218 priority: header
	// for each request based on its sec-fetch-dest. When omitted, the
	// preset's static StreamWeight / StreamExclusive is used for every
	// request (legacy single-weight behaviour).
	PriorityTable map[string]ResourcePrioritySpec `json:"priority_table,omitempty"`
}

HTTP2Spec defines HTTP/2 fingerprint configuration.

type HTTP3Spec added in v1.6.5

type HTTP3Spec struct {
	QPACKMaxTableCapacity     *uint64 `json:"qpack_max_table_capacity,omitempty"`
	QPACKBlockedStreams       *uint64 `json:"qpack_blocked_streams,omitempty"`
	MaxFieldSectionSize       *uint64 `json:"max_field_section_size,omitempty"`
	EnableDatagrams           *bool   `json:"enable_datagrams,omitempty"`
	QUICInitialPacketSize     *uint16 `json:"quic_initial_packet_size,omitempty"`
	QUICMaxIncomingStreams    *int64  `json:"quic_max_incoming_streams,omitempty"`
	QUICMaxIncomingUniStreams *int64  `json:"quic_max_incoming_uni_streams,omitempty"`
	QUICAllow0RTT             *bool   `json:"quic_allow_0rtt,omitempty"`
	QUICChromeStyleInitial    *bool   `json:"quic_chrome_style_initial,omitempty"`
	QUICDisableHelloScramble  *bool   `json:"quic_disable_hello_scramble,omitempty"`
	QUICTransportParamOrder   *string `json:"quic_transport_param_order,omitempty"` // "chrome","random"
	QUICConnectionIDLength    *int    `json:"quic_connection_id_length,omitempty"`
	QUICMaxDatagramFrameSize  *uint64 `json:"quic_max_datagram_frame_size,omitempty"`
	MaxResponseHeaderBytes    *uint64 `json:"max_response_header_bytes,omitempty"`
	SendGreaseFrames          *bool   `json:"send_grease_frames,omitempty"`

	// QUIC flow-control windows. These map to quic.Config fields and ultimately
	// to wire transport parameters initial_max_data (4) and initial_max_stream_data_*
	// (5/6/7). nil = quic-go default. iOS Chrome / Safari uses larger conn (16 MiB)
	// + smaller per-stream (2 MiB) than Chrome desktop.
	QUICInitialStreamReceiveWindow     *uint64 `json:"quic_initial_stream_receive_window,omitempty"`
	QUICInitialConnectionReceiveWindow *uint64 `json:"quic_initial_connection_receive_window,omitempty"`
}

HTTP3Spec defines HTTP/3 and QUIC fingerprint configuration.

type HeaderCoherence added in v1.0.1

type HeaderCoherence struct {
	// contains filtered or unexported fields
}

HeaderCoherence provides methods for generating coherent request headers

func NewHeaderCoherence added in v1.0.1

func NewHeaderCoherence(preset *Preset) *HeaderCoherence

NewHeaderCoherence creates a new HeaderCoherence helper

func (*HeaderCoherence) ApplyToHeaders added in v1.0.1

func (h *HeaderCoherence) ApplyToHeaders(headers map[string]string, ctx RequestContext)

ApplyToHeaders applies coherent headers to the given header map

func (*HeaderCoherence) GenerateNavigationHeaders added in v1.0.1

func (h *HeaderCoherence) GenerateNavigationHeaders() map[string]string

GenerateNavigationHeaders returns complete headers for page navigation

func (*HeaderCoherence) GenerateXHRHeaders added in v1.0.1

func (h *HeaderCoherence) GenerateXHRHeaders(referrer, targetURL string) map[string]string

GenerateXHRHeaders returns complete headers for XHR/fetch requests

type HeaderPair added in v1.1.1

type HeaderPair struct {
	Key   string
	Value string
}

HeaderPair represents a single header key-value pair for ordered headers

type HeaderPairSpec added in v1.6.5

type HeaderPairSpec struct {
	Key   string `json:"key"`
	Value string `json:"value"`
}

HeaderPairSpec is a key-value pair for ordered headers in JSON.

type HeaderSpec added in v1.6.5

type HeaderSpec struct {
	UserAgent string            `json:"user_agent,omitempty"`
	Values    map[string]string `json:"values,omitempty"`
	Order     []HeaderPairSpec  `json:"order,omitempty"`
}

HeaderSpec defines header fingerprint configuration.

type JA3Extras added in v1.6.1

type JA3Extras struct {
	SignatureAlgorithms           []tls.SignatureScheme
	DelegatedCredentialAlgorithms []tls.SignatureScheme // for ext 34; nil = Chrome defaults
	ALPN                          []string
	CertCompAlgs                  []tls.CertCompressionAlgo
	PermuteExtensions             bool
	RecordSizeLimit               uint16 // default: 0x4001
	KeyShareCurves                int    // number of curves to send key shares for; 0 = 1 (default)
}

JA3Extras provides extension data that JA3 cannot capture. JA3 only encodes extension IDs, not the data within them.

type JA3ExtrasSpec added in v1.6.5

type JA3ExtrasSpec struct {
	SignatureAlgorithms           []uint16 `json:"signature_algorithms,omitempty"`
	DelegatedCredentialAlgorithms []uint16 `json:"delegated_credential_algorithms,omitempty"`
	ALPN                          []string `json:"alpn,omitempty"`
	CertCompression               []string `json:"cert_compression,omitempty"`
	PermuteExtensions             *bool    `json:"permute_extensions,omitempty"`
	RecordSizeLimit               *uint16  `json:"record_size_limit,omitempty"`
	KeyShareCurves                *int     `json:"key_share_curves,omitempty"`
}

JA3ExtrasSpec is the JSON representation of JA3Extras.

type PlatformInfo

type PlatformInfo struct {
	UserAgentOS        string // e.g., "(Windows NT 10.0; Win64; x64)" or "(X11; Linux x86_64)"
	Platform           string // e.g., "Windows", "Linux", "macOS"
	Arch               string // e.g., "x86", "arm"
	PlatformVersion    string // e.g., "10.0.0", "6.12.0", "14.7.0"
	FirefoxUserAgentOS string // Firefox has slightly different format
}

PlatformInfo contains platform-specific header values

func GetPlatformInfo

func GetPlatformInfo() PlatformInfo

GetPlatformInfo returns platform-specific info based on runtime OS

type PoolSpec added in v1.6.5

type PoolSpec struct {
	Name     string       `json:"name"`
	Strategy string       `json:"strategy"` // "random" or "round-robin"
	Presets  []PresetSpec `json:"presets"`
}

PoolSpec defines a pool of presets for rotation.

type PoolStrategy added in v1.6.5

type PoolStrategy int

PoolStrategy determines how presets are selected from a pool.

const (
	// PoolRandom selects a random preset each time.
	PoolRandom PoolStrategy = iota
	// PoolRoundRobin cycles through presets sequentially.
	PoolRoundRobin
)

type Preset

type Preset struct {
	Name                 string
	ClientHelloID        tls.ClientHelloID // For TCP/TLS (HTTP/1.1, HTTP/2)
	PSKClientHelloID     tls.ClientHelloID // For TCP/TLS with PSK (session resumption)
	QUICClientHelloID    tls.ClientHelloID // For QUIC/HTTP/3 (different TLS extensions)
	QUICPSKClientHelloID tls.ClientHelloID // For QUIC/HTTP/3 with PSK (session resumption)
	UserAgent            string
	Headers              map[string]string  // For backward compatibility
	HeaderOrder          []HeaderPair       // Ordered headers for HTTP/2
	ClientHints          ClientHintsProfile // High-entropy UA client hint overrides; empty fields are derived from sec-ch-ua (see Preset.ResolveClientHints)
	HTTP2Settings        HTTP2Settings
	TCPFingerprint       TCPFingerprint
	SupportHTTP3         bool
	DisableHTTP2         bool                 // When true, auto mode skips HTTP/2 and goes straight to HTTP/1.1 (zero value = H2 enabled)
	H2Config             *H2FingerprintConfig // nil = Chrome defaults for all H2 fingerprinting
	H3Config             *H3FingerprintConfig // nil = Chrome defaults for all H3/QUIC fingerprinting
	JA3                  string               // JA3 fingerprint string. When set, parsed fresh per connection instead of using ClientHelloID.
	JA3Extras            *JA3Extras           // Supplements JA3 parsing. nil = Chrome defaults.
	BasedOn              string               // For custom presets: name of the parent preset (used by inheritance-loop detection). Empty for built-ins.

	// SignatureAlgorithms, when non-empty, replaces the signature_algorithms
	// extension emitted on TCP (HTTP/1.1 + HTTP/2), on top of whatever base spec
	// the ClientHelloID (or JA3) produces. It lets a preset keep a byte-exact
	// hand-tuned base spec (correct ALPS/ECH/key_share/GREASE ordering) while
	// changing ONLY the sig-algs — e.g. adding Chrome 150's ML-DSA post-quantum
	// codepoints (0x0904-0x0906) on top of the Chrome 146 base. Values are raw
	// SignatureScheme (uint16) codepoints, so schemes uTLS has no named constant
	// for (like ML-DSA) are still emitted verbatim.
	SignatureAlgorithms []tls.SignatureScheme

	// QUICSignatureAlgorithms is the HTTP/3 (QUIC) counterpart of
	// SignatureAlgorithms. It is separate because a browser's QUIC ClientHello can
	// advertise a DIFFERENT sig-algs set than its TCP one — e.g. Chrome 150 sends
	// ML-DSA on TCP but NOT on QUIC (QUIC anti-amplification limits make large PQ
	// certificate chains impractical), and adds rsa_pkcs1_sha1 there instead.
	// Empty = leave the QUIC base ClientHelloID untouched.
	QUICSignatureAlgorithms []tls.SignatureScheme
}

Preset represents a browser fingerprint configuration

func AndroidChrome143 added in v1.0.5

func AndroidChrome143() *Preset

AndroidChrome143 returns Chrome 143 on Android fingerprint preset Note: Chrome on Android uses Chrome's TLS fingerprint (not WebKit restricted like iOS)

func AndroidChrome144 added in v1.5.10

func AndroidChrome144() *Preset

AndroidChrome144 returns Chrome 144 on Android fingerprint preset

func AndroidChrome145 added in v1.6.0

func AndroidChrome145() *Preset

AndroidChrome145 returns Chrome 145 on Android fingerprint preset

func AndroidChrome146 added in v1.6.1

func AndroidChrome146() *Preset

AndroidChrome146 returns Chrome 146 on Android fingerprint preset

func AndroidChrome147 added in v1.6.5

func AndroidChrome147() *Preset

AndroidChrome147 returns Chrome 147 on Android. Same diff pattern as desktop (UA bump + sec-ch-ua brand rotation); inherits Linux-flavored TLS from chrome-146-android. Falls back to AndroidChrome146.

func AndroidChrome148 added in v1.6.6

func AndroidChrome148() *Preset

AndroidChrome148 returns Chrome 148 on Android. Same two-header diff pattern as the desktop variants. Falls back to AndroidChrome147.

func AndroidChrome150 added in v1.6.8

func AndroidChrome150() *Preset

AndroidChrome150 returns Chrome 150 on Android. Android Chrome runs the same Chromium/BoringSSL stack as desktop (the iOS line is the WebKit exception), and the Android TLS base is HelloChrome_146_Linux — identical to desktop Linux — so this preset carries the SAME ML-DSA signature_algorithms override as the desktop chrome-150 line (ML-DSA on TCP, none on QUIC). Headers are the reduced-UA mobile bump: Chrome/150 with the frozen "Android 10; K" model, sec-ch-ua-mobile ?1, sec-ch-ua-platform "Android", and the version-keyed (platform-independent) sec-ch-ua brand shared with desktop 150.

DERIVED (not yet captured from a device): the TLS/JA4 and reduced UA/sec-ch-ua are deterministic, but whether Chrome ships the ML-DSA sig-algs field trial on Android is assumed to match desktop pending a real Android 150 capture. Falls back to AndroidChrome148 if the JSON didn't load.

func BuildPreset added in v1.6.5

func BuildPreset(spec *PresetSpec) (*Preset, error)

BuildPreset converts a PresetSpec (parsed from JSON) into a Preset. If based_on is set, clones the base preset first and overlays changes.

func Chrome133

func Chrome133() *Preset

Chrome133 returns the Chrome 133 fingerprint preset

func Chrome141

func Chrome141() *Preset

Chrome141 returns the Chrome 141 fingerprint preset

func Chrome143

func Chrome143() *Preset

Chrome143 returns the Chrome 143 fingerprint preset with platform-specific TLS fingerprint

func Chrome143Linux added in v1.0.1

func Chrome143Linux() *Preset

Chrome143Linux returns Chrome 143 with Linux platform and fixed TLS extension order

func Chrome143Windows

func Chrome143Windows() *Preset

Chrome143Windows returns Chrome 143 with Windows platform and fixed TLS extension order

func Chrome143macOS added in v1.0.1

func Chrome143macOS() *Preset

Chrome143macOS returns Chrome 143 with macOS platform and fixed TLS extension order

func Chrome144 added in v1.5.10

func Chrome144() *Preset

Chrome144 returns the Chrome 144 fingerprint preset with platform-specific TLS fingerprint

func Chrome144Linux added in v1.5.10

func Chrome144Linux() *Preset

Chrome144Linux returns Chrome 144 with Linux platform

func Chrome144Windows added in v1.5.10

func Chrome144Windows() *Preset

Chrome144Windows returns Chrome 144 with Windows platform

func Chrome144macOS added in v1.5.10

func Chrome144macOS() *Preset

Chrome144macOS returns Chrome 144 with macOS platform

func Chrome145 added in v1.6.0

func Chrome145() *Preset

Chrome145 returns the Chrome 145 fingerprint preset with platform-specific TLS fingerprint

func Chrome145Linux added in v1.6.0

func Chrome145Linux() *Preset

Chrome145Linux returns Chrome 145 with Linux platform

func Chrome145Windows added in v1.6.0

func Chrome145Windows() *Preset

Chrome145Windows returns Chrome 145 with Windows platform

func Chrome145macOS added in v1.6.0

func Chrome145macOS() *Preset

Chrome145macOS returns Chrome 145 with macOS platform

func Chrome146 added in v1.6.1

func Chrome146() *Preset

Chrome146 returns the Chrome 146 fingerprint preset with platform-specific TLS fingerprint

func Chrome146Linux added in v1.6.1

func Chrome146Linux() *Preset

Chrome146Linux returns Chrome 146 with Linux platform

func Chrome146Windows added in v1.6.1

func Chrome146Windows() *Preset

Chrome146Windows returns Chrome 146 with Windows platform

func Chrome146macOS added in v1.6.1

func Chrome146macOS() *Preset

Chrome146macOS returns Chrome 146 with macOS platform

func Chrome147 added in v1.6.5

func Chrome147() *Preset

Chrome147 returns the Chrome 147 fingerprint preset auto-detected from the running OS. Mirrors Chrome146's platform-aware behavior.

func Chrome147Linux added in v1.6.5

func Chrome147Linux() *Preset

Chrome147Linux returns Chrome 147 with Linux platform. See Chrome147Windows.

func Chrome147Windows added in v1.6.5

func Chrome147Windows() *Preset

Chrome147Windows returns Chrome 147 with Windows platform.

The preset is provided by the embedded JSON registry (fingerprint/embedded/chrome-147-windows.json), which inherits TLS bytes from chrome-146-windows and overrides only the User-Agent and sec-ch-ua header. If the embedded JSON failed to load, the factory falls back to Chrome146Windows so callers don't get a Chrome146 fallback by accident.

func Chrome147macOS added in v1.6.5

func Chrome147macOS() *Preset

Chrome147macOS returns Chrome 147 with macOS platform. See Chrome147Windows.

func Chrome148 added in v1.6.6

func Chrome148() *Preset

Chrome148 returns the Chrome 148 fingerprint preset auto-detected from the running OS.

func Chrome148Linux added in v1.6.6

func Chrome148Linux() *Preset

Chrome148Linux returns Chrome 148 on Linux. See Chrome148Windows.

func Chrome148Windows added in v1.6.6

func Chrome148Windows() *Preset

Chrome148Windows returns Chrome 148 on Windows. Wire-level diff vs 147 is two header values: User-Agent version bump and sec-ch-ua brand list rotation (Chromium moved to first position, GREASE brand "Not.A/Brand" v="8" became "Not/A)Brand" v="99"). TLS extension order keeps shuffling per-handshake the same way 147 already does. Embedded JSON only overrides the two header values; everything else inherits from chrome-147-windows. Falls back to Chrome147Windows if the JSON didn't load.

func Chrome148macOS added in v1.6.6

func Chrome148macOS() *Preset

Chrome148macOS returns Chrome 148 on macOS. See Chrome148Windows.

func Chrome149 added in v1.6.7

func Chrome149() *Preset

Chrome149 returns the Chrome 149 fingerprint preset auto-detected from the running OS.

func Chrome149Linux added in v1.6.7

func Chrome149Linux() *Preset

Chrome149Linux returns Chrome 149 on Linux. See Chrome149Windows.

func Chrome149Windows added in v1.6.7

func Chrome149Windows() *Preset

Chrome149Windows returns Chrome 149 on Windows. The wire-level fingerprint is byte-identical to 148 (verified against a real Chrome 149 capture: JA4 t13d1516h2_8daaf6152771_d8a2da3f94cd, peetprint 1d4ffe9b0e34acac0bd883fa7f79d7b5, and Akamai H2 1:65536;2:0;4:6291456;6:262144|15663105|0|m,a,s,p all match 148). The only diff is two header values: the User-Agent version bump and a sec-ch-ua brand rotation (Google Chrome moved to first position, GREASE brand became "Not)A;Brand" v="24"). Embedded JSON overrides just those; everything else inherits from chrome-148-windows. Falls back to Chrome148Windows if the JSON didn't load.

func Chrome149macOS added in v1.6.7

func Chrome149macOS() *Preset

Chrome149macOS returns Chrome 149 on macOS. See Chrome149Windows.

func Chrome150 added in v1.6.8

func Chrome150() *Preset

Chrome150 returns the Chrome 150 fingerprint preset auto-detected from the running OS.

func Chrome150Linux added in v1.6.8

func Chrome150Linux() *Preset

Chrome150Linux returns Chrome 150 on Linux. See Chrome150Windows.

func Chrome150Windows added in v1.6.8

func Chrome150Windows() *Preset

Chrome150Windows returns Chrome 150 on Windows. The base TLS/H2/QUIC fingerprint is inherited byte-for-byte from the chrome-149 chain; Chrome 150 adds two things over 149, both captured from a real Chrome 150:

  • TCP signature_algorithms now prepend the three ML-DSA post-quantum codepoints (0x0904-0x0906 = ML-DSA-44/65/87, draft-ietf-tls-mldsa), giving JA4 t13d1516h2_8daaf6152771_806a8c22fdea. QUIC is left unchanged (Chrome does NOT advertise ML-DSA over QUIC — anti-amplification limits — so JA4 stays q13d0311h3_55b375c5d22e_653d80c3fe9d).
  • User-Agent bump and a sec-ch-ua brand rotation (GREASE brand became "Not;A=Brand" v="8", moved to first position).

Embedded JSON overrides just those; everything else inherits. Falls back to Chrome149Windows if the JSON didn't load.

func Chrome150macOS added in v1.6.8

func Chrome150macOS() *Preset

Chrome150macOS returns Chrome 150 on macOS. See Chrome150Windows.

func Firefox133

func Firefox133() *Preset

Firefox133 returns the Firefox 133 fingerprint preset

func Firefox148 added in v1.6.5

func Firefox148() *Preset

Firefox148 returns the Firefox 148 fingerprint preset using JA3 for TLS. Uses the exact JA3 fingerprint captured from real Firefox 148 on Linux.

func Get

func Get(name string) *Preset

Get returns a preset by name. Checks custom registry first, then built-in presets. Falls back to Chrome146 if not found.

func GetStrict added in v1.6.5

func GetStrict(name string) *Preset

GetStrict returns a preset by name, returning nil if not found (no fallback).

func IOSChrome143 added in v1.0.5

func IOSChrome143() *Preset

IOSChrome143 returns Chrome 143 on iOS fingerprint preset Note: iOS Chrome uses WebKit (Apple requirement), so it has Safari's TLS AND HTTP/2 fingerprint WebKit doesn't support Client Hints, so no sec-ch-ua headers

func IOSChrome144 added in v1.5.10

func IOSChrome144() *Preset

IOSChrome144 returns Chrome 144 on iOS fingerprint preset Note: iOS Chrome uses WebKit (Apple requirement), so it has Safari's TLS AND HTTP/2 fingerprint WebKit doesn't support Client Hints, so no sec-ch-ua headers

func IOSChrome145 added in v1.6.0

func IOSChrome145() *Preset

IOSChrome145 returns Chrome 145 on iOS fingerprint preset Note: iOS Chrome uses WebKit (Apple requirement), so it has Safari's TLS AND HTTP/2 fingerprint WebKit doesn't support Client Hints, so no sec-ch-ua headers

func IOSChrome146 added in v1.6.1

func IOSChrome146() *Preset

IOSChrome146 returns Chrome 146 on iOS fingerprint preset Note: iOS Chrome uses WebKit (Apple requirement), so it has Safari's TLS AND HTTP/2 fingerprint WebKit doesn't support Client Hints, so no sec-ch-ua headers

func IOSChrome147 added in v1.6.5

func IOSChrome147() *Preset

IOSChrome147 returns Chrome 147 on iOS. Embedded JSON only overrides the User-Agent (CriOS major version) — everything else (no sec-ch-ua due to WebKit, Safari TLS via HelloIOS_18, Safari H2 config) inherits unchanged from chrome-146-ios. Falls back to IOSChrome146 if the JSON didn't load.

func IOSChrome148 added in v1.6.5

func IOSChrome148() *Preset

IOSChrome148 returns Chrome 148 on iOS — captured against real iOS Chrome 148.0.7778.47, with deeper changes than the 147 bump:

  • User-Agent: iOS 26_4_2, CriOS/148.0.7778.47
  • HTTP/2 wire: SettingsOrder [2,3,4,9] (drops MAX_FRAME_SIZE), pseudo-order m,s,a,p (was m,s,p,a in safariH2Config), ConnectionWindowUpdate 10420225
  • HTTP/2 headers: priority added, sec-fetch-user removed, accept-encoding gains zstd, header order completely reshuffled
  • HTTP/3 QUIC: 2 MiB stream / 16 MiB connection flow control, 8 max incoming uni streams (vs Chrome's 103). TLS bytes (HelloIOS_18, HelloIOS_18_QUIC) match Chrome 146 iOS exactly — no utls update needed

Note: chrome-146-ios and chrome-147-ios are intentionally NOT updated; this preset captures the deeper iOS-Chrome-specific divergences as of 148 only.

func IOSChrome150 added in v1.6.8

func IOSChrome150() *Preset

IOSChrome150 returns Chrome 150 on iOS — a pure header/UA bump over the 148 iOS base (User-Agent: iOS 26_5_0, CriOS/150.0.7871.51). The TLS bytes (Safari/WebKit HelloIOS_18) are unchanged, and verified byte-exact against a real iOS 26.5 capture: JA4 t13d2013h2_a09f3c656075_7f0f34a4126d, matching Akamai H2 and peetprint. iOS Chrome does NOT advertise ML-DSA (that is a desktop/Android Chromium-BoringSSL trait; iOS uses Safari's stack), so unlike the desktop chrome-150 line this preset carries no signature_algorithms override. Falls back to IOSChrome148 if the JSON didn't load.

func IOSSafari17 added in v1.0.5

func IOSSafari17() *Preset

IOSSafari17 returns Safari 17 on iOS fingerprint preset

func IOSSafari18 added in v1.5.10

func IOSSafari18() *Preset

IOSSafari18 returns Safari 18 on iOS fingerprint preset

func LoadAndBuildPreset added in v1.6.5

func LoadAndBuildPreset(path string) (*Preset, error)

LoadAndBuildPreset is a convenience function: load + build a single preset from a file.

func LoadAndBuildPresetFromJSON added in v1.6.5

func LoadAndBuildPresetFromJSON(data []byte) (*Preset, error)

LoadAndBuildPresetFromJSON is a convenience function: parse JSON + build a single preset.

func LookupCustom added in v1.6.5

func LookupCustom(name string) *Preset

LookupCustom returns a registered custom preset by name, or nil if not found. Returns a deep clone to prevent callers from mutating the registry copy.

func Safari18

func Safari18() *Preset

Safari18 returns the Safari 18 fingerprint preset Note: Safari is macOS-only, so no platform detection needed

func (*Preset) H2DisableCookieSplit added in v1.6.5

func (p *Preset) H2DisableCookieSplit() bool

H2DisableCookieSplit reports whether to send the Cookie header as a single field instead of crumbling it into one field per cookie-pair. Chrome and Firefox crumble (false) per RFC 9113 8.2.3 / Chromium HpackEncoder CookieToCrumbs; Safari/WebKit sends a single field (true). Used for both the H2 (sardanioss/net HPACK encoder) and H3 (pre-split in HTTP3Transport) paths.

func (*Preset) H2HPACKIndexingPolicy added in v1.6.5

func (p *Preset) H2HPACKIndexingPolicy() string

H2HPACKIndexingPolicy returns the HPACK indexing policy name.

func (*Preset) H2HPACKNeverIndex added in v1.6.5

func (p *Preset) H2HPACKNeverIndex() []string

H2HPACKNeverIndex returns headers that should never be HPACK-indexed.

func (*Preset) H2HasPriorityTable added in v1.6.5

func (p *Preset) H2HasPriorityTable() bool

H2HasPriorityTable reports whether this preset will resolve per-dest priority data. Three states:

  • H2Config.PriorityTable populated (len > 0) → true (explicit override).
  • H2Config.PriorityTable nil or empty AND NoRFC7540Priorities=false → true (inherits the package-level defaultPriorityTable).
  • NoRFC7540Priorities=true → false (Safari / iOS Chrome / iOS Safari opt out of RFC 7540 priorities entirely; the wire frame is not emitted).

When false, callers fall back to the legacy HTTP2Settings.StreamWeight / StreamExclusive single-weight behaviour. To genuinely disable priority emission for a single preset, set NoRFC7540Priorities=true on its HTTP2Settings — the priority_table mechanism is purely additive.

func (*Preset) H2HeaderOrder added in v1.6.5

func (p *Preset) H2HeaderOrder() []string

H2HeaderOrder returns the HPACK wire encoding order for HTTP/2 headers.

func (*Preset) H2PriorityFor added in v1.6.5

func (p *Preset) H2PriorityFor(dest string) (weight uint16, exclusive bool, headerValue string, ok bool)

H2PriorityFor returns the resolved (weight, exclusive, headerValue) for a given sec-fetch-dest. Resolution order:

  1. Preset's explicit H2Config.PriorityTable (when populated, len > 0).
  2. Package-level defaultPriorityTable, but only if the preset uses RFC 7540 priorities (NoRFC7540Priorities=false).

ok=false in two cases:

  • the preset opts out of RFC 7540 priorities entirely (Safari etc.), or
  • the dest is not registered in whichever table applies.

In both cases the caller should fall back to HTTP2Settings.StreamWeight / StreamExclusive (legacy behaviour).

weight is the effective weight (1–256). The transport converts to wire format (weight-1) at the boundary.

headerValue is the RFC 9218 priority: header value rendered per the emission rules; empty string means "do not inject the header" (caller must skip Set/Add for this request).

Lookup is case-sensitive — Chrome emits "document", "image", etc. as lowercase ASCII. Pass req.Header.Get("Sec-Fetch-Dest") directly.

func (*Preset) H2PseudoHeaderOrder added in v1.6.5

func (p *Preset) H2PseudoHeaderOrder() []string

H2PseudoHeaderOrder returns the pseudo-header order for HTTP/2. nil signals "use heuristic" (Chrome m,a,s,p / Safari m,s,p,a).

func (*Preset) H2SettingsOrder added in v1.6.5

func (p *Preset) H2SettingsOrder() []uint16

H2SettingsOrder returns the explicit H2 SETTINGS frame ID order. nil signals "use dynamic builder" (existing behavior).

func (*Preset) H2StreamPriorityMode added in v1.6.5

func (p *Preset) H2StreamPriorityMode() string

H2StreamPriorityMode returns the stream priority mode name.

func (*Preset) H3EnableDatagrams added in v1.6.5

func (p *Preset) H3EnableDatagrams() bool

H3EnableDatagrams returns whether to enable H3 datagrams.

func (*Preset) H3MaxFieldSectionSize added in v1.6.5

func (p *Preset) H3MaxFieldSectionSize() uint64

H3MaxFieldSectionSize returns the max field section size. 0 means omit the setting (Safari behavior).

func (*Preset) H3MaxResponseHeaderBytes added in v1.6.5

func (p *Preset) H3MaxResponseHeaderBytes() uint64

H3MaxResponseHeaderBytes returns the max response header bytes.

func (*Preset) H3QPACKBlockedStreams added in v1.6.5

func (p *Preset) H3QPACKBlockedStreams() uint64

H3QPACKBlockedStreams returns the QPACK blocked streams limit.

func (*Preset) H3QPACKMaxTableCapacity added in v1.6.5

func (p *Preset) H3QPACKMaxTableCapacity() uint64

H3QPACKMaxTableCapacity returns the QPACK max dynamic table capacity.

func (*Preset) H3QUICAllow0RTT added in v1.6.5

func (p *Preset) H3QUICAllow0RTT() bool

H3QUICAllow0RTT returns whether to allow 0-RTT.

func (*Preset) H3QUICChromeStyleInitial added in v1.6.5

func (p *Preset) H3QUICChromeStyleInitial() bool

H3QUICChromeStyleInitial returns whether to use Chrome-style initial packets.

func (*Preset) H3QUICConnectionIDLength added in v1.6.5

func (p *Preset) H3QUICConnectionIDLength() int

H3QUICConnectionIDLength returns the QUIC connection ID length in bytes. Chrome uses 0 (empty SCID), Firefox uses 8.

func (*Preset) H3QUICDisableHelloScramble added in v1.6.5

func (p *Preset) H3QUICDisableHelloScramble() bool

H3QUICDisableHelloScramble returns whether to disable ClientHello scrambling.

func (*Preset) H3QUICInitialConnectionReceiveWindow added in v1.6.5

func (p *Preset) H3QUICInitialConnectionReceiveWindow() uint64

H3QUICInitialConnectionReceiveWindow returns the quic-go InitialConnectionReceiveWindow value (which becomes initial_max_data on the wire). 0 means "use quic-go default" (~7.5 MB). iOS Chrome sets 16 MiB.

func (*Preset) H3QUICInitialPacketSize added in v1.6.5

func (p *Preset) H3QUICInitialPacketSize() uint16

H3QUICInitialPacketSize returns the QUIC initial packet size.

func (*Preset) H3QUICInitialStreamReceiveWindow added in v1.6.5

func (p *Preset) H3QUICInitialStreamReceiveWindow() uint64

H3QUICInitialStreamReceiveWindow returns the quic-go InitialStreamReceiveWindow value (which becomes initial_max_stream_data_* on the wire). 0 means "use quic-go default" (~512 KB). iOS Chrome sets 2 MiB.

func (*Preset) H3QUICMaxDatagramFrameSize added in v1.6.5

func (p *Preset) H3QUICMaxDatagramFrameSize() uint64

H3QUICMaxDatagramFrameSize returns the max_datagram_frame_size transport parameter. Chrome uses 65536, default quic-go is 16383.

func (*Preset) H3QUICMaxIncomingStreams added in v1.6.5

func (p *Preset) H3QUICMaxIncomingStreams() int64

H3QUICMaxIncomingStreams returns the max incoming bidirectional streams.

func (*Preset) H3QUICMaxIncomingUniStreams added in v1.6.5

func (p *Preset) H3QUICMaxIncomingUniStreams() int64

H3QUICMaxIncomingUniStreams returns the max incoming unidirectional streams.

func (*Preset) H3QUICTransportParamOrder added in v1.6.5

func (p *Preset) H3QUICTransportParamOrder() string

H3QUICTransportParamOrder returns the QUIC transport parameter order mode name.

func (*Preset) H3SendGreaseFrames added in v1.6.5

func (p *Preset) H3SendGreaseFrames() bool

H3SendGreaseFrames returns whether to send GREASE frames on the control stream.

func (*Preset) ResolveClientHints added in v1.6.8

func (p *Preset) ResolveClientHints() ClientHints

ResolveClientHints returns the fully-resolved UA client hints for this preset. The low-entropy trio is taken verbatim from the preset headers; the high-entropy hints come from the preset's ClientHints overrides where set, and are otherwise DERIVED from the trio so they can never drift out of sync. Specifically, an unset full-version-list is built from sec-ch-ua by preserving the exact brand names, order and GREASE token and expanding each major version to "<major>.0.0.0". This is the single coherent source the session layer reads to emit high-entropy hints after a host advertises Accept-CH.

type PresetFile added in v1.6.5

type PresetFile struct {
	Version int         `json:"version"`
	Preset  *PresetSpec `json:"preset,omitempty"`
	Pool    *PoolSpec   `json:"pool,omitempty"`
}

PresetFile is the top-level JSON structure for preset files.

func LoadPresetFromFile added in v1.6.5

func LoadPresetFromFile(path string) (*PresetFile, error)

LoadPresetFromFile reads and parses a JSON preset file.

func LoadPresetFromJSON added in v1.6.5

func LoadPresetFromJSON(data []byte) (*PresetFile, error)

LoadPresetFromJSON parses JSON bytes into a PresetFile.

type PresetInfo added in v1.6.0

type PresetInfo struct {
	Protocols []string `json:"protocols"`
}

PresetInfo contains metadata about a preset's protocol support.

type PresetPool added in v1.6.5

type PresetPool struct {
	// contains filtered or unexported fields
}

PresetPool manages a collection of presets with rotation strategies.

func NewPresetPool added in v1.6.5

func NewPresetPool(name string, strategy PoolStrategy, presets []*Preset) *PresetPool

NewPresetPool creates a pool from pre-built presets. Panics if presets is empty.

func NewPresetPoolFromFile added in v1.6.5

func NewPresetPoolFromFile(path string) (*PresetPool, error)

NewPresetPoolFromFile loads a pool from a JSON file. Auto-registers all pool presets to the custom registry.

func NewPresetPoolFromJSON added in v1.6.5

func NewPresetPoolFromJSON(data []byte) (*PresetPool, error)

NewPresetPoolFromJSON loads a pool from JSON bytes. Auto-registers all pool presets to the custom registry.

func (*PresetPool) Close added in v1.6.5

func (p *PresetPool) Close()

Close unregisters all pool presets from the custom registry.

func (*PresetPool) Get added in v1.6.5

func (p *PresetPool) Get(index int) *Preset

Get returns a preset by index. Panics if index is out of range.

func (*PresetPool) Name added in v1.6.5

func (p *PresetPool) Name() string

Name returns the pool name.

func (*PresetPool) Next added in v1.6.5

func (p *PresetPool) Next() *Preset

Next returns the next preset using round-robin. Lock-free, thread-safe.

func (*PresetPool) Pick added in v1.6.5

func (p *PresetPool) Pick() *Preset

Pick returns a preset using the pool's configured strategy.

func (*PresetPool) Random added in v1.6.5

func (p *PresetPool) Random() *Preset

Random returns a random preset from the pool. Thread-safe.

func (*PresetPool) Size added in v1.6.5

func (p *PresetPool) Size() int

Size returns the number of presets in the pool.

type PresetSpec added in v1.6.5

type PresetSpec struct {
	Name        string           `json:"name"`
	BasedOn     string           `json:"based_on,omitempty"`
	TLS         *TLSSpec         `json:"tls,omitempty"`
	HTTP2       *HTTP2Spec       `json:"http2,omitempty"`
	HTTP3       *HTTP3Spec       `json:"http3,omitempty"`
	Headers     *HeaderSpec      `json:"headers,omitempty"`
	ClientHints *ClientHintsSpec `json:"client_hints,omitempty"`
	TCP         *TCPSpec         `json:"tcp,omitempty"`
	Protocol    *ProtocolSpec    `json:"protocols,omitempty"`
}

PresetSpec defines a single preset in JSON.

type ProtocolSpec added in v1.6.5

type ProtocolSpec struct {
	HTTP3 *bool `json:"http3,omitempty"`
	// Aliases / extra toggles. H3 is an alias for HTTP3. H2=false disables HTTP/2
	// in auto mode (the preset goes straight to HTTP/1.1). Accepting "h2"/"h3"
	// matches what users naturally write; previously only "http3" was honored.
	H3 *bool `json:"h3,omitempty"`
	H2 *bool `json:"h2,omitempty"`
}

ProtocolSpec defines protocol support.

type RequestContext added in v1.0.1

type RequestContext struct {
	// Mode is the fetch mode (navigate, cors, no-cors, same-origin)
	Mode FetchMode
	// Dest is the resource destination type
	Dest FetchDest
	// Site is the relationship between request origin and target
	Site FetchSite
	// IsUserTriggered indicates if the request was user-initiated (affects Sec-Fetch-User)
	IsUserTriggered bool
	// Referrer is the page that initiated the request (for Sec-Fetch-Site calculation)
	Referrer string
	// TargetURL is the URL being requested
	TargetURL string
}

RequestContext contains information about the request context for header generation

func FontContext added in v1.6.0

func FontContext(referrer, targetURL string) RequestContext

FontContext returns a RequestContext for font loads

func ImageContext added in v1.0.1

func ImageContext(referrer, targetURL string) RequestContext

ImageContext returns a RequestContext for image loads

func NavigationContext() RequestContext

NavigationContext returns a RequestContext for page navigation

func ScriptContext added in v1.0.1

func ScriptContext(referrer, targetURL string) RequestContext

ScriptContext returns a RequestContext for script loads

func StyleContext added in v1.0.1

func StyleContext(referrer, targetURL string) RequestContext

StyleContext returns a RequestContext for stylesheet loads

func XHRContext added in v1.0.1

func XHRContext(referrer, targetURL string) RequestContext

XHRContext returns a RequestContext for XHR/fetch API requests

type ResourcePriority added in v1.6.5

type ResourcePriority struct {
	Urgency     uint8 // 0–7; 3 = default (no `u=` on header)
	Incremental bool  // RFC 9218 `i` parameter
	EmitHeader  bool  // false → suppress the priority: HTTP header entirely
}

ResourcePriority describes a single browser priority decision for one resource class (sec-fetch-dest). Three orthogonal facts:

  • Urgency (0–7) drives the RFC 7540 H2 stream weight via the formula weight = 256 - (urgency * 73) / 2. 3 is Chrome's internal default and emits no `u=` parameter on the priority: header.
  • Incremental flag drives the RFC 9218 `i` parameter on the priority: header. The H2 wire frame ignores it (RFC 7540 has no incremental).
  • EmitHeader controls whether the priority: HTTP header is sent at all. Chrome omits the header entirely on async/defer scripts even though the wire weight defaults to 147 (urgency=3). The wire frame is still emitted; only the HTTP header is suppressed.

type ResourcePrioritySpec added in v1.6.5

type ResourcePrioritySpec struct {
	Urgency     uint8 `json:"urgency"`
	Incremental bool  `json:"incremental"`
	EmitHeader  bool  `json:"emit_header"`
}

ResourcePrioritySpec is the JSON shape of fingerprint.ResourcePriority. All three fields are required for a complete entry; partial entries inherit zero values (urgency=0 → highest, incremental=false, emit_header=false) which is rarely what a real preset wants — populate explicitly.

type SecFetchHeaders added in v1.0.1

type SecFetchHeaders struct {
	Site string
	Mode string
	Dest string
	User string // "?1" for user-triggered, empty otherwise
}

SecFetchHeaders generates coherent Sec-Fetch-* headers based on context

func GenerateSecFetchHeaders added in v1.0.1

func GenerateSecFetchHeaders(ctx RequestContext) SecFetchHeaders

GenerateSecFetchHeaders generates Sec-Fetch-* headers for the given context

type TCPFingerprint added in v1.6.1

type TCPFingerprint struct {
	TTL         int  // IP Time-To-Live: 128=Windows, 64=Linux/macOS/iOS/Android
	MSS         int  // TCP Maximum Segment Size: 1460 for standard Ethernet
	WindowSize  int  // TCP Window Size in SYN: 64240=Win10/11, 65535=Linux/macOS
	WindowScale int  // TCP Window Scale option: 8=Win10/11, 7=Linux/Android, 6=macOS/iOS
	DFBit       bool // IP Don't Fragment flag
}

TCPFingerprint contains TCP/IP stack parameters that identify the OS. Anti-bot systems check TTL, window size, and other TCP options in the SYN packet to verify the claimed browser platform matches the actual OS.

func LinuxTCPFingerprint added in v1.6.1

func LinuxTCPFingerprint() TCPFingerprint

LinuxTCPFingerprint returns TCP fingerprint values for Linux

func MacOSTCPFingerprint added in v1.6.1

func MacOSTCPFingerprint() TCPFingerprint

MacOSTCPFingerprint returns TCP fingerprint values for macOS

func PlatformTCPFingerprint added in v1.6.1

func PlatformTCPFingerprint(platform string) TCPFingerprint

PlatformTCPFingerprint returns the TCP fingerprint matching the given platform string. Used by auto-platform presets that detect the running OS at runtime.

func WindowsTCPFingerprint added in v1.6.1

func WindowsTCPFingerprint() TCPFingerprint

WindowsTCPFingerprint returns TCP fingerprint values for Windows 10/11

type TCPSpec added in v1.6.5

type TCPSpec struct {
	Platform    string `json:"platform,omitempty"` // "Windows","macOS","Linux" — shorthand
	TTL         *int   `json:"ttl,omitempty"`
	MSS         *int   `json:"mss,omitempty"`
	WindowSize  *int   `json:"window_size,omitempty"`
	WindowScale *int   `json:"window_scale,omitempty"`
	DFBit       *bool  `json:"df_bit,omitempty"`
}

TCPSpec defines TCP/IP fingerprint configuration.

type TLSSpec added in v1.6.5

type TLSSpec struct {
	// Mutually exclusive: use client_hello OR ja3, not both
	ClientHello        string `json:"client_hello,omitempty"`      // e.g., "chrome-146-windows"
	PSKClientHello     string `json:"psk_client_hello,omitempty"`  // e.g., "chrome-146-windows-psk"
	QUICClientHello    string `json:"quic_client_hello,omitempty"` // e.g., "chrome-146-quic"
	QUICPSKClientHello string `json:"quic_psk_client_hello,omitempty"`

	JA3           string         `json:"ja3,omitempty"` // JA3 string
	JA3ExtrasSpec *JA3ExtrasSpec `json:"ja3_extras,omitempty"`

	// Individual extension data (supplements client_hello or ja3)
	SignatureAlgorithms           []uint16 `json:"signature_algorithms,omitempty"`      // TCP (H1/H2) sig-algs override; overrides the ClientHelloID base
	QUICSignatureAlgorithms       []uint16 `json:"quic_signature_algorithms,omitempty"` // HTTP/3 (QUIC) sig-algs override; separate because a browser's QUIC set can differ (e.g. Chrome 150 sends ML-DSA on TCP only)
	DelegatedCredentialAlgorithms []uint16 `json:"delegated_credential_algorithms,omitempty"`
	ALPN                          []string `json:"alpn,omitempty"`
	CertCompression               []string `json:"cert_compression,omitempty"` // "brotli", "zlib", "zstd"
	PermuteExtensions             *bool    `json:"permute_extensions,omitempty"`
	RecordSizeLimit               *uint16  `json:"record_size_limit,omitempty"`
	KeyShareCurves                *int     `json:"key_share_curves,omitempty"` // number of curves to send key shares for; nil/0 = 1
}

TLSSpec defines TLS fingerprint configuration.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL