client

package
v1.6.7 Latest Latest
Warning

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

Go to latest
Published: Jun 3, 2026 License: MIT Imports: 36 Imported by: 1

Documentation

Overview

Package client provides an HTTP client with browser TLS/HTTP fingerprint spoofing.

This package is the core of httpcloak. It provides an HTTP client that mimics real browser fingerprints at the TLS and HTTP/2 protocol levels, making requests indistinguishable from actual Chrome, Firefox, or Safari browsers.

Why Fingerprint Spoofing Matters

Modern bot detection systems analyze multiple layers of your HTTP connection:

  1. TLS Fingerprint (JA3/JA4): Cipher suites, extensions, elliptic curves
  2. HTTP/2 Fingerprint (Akamai): SETTINGS frame values, WINDOW_UPDATE, PRIORITY
  3. Header Fingerprint: Order, format, and values of HTTP headers

Go's standard library has a distinct fingerprint that bot detection systems (Cloudflare, Akamai, PerimeterX) can identify instantly. This package solves that by using uTLS for TLS spoofing and custom HTTP/2 framing.

Basic Usage

c := client.NewClient("chrome-143")
defer c.Close()

resp, err := c.Get(ctx, "https://example.com", nil)
if err != nil {
    log.Fatal(err)
}
fmt.Println(resp.Text())

Session Usage (with cookies)

session := client.NewSession("chrome-143")
defer session.Close()

// Login - cookies are persisted
session.Post(ctx, "https://example.com/login", body, headers)

// Subsequent requests include cookies
resp, _ := session.Get(ctx, "https://example.com/dashboard", nil)

Package client options - configuration for the HTTP client.

The client uses functional options pattern for configuration. All options have sensible defaults, so you can create a client with just:

c := client.NewClient("chrome-143")

Or customize with options:

c := client.NewClient("chrome-143",
    client.WithTimeout(60*time.Second),
    client.WithProxy("http://proxy:8080"),
    client.WithRetry(3),
)

Index

Constants

This section is empty.

Variables

View Source
var EnableCookies = struct{}{}

EnableCookies is a marker to enable cookie jar in NewClient Use NewSession() instead for simpler API, or call client.EnableCookies() after creation

View Source
var WithDisableH3 = WithDisableHTTP3

WithDisableH3 is an alias for WithDisableHTTP3. Disables HTTP/3, allowing HTTP/2 with HTTP/1.1 fallback.

Functions

func CalculateSPKIHash

func CalculateSPKIHash(cert *x509.Certificate) string

CalculateSPKIHash calculates the SHA256 hash of a certificate's SPKI Returns base64-encoded hash (HPKP format)

func DecodeParams

func DecodeParams(query string) (map[string]string, error)

DecodeParams decodes a query string to a map of parameters

func Decompress

func Decompress(data []byte, encoding string) ([]byte, error)

Decompress decompresses response body based on Content-Encoding

func EncodeParams

func EncodeParams(params map[string]string) string

EncodeParams encodes a map of parameters to a query string

func HeadersFromMap deprecated added in v1.5.3

func HeadersFromMap(old map[string]string) map[string][]string

HeadersFromMap converts the old map[string]string header format to the new map[string][]string format. This is provided for backward compatibility.

Deprecated: Use map[string][]string directly for headers. This function will be removed in a future version.

Example migration:

// Old (deprecated):
headers := map[string]string{"Content-Type": "application/json"}

// New:
headers := map[string][]string{"Content-Type": {"application/json"}}

func JoinURL

func JoinURL(base, path string) string

JoinURL joins a base URL with a path

func MakeHeaders added in v1.5.3

func MakeHeaders(keyValuePairs ...string) map[string][]string

MakeHeaders creates a map[string][]string from key-value pairs. Useful for inline header creation.

Example:

headers := client.MakeHeaders("Content-Type", "application/json", "Accept", "text/html")

Types

type Auth

type Auth interface {
	// Apply applies authentication to the request
	Apply(req *http.Request) error
	// HandleChallenge handles authentication challenge from 401 response
	HandleChallenge(resp *http.Response, req *http.Request) (bool, error)
}

Auth interface for authentication methods

type BasicAuth

type BasicAuth struct {
	Username string
	Password string
}

BasicAuth implements HTTP Basic authentication

func NewBasicAuth

func NewBasicAuth(username, password string) *BasicAuth

NewBasicAuth creates a new BasicAuth

func (*BasicAuth) Apply

func (a *BasicAuth) Apply(req *http.Request) error

Apply applies Basic auth header to request

func (*BasicAuth) HandleChallenge

func (a *BasicAuth) HandleChallenge(resp *http.Response, req *http.Request) (bool, error)

HandleChallenge handles 401 response - Basic auth doesn't retry

type BearerAuth

type BearerAuth struct {
	Token string
}

BearerAuth implements Bearer token authentication

func NewBearerAuth

func NewBearerAuth(token string) *BearerAuth

NewBearerAuth creates a new BearerAuth

func (*BearerAuth) Apply

func (a *BearerAuth) Apply(req *http.Request) error

Apply applies Bearer auth header to request

func (*BearerAuth) HandleChallenge

func (a *BearerAuth) HandleChallenge(resp *http.Response, req *http.Request) (bool, error)

HandleChallenge handles 401 response - Bearer auth doesn't retry

type CertPinError

type CertPinError struct {
	Host           string
	ExpectedHashes []string
	ActualHashes   []string
}

CertPinError is returned when certificate pinning verification fails

func (*CertPinError) Error

func (e *CertPinError) Error() string

type CertPinner

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

CertPinner handles certificate pinning verification

func NewCertPinner

func NewCertPinner() *CertPinner

NewCertPinner creates a new certificate pinner

func (*CertPinner) AddPin

func (p *CertPinner) AddPin(hash string, opts ...PinOption) *CertPinner

AddPin adds a certificate pin hash should be base64-encoded SHA256 of the certificate's SPKI Example: "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="

func (*CertPinner) AddPinFromCertFile

func (p *CertPinner) AddPinFromCertFile(certPath string, opts ...PinOption) error

AddPinFromCertFile loads a certificate from file and pins its public key

func (*CertPinner) AddPinFromPEM

func (p *CertPinner) AddPinFromPEM(pemData []byte, opts ...PinOption) error

AddPinFromPEM adds a pin from PEM-encoded certificate data

func (*CertPinner) Clear

func (p *CertPinner) Clear()

Clear removes all pins

func (*CertPinner) GetPins

func (p *CertPinner) GetPins() []*CertificatePin

GetPins returns all configured pins

func (*CertPinner) HasPins

func (p *CertPinner) HasPins() bool

HasPins returns true if any pins are configured

func (*CertPinner) Verify

func (p *CertPinner) Verify(host string, certs []*x509.Certificate) error

Verify checks if the certificate chain matches any pin

type CertificatePin

type CertificatePin struct {
	// Type of pin (SHA256 of SPKI or full certificate)
	Type PinType

	// Hash is the pin value (base64 or hex encoded)
	Hash string

	// Host is the hostname this pin applies to (optional, empty = all hosts)
	Host string

	// IncludeSubdomains applies pin to subdomains as well
	IncludeSubdomains bool
}

CertificatePin represents a pinned certificate or public key

type Client

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

Client is an HTTP client with connection pooling and fingerprint spoofing By default, it tries HTTP/3 first, then HTTP/2, then HTTP/1.1 as fallback

func NewClient

func NewClient(presetName string, opts ...Option) *Client

NewClient creates a new HTTP client with default configuration Tries HTTP/3 first, then HTTP/2, then HTTP/1.1 as fallback

func NewSession

func NewSession(presetName string, opts ...Option) *Client

NewSession creates a new HTTP client with cookie jar and retry enabled (like requests.Session()) Cookies are automatically persisted between requests. Retry is enabled by default (3 retries) to handle bot protection cookie challenges. This mimics browser behavior where cookies are accepted and requests are retried.

func (*Client) CertPinner

func (c *Client) CertPinner() *CertPinner

CertPinner returns the certificate pinner, creating one if needed

func (*Client) ClearCookies

func (c *Client) ClearCookies()

ClearCookies removes all cookies from the jar

func (*Client) ClearHooks

func (c *Client) ClearHooks()

ClearHooks removes all hooks

func (*Client) ClearPins

func (c *Client) ClearPins()

ClearPins removes all certificate pins

func (*Client) Close

func (c *Client) Close()

Close shuts down the client and all connections

func (*Client) CloseQUICConnections added in v1.5.7

func (c *Client) CloseQUICConnections()

CloseQUICConnections closes all QUIC connections but keeps session caches intact This forces new connections on subsequent requests, allowing session resumption testing

func (*Client) Cookies

func (c *Client) Cookies() *CookieJar

Cookies returns the cookie jar (nil if cookies are disabled)

func (*Client) DisableCookies

func (c *Client) DisableCookies()

DisableCookies disables cookie handling

func (*Client) Do

func (c *Client) Do(ctx context.Context, req *Request) (*Response, error)

Do executes an HTTP request Tries HTTP/3 first, falls back to HTTP/2 if HTTP/3 fails

func (*Client) DoStream

func (c *Client) DoStream(ctx context.Context, req *Request) (*StreamResponse, error)

DoStream executes an HTTP request and returns a streaming response The caller is responsible for closing the response

func (*Client) EnableCookies

func (c *Client) EnableCookies()

EnableCookies enables cookie jar for session persistence

func (*Client) Get

func (c *Client) Get(ctx context.Context, url string, headers map[string][]string) (*Response, error)

Get performs a GET request

func (*Client) GetHeaderOrder added in v1.5.8

func (c *Client) GetHeaderOrder() []string

GetHeaderOrder returns the current header order. Returns preset's default order if no custom order is set.

func (*Client) GetProxy added in v1.5.8

func (c *Client) GetProxy() string

GetProxy returns the current proxy URL (TCP proxy if they differ)

func (*Client) GetStream

func (c *Client) GetStream(ctx context.Context, url string, headers map[string][]string) (*StreamResponse, error)

GetStream performs a streaming GET request

func (*Client) GetTCPProxy added in v1.5.8

func (c *Client) GetTCPProxy() string

GetTCPProxy returns the current TCP proxy URL

func (*Client) GetUDPProxy added in v1.5.8

func (c *Client) GetUDPProxy() string

GetUDPProxy returns the current UDP proxy URL

func (*Client) Hooks

func (c *Client) Hooks() *Hooks

Hooks returns the client's hooks instance, creating one if needed

func (*Client) OnPostResponse

func (c *Client) OnPostResponse(hook PostResponseHook) *Client

OnPostResponse adds a post-response hook Hook is called after each response is received

func (*Client) OnPreRequest

func (c *Client) OnPreRequest(hook PreRequestHook) *Client

OnPreRequest adds a pre-request hook Hook is called before each request is sent

func (*Client) PinCertificate

func (c *Client) PinCertificate(hash string, opts ...PinOption) *Client

PinCertificate adds a certificate pin hash should be base64-encoded SHA256 of the certificate's SPKI Example: c.PinCertificate("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=", ForHost("example.com"))

func (*Client) PinCertificateFromFile

func (c *Client) PinCertificateFromFile(certPath string, opts ...PinOption) error

PinCertificateFromFile loads a certificate from file and pins its public key

func (*Client) Post

func (c *Client) Post(ctx context.Context, url string, body io.Reader, headers map[string][]string) (*Response, error)

Post performs a POST request

func (*Client) Prepare

func (c *Client) Prepare(ctx context.Context, req *Request) (*PreparedRequest, error)

Prepare creates a PreparedRequest from a Request The PreparedRequest can be inspected, modified, and then sent

func (*Client) PrepareGet

func (c *Client) PrepareGet(ctx context.Context, url string, headers map[string][]string) (*PreparedRequest, error)

PrepareGet creates a prepared GET request

func (*Client) PreparePost

func (c *Client) PreparePost(ctx context.Context, url string, body io.Reader, headers map[string][]string) (*PreparedRequest, error)

PreparePost creates a prepared POST request

func (*Client) SetAuth

func (c *Client) SetAuth(auth Auth)

SetAuth sets authentication for all requests

func (*Client) SetBasicAuth

func (c *Client) SetBasicAuth(username, password string)

SetBasicAuth sets Basic authentication

func (*Client) SetBearerAuth

func (c *Client) SetBearerAuth(token string)

SetBearerAuth sets Bearer token authentication

func (*Client) SetForceProtocol added in v1.6.1

func (c *Client) SetForceProtocol(p Protocol)

SetForceProtocol changes the protocol for all subsequent requests. Use ProtocolHTTP2 for H2, ProtocolHTTP3 for H3, ProtocolAuto for auto-detect. Added for PX solver: mimics Chrome's H2→H3 alt-svc upgrade pattern.

func (*Client) SetHeaderOrder added in v1.5.8

func (c *Client) SetHeaderOrder(order []string)

SetHeaderOrder sets a custom header order for all requests. Pass nil or empty slice to reset to preset's default order. Order should contain lowercase header names.

func (*Client) SetPreset

func (c *Client) SetPreset(presetName string)

SetPreset changes the fingerprint preset

func (*Client) SetProxy added in v1.5.8

func (c *Client) SetProxy(proxyURL string)

SetProxy changes both TCP (HTTP/1.1, HTTP/2) and UDP (HTTP/3) proxies This closes all existing connections - they're invalid for the new proxy route Pass empty string to switch to direct connection (no proxy)

func (*Client) SetTCPProxy added in v1.5.8

func (c *Client) SetTCPProxy(proxyURL string)

SetTCPProxy changes the proxy for HTTP/1.1 and HTTP/2 connections This closes all existing TCP-based connections Pass empty string to switch to direct connection (no proxy)

func (*Client) SetTimeout

func (c *Client) SetTimeout(timeout time.Duration)

SetTimeout sets the request timeout

func (*Client) SetUDPProxy added in v1.5.8

func (c *Client) SetUDPProxy(proxyURL string)

SetUDPProxy changes the proxy for HTTP/3 (QUIC) connections Supports SOCKS5 (UDP relay) and MASQUE (CONNECT-UDP) proxies Pass empty string to switch to direct connection (no proxy)

func (*Client) Stats

func (c *Client) Stats() map[string]struct {
	Total    int
	Healthy  int
	Requests int64
}

Stats returns connection pool statistics

type ClientConfig

type ClientConfig struct {
	// Preset is the browser fingerprint preset name (e.g., "chrome-143", "firefox-133").
	// This determines the TLS fingerprint (JA3/JA4), HTTP/2 settings, and default headers.
	Preset string

	// Timeout is the maximum duration for a request including redirects.
	// Default: 30 seconds.
	Timeout time.Duration

	// Proxy is the URL of the proxy server (used for all protocols).
	// Supports http://, https://, socks5://, and masque:// schemes.
	// Example: "http://user:pass@proxy.example.com:8080"
	// For split proxy configuration, use TCPProxy and UDPProxy instead.
	Proxy string

	// TCPProxy is the proxy URL for TCP-based protocols (HTTP/1.1 and HTTP/2).
	// Use this with UDPProxy for split proxy configuration.
	// Supports http://, https://, and socks5:// schemes.
	// Example: "http://user:pass@datacenter-proxy:8080"
	TCPProxy string

	// UDPProxy is the proxy URL for UDP-based protocols (HTTP/3 via MASQUE).
	// Use this with TCPProxy for split proxy configuration.
	// Supports masque:// scheme or known MASQUE providers (e.g., Bright Data).
	// Example: "masque://user:pass@brd.superproxy.io:443"
	UDPProxy string

	// FollowRedirects controls whether the client follows HTTP redirects (3xx responses).
	// Default: true.
	FollowRedirects bool

	// MaxRedirects is the maximum number of redirects to follow.
	// Prevents infinite redirect loops.
	// Default: 10.
	MaxRedirects int

	// RetryEnabled enables automatic retry on transient failures.
	// When enabled, uses exponential backoff with jitter.
	// Default: false.
	RetryEnabled bool

	// MaxRetries is the maximum number of retry attempts.
	// Default: 3.
	MaxRetries int

	// RetryWaitMin is the minimum wait time between retries.
	// The actual wait is calculated using exponential backoff.
	// Default: 1 second.
	RetryWaitMin time.Duration

	// RetryWaitMax is the maximum wait time between retries.
	// Caps the exponential backoff.
	// Default: 30 seconds.
	RetryWaitMax time.Duration

	// RetryOnStatus is the list of HTTP status codes that trigger a retry.
	// Default: [429, 500, 502, 503, 504].
	RetryOnStatus []int

	// InsecureSkipVerify disables TLS certificate verification.
	// WARNING: This makes the connection insecure. Only use for testing.
	// Default: false.
	InsecureSkipVerify bool

	// TLSConfig is a custom TLS configuration for advanced use cases.
	// Most users should not need to set this.
	TLSConfig *tls.Config

	// DisableKeepAlives disables HTTP keep-alives.
	// When true, each request opens a new connection.
	// Default: false.
	DisableKeepAlives bool

	// DisableH3 disables HTTP/3 (QUIC) and forces HTTP/2.
	// Useful if HTTP/3 causes issues with certain servers.
	// Default: false.
	DisableH3 bool

	// PreferIPv4 makes the client prefer IPv4 addresses over IPv6.
	// Useful on networks with poor IPv6 connectivity.
	// Default: false (prefers IPv6 like modern browsers).
	PreferIPv4 bool

	// ConnectTo maps request hosts to connection hosts.
	// Key: request host (e.g., "example.com")
	// Value: connection host (e.g., "www.cloudflare.com")
	// The TLS SNI and Host header use the request host, but DNS resolution
	// and TCP/QUIC connection use the connection host.
	// Similar to curl's --connect-to option.
	ConnectTo map[string]string

	// ECHConfig is a custom ECH (Encrypted Client Hello) configuration.
	// When set, this overrides automatic ECH fetching from DNS.
	// Use this to force ECH with a known config (e.g., from cloudflare-ech.com).
	ECHConfig []byte

	// ECHConfigDomain specifies a domain to fetch ECH config from.
	// When set, ECH config is fetched from this domain's DNS HTTPS records
	// instead of the target domain. Useful for Cloudflare domains where
	// you can use cloudflare-ech.com's ECH config for any CF-proxied domain.
	ECHConfigDomain string

	// DisableECH disables automatic ECH fetching from DNS.
	// Chrome doesn't always use ECH even when available - some sites may
	// reject connections with ECH enabled. Set this to match Chrome behavior.
	DisableECH bool

	// ForceProtocol forces a specific HTTP protocol for all requests.
	// ProtocolAuto (default): Auto-detect with fallback (H3 -> H2 -> H1)
	// ProtocolHTTP1: Force HTTP/1.1 only
	// ProtocolHTTP2: Force HTTP/2 only
	// ProtocolHTTP3: Force HTTP/3 only
	// Per-request ForceProtocol in Request struct takes precedence.
	ForceProtocol Protocol

	// TLSOnly mode: use TLS fingerprint but skip preset HTTP headers.
	// When enabled, the preset's TLS fingerprint (JA3/JA4, cipher suites, etc.)
	// is applied, but the preset's default HTTP headers are NOT added.
	// You must set all headers manually per-request.
	// Useful when you need full control over HTTP headers while keeping the TLS fingerprint.
	// Default: false.
	TLSOnly bool
}

ClientConfig holds all configuration options for the HTTP client. Use functional options (WithTimeout, WithProxy, etc.) to set these values.

func DefaultConfig

func DefaultConfig() *ClientConfig

DefaultConfig returns default client configuration

type Cookie struct {
	Name     string
	Value    string
	Domain   string
	Path     string
	Expires  time.Time
	MaxAge   int // seconds
	Secure   bool
	HttpOnly bool
	SameSite string // "Strict", "Lax", "None"
	Raw      string // original Set-Cookie header
}

Cookie represents an HTTP cookie

func ParseSetCookie

func ParseSetCookie(header string, requestURL *url.URL) *Cookie

ParseSetCookie parses a Set-Cookie header value into a Cookie

func (*Cookie) IsExpired

func (c *Cookie) IsExpired() bool

IsExpired returns true if the cookie has expired

func (*Cookie) Matches

func (c *Cookie) Matches(u *url.URL) bool

Matches returns true if this cookie should be sent for the given URL

func (*Cookie) String

func (c *Cookie) String() string

String returns the cookie in "name=value" format for the Cookie header

type CookieJar

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

CookieJar stores cookies and provides thread-safe access

func NewCookieJar

func NewCookieJar() *CookieJar

NewCookieJar creates a new empty cookie jar

func (*CookieJar) AllCookies

func (j *CookieJar) AllCookies() map[string][]*Cookie

AllCookies returns all cookies in the jar (for debugging)

func (*CookieJar) Clear

func (j *CookieJar) Clear()

Clear removes all cookies from the jar

func (*CookieJar) ClearDomain

func (j *CookieJar) ClearDomain(domain string)

ClearDomain removes all cookies for a specific domain

func (*CookieJar) ClearExpired

func (j *CookieJar) ClearExpired()

ClearExpired removes all expired cookies

func (*CookieJar) CookieHeader

func (j *CookieJar) CookieHeader(u *url.URL) string

CookieHeader returns the Cookie header value for the given URL

func (*CookieJar) Cookies

func (j *CookieJar) Cookies(u *url.URL) []*Cookie

Cookies returns the cookies to send for the given URL

func (*CookieJar) Count

func (j *CookieJar) Count() int

Count returns the total number of cookies in the jar

func (*CookieJar) SetCookie

func (j *CookieJar) SetCookie(u *url.URL, name, value string)

SetCookie adds a single cookie to the jar

func (*CookieJar) SetCookies

func (j *CookieJar) SetCookies(u *url.URL, cookies []*Cookie)

SetCookies adds cookies from Set-Cookie headers to the jar

func (*CookieJar) SetCookiesFromHeaderList

func (j *CookieJar) SetCookiesFromHeaderList(u *url.URL, setCookieHeaders []string)

SetCookiesFromHeaderList handles multiple Set-Cookie headers

func (*CookieJar) SetCookiesFromHeaders

func (j *CookieJar) SetCookiesFromHeaders(u *url.URL, headers map[string]string)

SetCookiesFromHeaders parses Set-Cookie headers and adds them to the jar

type DigestAuth

type DigestAuth struct {
	Username string
	Password string
	// contains filtered or unexported fields
}

DigestAuth implements HTTP Digest authentication

func NewDigestAuth

func NewDigestAuth(username, password string) *DigestAuth

NewDigestAuth creates a new DigestAuth

func (*DigestAuth) Apply

func (a *DigestAuth) Apply(req *http.Request) error

Apply applies Digest auth header to request (if challenge has been received)

func (*DigestAuth) HandleChallenge

func (a *DigestAuth) HandleChallenge(resp *http.Response, req *http.Request) (bool, error)

HandleChallenge parses WWW-Authenticate header and prepares auth

type FetchMode

type FetchMode int

FetchMode specifies the Sec-Fetch-Mode behavior

const (
	FetchModeNavigate FetchMode = iota // Default: human clicked link (sec-fetch-mode: navigate)
	FetchModeCORS                      // XHR/fetch call (sec-fetch-mode: cors)
	FetchModeNoCors                    // Subresource load (script/style/image): sec-fetch-mode: no-cors
)

type FetchSite

type FetchSite int

FetchSite specifies the Sec-Fetch-Site value

const (
	FetchSiteAuto       FetchSite = iota // Auto-detect based on Referer header
	FetchSiteNone                        // Direct navigation (typed URL, bookmark)
	FetchSiteSameOrigin                  // Same origin request
	FetchSiteSameSite                    // Same site but different subdomain
	FetchSiteCrossSite                   // Different site
)

type FormData

type FormData struct {
	Fields map[string]string // Regular form fields
	Files  []FormFile        // Files to upload
}

FormData represents multipart form data

func NewFormData

func NewFormData() *FormData

NewFormData creates a new FormData instance

func (*FormData) AddField

func (f *FormData) AddField(name, value string) *FormData

AddField adds a form field

func (*FormData) AddFile

func (f *FormData) AddFile(fieldName, fileName string, content []byte) *FormData

AddFile adds a file from bytes

func (*FormData) AddFilePath

func (f *FormData) AddFilePath(fieldName, filePath string) error

AddFilePath adds a file from a filesystem path

func (*FormData) AddFileReader

func (f *FormData) AddFileReader(fieldName, fileName string, content io.Reader, mimeType string) *FormData

AddFileReader adds a file from an io.Reader

func (*FormData) Encode

func (f *FormData) Encode() ([]byte, string, error)

Encode encodes the form data as multipart/form-data Returns the body bytes and the Content-Type header value (with boundary)

type FormFile

type FormFile struct {
	FieldName string    // Form field name
	FileName  string    // File name
	Content   io.Reader // File content
	MIMEType  string    // MIME type (optional, will be detected)
}

FormFile represents a file to upload

type H added in v1.5.3

type H map[string]string

H is a shorthand for creating single-value headers. Use this for convenience when you only need one value per header.

Example:

headers := client.H{
    "Content-Type": "application/json",
    "Accept": "application/json",
}
req := &client.Request{
    URL: "https://example.com",
    Headers: headers.ToMulti(),
}

func (H) ToMulti added in v1.5.3

func (h H) ToMulti() map[string][]string

ToMulti converts H to map[string][]string for use with Request.Headers

type HTTP3Client

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

HTTP3Client is an HTTP/3 client with QUIC connection pooling

func NewHTTP3Client

func NewHTTP3Client(presetName string) *HTTP3Client

NewHTTP3Client creates a new HTTP/3 client

func NewHTTP3ClientWithDNS

func NewHTTP3ClientWithDNS(presetName string, dnsCache interface{}) *HTTP3Client

NewHTTP3ClientWithDNS creates a new HTTP/3 client with shared DNS cache

func (*HTTP3Client) Close

func (c *HTTP3Client) Close()

Close shuts down the client and all connections

func (*HTTP3Client) Do

func (c *HTTP3Client) Do(ctx context.Context, req *Request) (*Response, error)

Do executes an HTTP/3 request

func (*HTTP3Client) Get

func (c *HTTP3Client) Get(ctx context.Context, url string, headers map[string][]string) (*Response, error)

Get performs a GET request over HTTP/3

func (*HTTP3Client) Post

func (c *HTTP3Client) Post(ctx context.Context, url string, body io.Reader, headers map[string][]string) (*Response, error)

Post performs a POST request over HTTP/3

func (*HTTP3Client) SetPreset

func (c *HTTP3Client) SetPreset(presetName string)

SetPreset changes the fingerprint preset

func (*HTTP3Client) SetTimeout

func (c *HTTP3Client) SetTimeout(timeout time.Duration)

SetTimeout sets the request timeout

func (*HTTP3Client) Stats

func (c *HTTP3Client) Stats() map[string]struct {
	Total    int
	Healthy  int
	Requests int64
}

Stats returns QUIC connection pool statistics

type HookType

type HookType string

HookType represents the type of hook

const (
	// HookPreRequest is called before the request is sent
	HookPreRequest HookType = "pre_request"
	// HookPostResponse is called after the response is received
	HookPostResponse HookType = "post_response"
)

type Hooks

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

Hooks holds request hooks

func NewHooks

func NewHooks() *Hooks

NewHooks creates a new Hooks instance

func (*Hooks) Clear

func (h *Hooks) Clear()

Clear removes all hooks

func (*Hooks) ClearPostResponse

func (h *Hooks) ClearPostResponse()

ClearPostResponse removes all post-response hooks

func (*Hooks) ClearPreRequest

func (h *Hooks) ClearPreRequest()

ClearPreRequest removes all pre-request hooks

func (*Hooks) OnPostResponse

func (h *Hooks) OnPostResponse(hook PostResponseHook) *Hooks

OnPostResponse adds a post-response hook Hook is called after each response is received Can be used to log responses, collect metrics, etc.

func (*Hooks) OnPreRequest

func (h *Hooks) OnPreRequest(hook PreRequestHook) *Hooks

OnPreRequest adds a pre-request hook Hook is called before each request is sent Can be used to modify headers, log requests, etc.

func (*Hooks) RunPostResponse

func (h *Hooks) RunPostResponse(resp *Response) error

RunPostResponse runs all post-response hooks

func (*Hooks) RunPreRequest

func (h *Hooks) RunPreRequest(req *http.Request) error

RunPreRequest runs all pre-request hooks

type Option

type Option func(*ClientConfig)

Option is a function that modifies ClientConfig

func WithConnectTo added in v1.5.2

func WithConnectTo(requestHost, connectHost string) Option

WithConnectTo sets a host mapping for domain fronting. Requests to requestHost will connect to connectHost instead. The TLS SNI and Host header will still use requestHost. Similar to curl's --connect-to option.

Example:

// Connect to cloudflare.com but request example.com
client.WithConnectTo("example.com", "www.cloudflare.com")

func WithDisableECH added in v1.5.8

func WithDisableECH() Option

WithDisableECH disables automatic ECH fetching from DNS. Chrome doesn't always use ECH even when available from DNS HTTPS records. Some sites may reject connections with ECH enabled. Use this option to match real Chrome behavior on sites that have ECH issues.

Example:

client.NewClient("chrome-143", client.WithDisableECH())

func WithDisableHTTP3

func WithDisableHTTP3() Option

WithDisableHTTP3 disables HTTP/3, allowing HTTP/2 with HTTP/1.1 fallback. Use WithForceHTTP2() if you want HTTP/2 only without fallback.

func WithDisableKeepAlives

func WithDisableKeepAlives() Option

WithDisableKeepAlives disables HTTP keep-alives

func WithECHConfig added in v1.5.2

func WithECHConfig(echConfig []byte) Option

WithECHConfig sets a custom ECH configuration. This overrides automatic ECH fetching from DNS. The config should be the raw ECHConfigList bytes.

Example:

// Use ECH config fetched from cloudflare-ech.com
echConfig, _ := dns.FetchECHConfigs(ctx, "cloudflare-ech.com")
client.WithECHConfig(echConfig)

func WithECHFrom added in v1.5.2

func WithECHFrom(domain string) Option

WithECHFrom sets a domain to fetch ECH config from. Instead of fetching ECH from the target domain's DNS, the config will be fetched from this domain. Useful for Cloudflare domains - use "cloudflare-ech.com" to get ECH config that works for any Cloudflare-proxied domain.

Example:

// Use Cloudflare's shared ECH config for any CF domain
client.WithECHFrom("cloudflare-ech.com")

func WithForceHTTP1

func WithForceHTTP1() Option

WithForceHTTP1 forces HTTP/1.1 for all requests. The client will only use HTTP/1.1, no HTTP/2 or HTTP/3.

func WithForceHTTP2

func WithForceHTTP2() Option

WithForceHTTP2 forces HTTP/2 for all requests. The client will only use HTTP/2, no HTTP/3 or HTTP/1.1 fallback. Use WithDisableHTTP3() if you want H2 with H1 fallback.

func WithForceHTTP3 added in v1.5.2

func WithForceHTTP3() Option

WithForceHTTP3 forces HTTP/3 (QUIC) for all requests. The client will only use HTTP/3, no HTTP/2 or HTTP/1.1 fallback. Requires a SOCKS5 or MASQUE proxy if using a proxy.

func WithInsecureSkipVerify

func WithInsecureSkipVerify() Option

WithInsecureSkipVerify disables TLS certificate verification WARNING: This makes the connection insecure and should only be used for testing

func WithPreferIPv4 added in v1.0.1

func WithPreferIPv4() Option

WithPreferIPv4 makes the client prefer IPv4 addresses over IPv6. Use this on networks with poor IPv6 connectivity.

func WithPreset

func WithPreset(preset string) Option

WithPreset sets the fingerprint preset

func WithProxy

func WithProxy(proxyURL string) Option

WithProxy sets the proxy URL. Supported proxy types:

For HTTP/3 through a proxy, use either:

  • SOCKS5 proxy with UDP relay support
  • MASQUE proxy (known providers like Bright Data are auto-detected with https:// scheme)

Authentication can be included in the URL: "http://user:pass@host:port"

func WithRedirects

func WithRedirects(follow bool, maxRedirects int) Option

WithRedirects configures redirect behavior

func WithRetry

func WithRetry(maxRetries int) Option

WithRetry enables retry with default settings

func WithRetryConfig

func WithRetryConfig(maxRetries int, waitMin, waitMax time.Duration, retryOnStatus []int) Option

WithRetryConfig configures retry behavior

func WithTCPProxy added in v1.5.3

func WithTCPProxy(proxyURL string) Option

WithTCPProxy sets the proxy URL for TCP-based protocols (HTTP/1.1 and HTTP/2). Use this with WithUDPProxy for split proxy configuration where different proxies handle TCP and UDP traffic.

Supported proxy types:

Example:

client.WithTCPProxy("http://user:pass@datacenter-proxy:8080")

func WithTLSConfig

func WithTLSConfig(tlsConfig *tls.Config) Option

WithTLSConfig sets a custom TLS configuration

func WithTLSOnly added in v1.5.8

func WithTLSOnly() Option

WithTLSOnly enables TLS-only mode. In this mode, the preset's TLS fingerprint (JA3/JA4, cipher suites, extension order) is applied, but the preset's default HTTP headers are NOT added. You must set all headers manually per-request. Useful when you need full control over HTTP headers while keeping the TLS fingerprint.

func WithTimeout

func WithTimeout(timeout time.Duration) Option

WithTimeout sets the request timeout

func WithUDPProxy added in v1.5.3

func WithUDPProxy(proxyURL string) Option

WithUDPProxy sets the proxy URL for UDP-based protocols (HTTP/3 via MASQUE). Use this with WithTCPProxy for split proxy configuration where different proxies handle TCP and UDP traffic.

This is useful for providers like Bright Data that only support MASQUE for HTTP/3 traffic but don't support HTTP/1.1 or HTTP/2 through the same endpoint.

Supported proxy types:

Example:

client.WithUDPProxy("masque://user:pass@brd.superproxy.io:443")

func WithoutRedirects

func WithoutRedirects() Option

WithoutRedirects disables automatic redirect following

func WithoutRetry added in v1.0.5

func WithoutRetry() Option

WithoutRetry explicitly disables retry

type PinOption

type PinOption func(*CertificatePin)

PinOption configures a certificate pin

func ForHost

func ForHost(host string) PinOption

ForHost restricts the pin to a specific host

func IncludeSubdomains

func IncludeSubdomains() PinOption

IncludeSubdomains applies the pin to subdomains as well

type PinType

type PinType int

PinType represents the type of certificate pin

const (
	// PinTypeSHA256 uses SHA256 hash of the certificate's Subject Public Key Info (SPKI)
	// This is the standard format used by HPKP and Chrome
	PinTypeSHA256 PinType = iota
	// PinTypeCertificate pins to the entire certificate
	PinTypeCertificate
)

type PostResponseHook

type PostResponseHook func(resp *Response) error

PostResponseHook is called after a response is received It receives the Response and can inspect/modify it Return an error to signal a problem (won't affect the response)

type PreRequestHook

type PreRequestHook func(req *http.Request) error

PreRequestHook is called before a request is sent It receives the http.Request and can modify it Return an error to abort the request

type PreparedRequest

type PreparedRequest struct {
	// The underlying http.Request
	HTTPRequest *http.Request

	// Original request data (for reference)
	Method  string
	URL     string
	Headers map[string][]string
	Body    []byte // Cached body bytes

	// Configuration
	Timeout       int64    // Timeout in milliseconds
	ForceProtocol Protocol // Forced protocol
	FetchMode     FetchMode
	FetchSite     FetchSite
	FetchDest     string
	Referer       string
	Auth          Auth

	// Redirect settings
	FollowRedirects bool
	MaxRedirects    int
	// contains filtered or unexported fields
}

PreparedRequest is a request that has been prepared for sending It allows inspection and modification before actual execution

func (*PreparedRequest) AddHeader

func (p *PreparedRequest) AddHeader(key, value string) *PreparedRequest

AddHeader adds a header to the prepared request (allows multiple values)

func (*PreparedRequest) DelHeader

func (p *PreparedRequest) DelHeader(key string) *PreparedRequest

DelHeader removes a header from the prepared request

func (*PreparedRequest) GetAllHeaders

func (p *PreparedRequest) GetAllHeaders() http.Header

GetAllHeaders returns all headers

func (*PreparedRequest) GetHeader

func (p *PreparedRequest) GetHeader(key string) string

GetHeader gets a header value from the prepared request

func (*PreparedRequest) Send

func (p *PreparedRequest) Send(ctx context.Context) (*Response, error)

Send executes the prepared request

func (*PreparedRequest) SetAuth

func (p *PreparedRequest) SetAuth(auth Auth) *PreparedRequest

SetAuth sets authentication on the prepared request

func (*PreparedRequest) SetBody

func (p *PreparedRequest) SetBody(body []byte) *PreparedRequest

SetBody sets a new body on the prepared request

func (*PreparedRequest) SetForceProtocol

func (p *PreparedRequest) SetForceProtocol(protocol Protocol) *PreparedRequest

SetForceProtocol sets the forced protocol

func (*PreparedRequest) SetHeader

func (p *PreparedRequest) SetHeader(key, value string) *PreparedRequest

SetHeader sets a header on the prepared request

func (*PreparedRequest) SetTimeout

func (p *PreparedRequest) SetTimeout(ms int64) *PreparedRequest

SetTimeout sets the timeout in milliseconds

type Protocol

type Protocol int

Protocol enum for forcing specific HTTP protocol versions

const (
	ProtocolAuto  Protocol = iota // Auto-detect (H3 -> H2 -> H1 fallback)
	ProtocolHTTP1                 // Force HTTP/1.1
	ProtocolHTTP2                 // Force HTTP/2
	ProtocolHTTP3                 // Force HTTP/3
)

func (Protocol) String

func (p Protocol) String() string

String returns the string representation of the protocol

type RedirectInfo

type RedirectInfo struct {
	StatusCode int
	URL        string
	Headers    map[string][]string // Multi-value headers
}

RedirectInfo stores information about a redirect

type Request

type Request struct {
	Method  string
	URL     string
	Headers map[string][]string // Multi-value headers (matches http.Header)
	Body    io.Reader           // Streaming body for uploads
	Timeout time.Duration

	// Customization options
	UserAgent     string    // Override User-Agent (empty = use preset)
	ForceProtocol Protocol  // Force specific protocol (ProtocolAuto = auto)
	FetchMode     FetchMode // Fetch mode: Navigate (default, human click) or CORS (XHR/fetch) or NoCors (subresource)
	FetchSite     FetchSite // Sec-Fetch-Site: Auto (default), None, SameOrigin, SameSite, CrossSite
	FetchDest     string    // Sec-Fetch-Dest for NoCors mode: "script", "style", "image" (empty = use mode default)
	Referer       string    // Referer header (used for auto-detecting FetchSite)

	// Authentication (overrides client-level auth)
	Auth Auth

	// Params adds query parameters to the URL
	Params map[string]string

	// Per-request redirect override (nil = use client config)
	FollowRedirects *bool
	MaxRedirects    int

	// Per-request retry override (nil = use client config)
	DisableRetry bool
}

Request represents an HTTP request

func (*Request) AddHeader added in v1.5.3

func (r *Request) AddHeader(key, value string)

AddHeader adds a header value, preserving existing values.

func (*Request) GetHeader added in v1.5.3

func (r *Request) GetHeader(key string) string

GetHeader returns the first value for the given header key (case-insensitive).

func (*Request) SetHeader added in v1.5.3

func (r *Request) SetHeader(key, value string)

SetHeader sets a header value, replacing any existing values.

type RequestError

type RequestError struct {
	Op  string
	Err string
}

RequestError represents a request-level error

func (*RequestError) Error

func (e *RequestError) Error() string

type Response

type Response struct {
	StatusCode int
	Headers    map[string][]string // Multi-value headers (matches http.Header)
	Body       io.ReadCloser       // Streaming body - call Close() when done
	FinalURL   string
	Timing     *protocol.Timing
	Protocol   string // "h3" or "h2"

	// Request info
	Request *Request

	// Redirect history
	RedirectHistory []*RedirectInfo
	// contains filtered or unexported fields
}

Response represents an HTTP response

func (*Response) Bytes added in v1.5.3

func (r *Response) Bytes() ([]byte, error)

Bytes reads and returns the entire response body. The body can only be read once unless cached.

func (*Response) Close added in v1.5.3

func (r *Response) Close() error

Close closes the response body.

func (*Response) GetHeader added in v1.5.3

func (r *Response) GetHeader(key string) string

GetHeader returns the first value for the given header key (case-insensitive).

func (*Response) GetHeaders added in v1.5.3

func (r *Response) GetHeaders(key string) []string

GetHeaders returns all values for the given header key (case-insensitive).

func (*Response) IsClientError

func (r *Response) IsClientError() bool

IsClientError returns true if the status code is 4xx

func (*Response) IsRedirect

func (r *Response) IsRedirect() bool

IsRedirect returns true if the status code is 3xx

func (*Response) IsServerError

func (r *Response) IsServerError() bool

IsServerError returns true if the status code is 5xx

func (*Response) IsSuccess

func (r *Response) IsSuccess() bool

IsSuccess returns true if the status code is 2xx

func (*Response) JSON

func (r *Response) JSON(v interface{}) error

JSON decodes the response body as JSON into the given interface

func (*Response) Text

func (r *Response) Text() (string, error)

Text returns the response body as a string

type SSEEvent

type SSEEvent struct {
	Event string
	Data  string
	ID    string
	Retry int
}

SSEEvent represents a Server-Sent Event

type SSEReader

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

SSEReader provides Server-Sent Events parsing

func NewSSEReader

func NewSSEReader(resp *StreamResponse) *SSEReader

NewSSEReader creates an SSE reader from a streaming response

func (*SSEReader) Close

func (r *SSEReader) Close() error

Close closes the underlying response

func (*SSEReader) Events

func (r *SSEReader) Events() <-chan *SSEEvent

Events returns a channel that yields SSE events Close the reader when done to stop iteration

func (*SSEReader) Next

func (r *SSEReader) Next() (*SSEEvent, error)

Next reads the next SSE event Returns nil, io.EOF when stream ends

type StreamResponse

type StreamResponse struct {
	StatusCode    int
	Headers       map[string][]string
	FinalURL      string
	Timing        *protocol.Timing
	Protocol      string
	ContentLength int64 // -1 if unknown (chunked encoding)

	// Request info
	Request *Request
	// contains filtered or unexported fields
}

StreamResponse represents a streaming HTTP response

func (*StreamResponse) Close

func (r *StreamResponse) Close() error

Close closes the response body and cancels the context

func (*StreamResponse) IsSuccess

func (r *StreamResponse) IsSuccess() bool

IsSuccess returns true if the status code is 2xx

func (*StreamResponse) Lines

func (r *StreamResponse) Lines() <-chan string

Lines returns a channel that yields lines from the response Close the response when done to stop iteration

func (*StreamResponse) Read

func (r *StreamResponse) Read(p []byte) (n int, err error)

Read reads data from the response body

func (*StreamResponse) ReadAll

func (r *StreamResponse) ReadAll() ([]byte, error)

ReadAll reads the entire response body into memory

func (*StreamResponse) Scanner

func (r *StreamResponse) Scanner() *bufio.Scanner

Scanner returns a bufio.Scanner for line-by-line reading

type URLBuilder

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

URLBuilder helps build URLs with query parameters

func NewURLBuilder

func NewURLBuilder(baseURL string) *URLBuilder

NewURLBuilder creates a new URLBuilder from a base URL

func (*URLBuilder) AddParam

func (b *URLBuilder) AddParam(key, value string) *URLBuilder

AddParam adds a query parameter (allows multiple values for same key)

func (*URLBuilder) Build

func (b *URLBuilder) Build() string

Build builds the final URL string

func (*URLBuilder) BuildSorted

func (b *URLBuilder) BuildSorted() string

BuildSorted builds the final URL with sorted query parameters Useful for consistent URL generation (e.g., for caching)

func (*URLBuilder) Param

func (b *URLBuilder) Param(key, value string) *URLBuilder

Param adds a single query parameter

func (*URLBuilder) Params

func (b *URLBuilder) Params(params map[string]string) *URLBuilder

Params adds multiple query parameters from a map

Jump to

Keyboard shortcuts

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