Documentation
¶
Overview ¶
Package fetch provides the dual-mode fetching layer for Foxhound.
stealth_default.go is a FALLBACK with NO TLS fingerprint impersonation. Production code should build with -tags tls to use stealth_tls.go. Without -tags tls, the TLS ClientHello is Go's crypto/tls default — trivially detected by every modern anti-bot system. Headers will look like Firefox but the TLS layer will not. This is almost always the wrong choice for scraping production targets that have any bot defence.
To verify which build you have:
fetcher := fetch.NewStealth(...)
if !fetcher.IsImpersonating() { log.Fatal("built without -tags tls") }
Or check the binary:
go tool nm /path/to/binary | grep -q azuretls && echo OK || echo MISSING
Build the impersonating variant with:
go build -tags tls ./... go test -tags tls ./fetch/...
Index ¶
- Constants
- func ContentOnlyResources() map[ResourceType]bool
- func DefaultBlockedResources() map[ResourceType]bool
- type BlockDetector
- type BrowserCookie
- type CamoufoxFetcher
- func (f *CamoufoxFetcher) Close() error
- func (f *CamoufoxFetcher) ExportStorageState() (*StorageState, error)
- func (f *CamoufoxFetcher) Fetch(_ context.Context, _ *foxhound.Job) (*foxhound.Response, error)
- func (f *CamoufoxFetcher) LoadStorageState() (*StorageState, error)
- func (f *CamoufoxFetcher) SaveStorageState() error
- type CamoufoxOption
- func WithBehaviorProfile(p *behavior.BehaviorProfile) CamoufoxOption
- func WithBlockImages(block bool) CamoufoxOption
- func WithBrowserCookies(cookies []BrowserCookie) CamoufoxOption
- func WithBrowserIdentity(p *identity.Profile) CamoufoxOption
- func WithBrowserProxy(proxyURL string) CamoufoxOption
- func WithBrowserTimeout(d time.Duration) CamoufoxOption
- func WithCDPURL(url string) CamoufoxOption
- func WithCaptureXHR(patterns ...*regexp.Regexp) CamoufoxOption
- func WithExtensionPath(path string) CamoufoxOption
- func WithHeadless(mode string) CamoufoxOption
- func WithInitScript(script string) CamoufoxOption
- func WithInterceptConfig(ic *InterceptConfig) CamoufoxOption
- func WithMaxBrowserRequests(n int) CamoufoxOption
- func WithPageReuseLimit(n int) CamoufoxOption
- func WithPersistSession(persist bool) CamoufoxOption
- func WithPoolSize(n int) CamoufoxOption
- func WithRealChrome(use bool) CamoufoxOption
- func WithSkipExtension() CamoufoxOption
- func WithSolveCloudflare(timeout time.Duration) CamoufoxOption
- func WithStorageState(path string) CamoufoxOption
- func WithUserDataDir(dir string) CamoufoxOption
- type CapturePattern
- type CapturedExchange
- type ContentBlockDetector
- type DefaultBlockDetector
- type DisplayManager
- type DisplayOption
- type DomainScore
- type DomainScoreAction
- type DomainScoreConfig
- type DomainScorer
- type InterceptConfig
- type OriginStorage
- type PagePool
- func (p *PagePool) Acquire(ctx context.Context) (any, error)
- func (p *PagePool) AcquireWithTimeout(timeout time.Duration) (any, error)
- func (p *PagePool) Busy() int64
- func (p *PagePool) Close() error
- func (p *PagePool) Free() int64
- func (p *PagePool) Release(page any)
- func (p *PagePool) Stats() PagePoolStats
- func (p *PagePool) Total() int64
- func (p *PagePool) WarmUp(n int) int
- type PagePoolOption
- type PagePoolStats
- type ResourceType
- type SmartFetcher
- type SmartOption
- type StealthFetcher
- type StealthOption
- func WithHTTP2Fingerprint(_ string) StealthOption
- func WithHTTP3Fingerprint(_ string) StealthOption
- func WithIdentity(p *identity.Profile) StealthOption
- func WithJA3(_ string) StealthOption
- func WithJA3Pool(pool []string) StealthOption
- func WithProxy(proxyURL string) StealthOption
- func WithTimeout(d time.Duration) StealthOption
- type StorageState
Constants ¶
const CaptureXHRMetaKey = "_foxhound_capture_xhr"
CaptureXHRMetaKey is the Job.Meta key under which Trail.CaptureXHR stores per-job XHR capture URL patterns. The walker passes the job through to the camoufox fetcher unchanged; the fetcher merges these patterns with any fetcher-global patterns configured via WithCaptureXHR.
Variables ¶
This section is empty.
Functions ¶
func ContentOnlyResources ¶
func ContentOnlyResources() map[ResourceType]bool
ContentOnlyResources returns a minimal set of resources to block that preserves page layout while eliminating heavy binary assets. Stylesheets are NOT blocked so the page renders correctly for layout-dependent extraction.
func DefaultBlockedResources ¶
func DefaultBlockedResources() map[ResourceType]bool
DefaultBlockedResources returns the standard set of resource types to block for speed optimization. Blocking these typically cuts page load time by 30-70% for content-only scraping.
Types ¶
type BlockDetector ¶
type BlockDetector interface {
// IsBlocked returns true when the response should trigger escalation to
// the browser fetcher.
IsBlocked(resp *foxhound.Response) bool
}
BlockDetector determines whether an HTTP response indicates that the server has blocked or rate-limited the scraper.
type BrowserCookie ¶
type BrowserCookie struct {
Name string
Value string
Domain string
Path string
Secure bool
HttpOnly bool
}
BrowserCookie represents a cookie to inject into the browser context.
type CamoufoxFetcher ¶
type CamoufoxFetcher struct {
// contains filtered or unexported fields
}
CamoufoxFetcher drives a Camoufox (Firefox fork) browser instance via the Juggler protocol using playwright-go.
Stub build (!playwright tag): Fetch always returns errPlaywrightNotConfigured. Real build ( playwright tag): see camoufox_playwright.go.
func NewCamoufox ¶
func NewCamoufox(opts ...CamoufoxOption) (*CamoufoxFetcher, error)
NewCamoufox creates a CamoufoxFetcher. In the stub build no browser is launched; the constructor stores the configuration and returns immediately.
func (*CamoufoxFetcher) Close ¶
func (f *CamoufoxFetcher) Close() error
Close is a no-op in the stub build; no resources were allocated.
func (*CamoufoxFetcher) ExportStorageState ¶
func (f *CamoufoxFetcher) ExportStorageState() (*StorageState, error)
ExportStorageState is a stub; always returns an error in the non-playwright build.
func (*CamoufoxFetcher) Fetch ¶
Fetch always returns errPlaywrightNotConfigured in the stub build. Rebuild with -tags playwright to enable real browser navigation.
func (*CamoufoxFetcher) LoadStorageState ¶
func (f *CamoufoxFetcher) LoadStorageState() (*StorageState, error)
LoadStorageState reads saved state from the configured file path. Returns (nil, nil) when no path is set or the file does not exist yet.
func (*CamoufoxFetcher) SaveStorageState ¶
func (f *CamoufoxFetcher) SaveStorageState() error
SaveStorageState exports and saves the session state to the configured file path. In the stub build, this falls back to saving the in-memory cookie list.
type CamoufoxOption ¶
type CamoufoxOption func(*CamoufoxFetcher)
CamoufoxOption is a functional option for configuring a CamoufoxFetcher.
func WithBehaviorProfile ¶
func WithBehaviorProfile(p *behavior.BehaviorProfile) CamoufoxOption
WithBehaviorProfile sets the behavior profile for scroll and keyboard configs. In the stub build this stores the value but has no effect.
func WithBlockImages ¶
func WithBlockImages(block bool) CamoufoxOption
WithBlockImages controls whether the browser route handler intercepts and aborts image/media/font requests. Reduces bandwidth and speeds up navigation for content-only scraping.
func WithBrowserCookies ¶
func WithBrowserCookies(cookies []BrowserCookie) CamoufoxOption
WithBrowserCookies sets cookies to inject into the browser context before page navigation. Useful for pre-authenticated sessions.
func WithBrowserIdentity ¶
func WithBrowserIdentity(p *identity.Profile) CamoufoxOption
WithBrowserIdentity sets the identity profile used to configure the Camoufox browser context. All CAMOU_CONFIG environment variables are derived from p.
func WithBrowserProxy ¶
func WithBrowserProxy(proxyURL string) CamoufoxOption
WithBrowserProxy sets the proxy URL for all browser requests. Supports SOCKS5 (socks5://user:pass@host:port) and HTTP (http://user:pass@host:port).
func WithBrowserTimeout ¶
func WithBrowserTimeout(d time.Duration) CamoufoxOption
WithBrowserTimeout overrides the default per-navigation timeout.
func WithCDPURL ¶
func WithCDPURL(url string) CamoufoxOption
WithCDPURL sets a Chrome DevTools Protocol endpoint URL (e.g. "http://localhost:9222"). When non-empty the real build connects to that existing browser instance via pw.Chromium.ConnectOverCDP instead of launching a new browser process. In the stub build this stores the value but has no effect.
func WithCaptureXHR ¶
func WithCaptureXHR(patterns ...*regexp.Regexp) CamoufoxOption
WithCaptureXHR configures URL patterns for XHR/fetch response capture. Captured responses are available in Response.CapturedXHR after fetch.
func WithExtensionPath ¶
func WithExtensionPath(path string) CamoufoxOption
WithExtensionPath sets the path to a Firefox extension directory to load. By default, NopeCHA is auto-downloaded and loaded. Set to "none" to disable. In the stub build this stores the value but has no effect — the extension is only loaded when compiled with the playwright build tag.
func WithHeadless ¶
func WithHeadless(mode string) CamoufoxOption
WithHeadless sets the display mode for the Camoufox browser:
- "virtual": Xvfb virtual display (recommended on servers without a GPU)
- "true": native headless mode
- "false": full visible browser (useful for local debugging)
func WithInitScript ¶
func WithInitScript(script string) CamoufoxOption
WithInitScript sets a JavaScript snippet that is injected into every new page before the page's own scripts execute. This is useful for overriding navigator properties (e.g. navigator.webdriver) or installing global hooks. In the stub build this stores the value but has no effect.
func WithInterceptConfig ¶
func WithInterceptConfig(ic *InterceptConfig) CamoufoxOption
WithInterceptConfig wires a route-level blocking configuration into the browser. Resources matching BlockedResourceTypes are aborted before they reach the network, and requests to BlockedDomains (or their subdomains) are also aborted. Use NewInterceptConfig to construct the value, then pass it here. In the stub build this stores the value but has no effect.
func WithMaxBrowserRequests ¶
func WithMaxBrowserRequests(n int) CamoufoxOption
WithMaxBrowserRequests configures the browser instance to be restarted after serving n requests. This clears accumulated state (cookies, cache, memory leaks) and rotates the browser fingerprint.
Set n=0 to disable automatic restarts (not recommended for long-running hunts). The default is 300.
func WithPageReuseLimit ¶
func WithPageReuseLimit(n int) CamoufoxOption
WithPageReuseLimit sets the maximum number of requests a pooled page handles before being destroyed and replaced. This prevents long-lived pages from accumulating state that increases detection risk. Default 0 means unlimited. Recommended: 50-200 for anti-detection scraping. In the stub build this stores the value but has no effect.
func WithPersistSession ¶
func WithPersistSession(persist bool) CamoufoxOption
WithPersistSession controls whether the same BrowserContext is reused across requests for the same walker session (cookies and localStorage are preserved between fetches). When false (default) a fresh context is created per fetch for full isolation between requests.
Use true when scraping sites that require login state to be maintained across multiple page visits in a single session.
func WithPoolSize ¶
func WithPoolSize(n int) CamoufoxOption
WithPoolSize enables page pooling with the given max size. When enabled, browser contexts and pages are reused instead of created fresh for each request, significantly reducing per-request overhead (~3s context creation cost is eliminated after warmup). Only applies when PersistSession is false (non-persistent mode). Set to 0 (default) to disable pooling and use per-request contexts. In the stub build this stores the value but has no effect.
func WithRealChrome ¶
func WithRealChrome(use bool) CamoufoxOption
WithRealChrome switches the real build from Firefox/Camoufox to pw.Chromium.Launch with channel="chrome". Use this when you need Chrome's rendering behaviour or have a Chrome installation but not Camoufox. Falls back to Chromium if the Chrome channel is not installed. In the stub build this stores the value but has no effect.
func WithSkipExtension ¶
func WithSkipExtension() CamoufoxOption
WithSkipExtension prevents the NopeCHA addon from being auto-loaded. Use when the NopeCHA Token API solver is active — the API and addon should not run simultaneously. In the stub build this stores the value but has no effect.
func WithSolveCloudflare ¶
func WithSolveCloudflare(timeout time.Duration) CamoufoxOption
WithSolveCloudflare enables verified Cloudflare challenge resolution. After the existing handler runs (extension addon or manual click), the fetcher polls for up to timeout for three success signals: the cf_clearance cookie is present, Turnstile DOM markers are gone, and the cf-turnstile-response token is set. When all three pass within the budget the resulting Response has CloudflareSolved=true. On timeout the fetch is NOT failed; the response is still returned with CloudflareSolved=false so callers can decide whether to retry, escalate, or accept a partial page.
Pass 0 to disable verified-solve mode (default behaviour).
In the stub build this stores the value but has no effect.
func WithStorageState ¶
func WithStorageState(path string) CamoufoxOption
WithStorageState sets a file path for session state persistence. In the stub build this stores the value but has no effect.
func WithUserDataDir ¶
func WithUserDataDir(dir string) CamoufoxOption
WithUserDataDir sets a persistent profile directory. When non-empty the real build uses LaunchPersistentContext so cookies, localStorage, and cached resources survive across browser restarts. In the stub build this stores the value but has no effect.
type CapturePattern ¶
CapturePattern defines a URL pattern to capture.
type CapturedExchange ¶
type CapturedExchange struct {
RequestURL string `json:"request_url"`
RequestMethod string `json:"request_method"`
Status int `json:"status"`
Headers map[string]string `json:"headers,omitempty"`
Body []byte `json:"body,omitempty"`
}
CapturedExchange holds a captured XHR/fetch request-response pair.
type ContentBlockDetector ¶
type ContentBlockDetector struct{}
ContentBlockDetector extends status-code-only detection with body-based CAPTCHA and soft-block detection using the captcha package. This is the default detector used by NewSmart.
type DefaultBlockDetector ¶
type DefaultBlockDetector struct{}
DefaultBlockDetector treats common anti-scraping status codes as blocks: 401 Unauthorised, 403 Forbidden, 407 Proxy Auth Required, 429 Too Many Requests, 503 Service Unavailable.
type DisplayManager ¶
type DisplayManager struct{}
DisplayManager is a no-op stub when playwright is not enabled.
func NewDisplayManager ¶
func NewDisplayManager(opts ...DisplayOption) (*DisplayManager, error)
NewDisplayManager returns nil in the stub build — Xvfb is never needed without playwright.
func (*DisplayManager) Close ¶
func (d *DisplayManager) Close() error
Close is a no-op in the stub build.
func (*DisplayManager) Display ¶
func (d *DisplayManager) Display() string
Display returns an empty string in the stub build.
type DisplayOption ¶
type DisplayOption func(*DisplayManager)
DisplayOption is a functional option (no-op in stub build).
func WithDisplayNumber ¶
func WithDisplayNumber(n int) DisplayOption
WithDisplayNumber is a no-op in the stub build.
func WithScreenResolution ¶
func WithScreenResolution(res string) DisplayOption
WithScreenResolution is a no-op in the stub build.
type DomainScore ¶
type DomainScore struct {
// contains filtered or unexported fields
}
DomainScore tracks static vs browser fetch outcomes for a single domain using a Bayesian Beta distribution model.
Risk score formula (Beta posterior mean):
risk = (blocked + priorAlpha) / (blocked + success + priorAlpha + priorBeta)
With prior Beta(1, 3): assumes static usually works (75% prior success rate). As blocked events accumulate, risk rises toward 1.0.
Time decay ensures old outcomes fade:
effective_count = count * exp(-age / halflife)
type DomainScoreAction ¶
type DomainScoreAction int
DomainScoreAction indicates what the SmartFetcher should do.
const ( // ActionStaticNormal means use static with normal timeout. ActionStaticNormal DomainScoreAction = iota // ActionStaticCautious means use static but with a shorter timeout (fail-fast). ActionStaticCautious // ActionBrowserDirect means skip static and go directly to browser. ActionBrowserDirect )
type DomainScoreConfig ¶
type DomainScoreConfig struct {
// PriorAlpha is the Beta distribution prior for blocked (default 1.0).
PriorAlpha float64
// PriorBeta is the Beta distribution prior for success (default 3.0).
PriorBeta float64
// EscalationThreshold: if risk > this, skip static entirely (default 0.6).
EscalationThreshold float64
// CautionThreshold: if risk > this, use static with shorter timeout (default 0.3).
CautionThreshold float64
// DecayHalflife: old outcomes decay with this half-life (default 1h).
DecayHalflife time.Duration
}
DomainScoreConfig controls the learning behavior.
func DefaultDomainScoreConfig ¶
func DefaultDomainScoreConfig() DomainScoreConfig
DefaultDomainScoreConfig returns sensible defaults.
func SocialMediaScoreConfig ¶
func SocialMediaScoreConfig() DomainScoreConfig
SocialMediaScoreConfig returns a configuration tuned for social media targets where static fetches are almost always blocked. Prior Beta(3,1) = 75% prior block rate — escalates after just 1 blocked attempt.
type DomainScorer ¶
type DomainScorer struct {
// contains filtered or unexported fields
}
DomainScorer manages per-domain risk scores.
func NewDomainScorer ¶
func NewDomainScorer(cfg DomainScoreConfig) *DomainScorer
NewDomainScorer creates a scorer with the given configuration.
func (*DomainScorer) Recommend ¶
func (ds *DomainScorer) Recommend(domain string) DomainScoreAction
Recommend returns the recommended fetch action for a domain.
func (*DomainScorer) RecordBrowser ¶
func (ds *DomainScorer) RecordBrowser(domain string, blocked bool)
RecordBrowser records the outcome of a browser fetch for the given domain.
func (*DomainScorer) RecordStatic ¶
func (ds *DomainScorer) RecordStatic(domain string, blocked bool)
RecordStatic records the outcome of a static fetch for the given domain.
func (*DomainScorer) Risk ¶
func (ds *DomainScorer) Risk(domain string) float64
Risk returns the current risk score for a domain (probability that static will be blocked). Uses Bayesian Beta posterior mean with time decay.
type InterceptConfig ¶
type InterceptConfig struct {
// BlockedResourceTypes maps resource types (e.g. "font", "stylesheet")
// to true for those that should be aborted.
BlockedResourceTypes map[ResourceType]bool
// BlockedDomains maps domain names to true. Subdomains are also matched:
// "example.com" blocks "sub.example.com".
BlockedDomains map[string]bool
}
InterceptConfig configures what to block during browser navigation. It combines resource-type filtering and domain-level blocking into a single check that is called for every network request via the browser's route handler.
func NewInterceptConfig ¶
func NewInterceptConfig(resourceTypes map[ResourceType]bool, domains map[string]bool) *InterceptConfig
NewInterceptConfig creates an InterceptConfig with the given resource types and domains to block.
func (*InterceptConfig) IsActive ¶
func (ic *InterceptConfig) IsActive() bool
IsActive returns true if any blocking rules are configured.
func (*InterceptConfig) ShouldBlock ¶
func (ic *InterceptConfig) ShouldBlock(resourceType string, requestURL string) bool
ShouldBlock returns true if the given resource type and URL should be blocked based on this configuration.
type OriginStorage ¶
type OriginStorage struct {
Origin string `json:"origin"`
LocalStorage map[string]string `json:"local_storage"`
}
OriginStorage represents localStorage/sessionStorage for a single origin.
type PagePool ¶
type PagePool struct {
// contains filtered or unexported fields
}
PagePool manages a pool of reusable browser pages/tabs. Instead of creating a fresh browser context + page for every fetch, the pool maintains a set of warm pages that are checked out, used, and returned. This eliminates the per-request overhead of context creation (~200ms) and reduces memory churn.
Pages are reset between uses (cookies cleared, navigated to about:blank) to prevent session bleed. The pool is safe for concurrent use.
Usage:
pool := NewPagePool(8, createPageFunc, destroyPageFunc)
defer pool.Close()
page, err := pool.Acquire(ctx)
if err != nil { ... }
defer pool.Release(page)
func NewPagePool ¶
func NewPagePool(maxSize int, create func() (any, error), destroy func(any) error, opts ...PagePoolOption) *PagePool
NewPagePool creates a pool of reusable browser pages with the given capacity. create is called to instantiate a new page; destroy is called when a page is evicted or the pool is closed.
func (*PagePool) Acquire ¶
Acquire checks out a page from the pool. If no pages are available and the pool hasn't reached maxSize, a new page is created. If maxSize is reached, Acquire blocks until a page is returned or ctx is cancelled.
func (*PagePool) AcquireWithTimeout ¶
AcquireWithTimeout is a convenience wrapper around Acquire with a timeout.
func (*PagePool) Release ¶
Release returns a page to the pool. If a reset function is configured, the page is reset before being made available. If reset fails, the page is destroyed and a new slot opens.
Release is a no-op when called on a nil receiver, so callers may safely hold a snapshotted pool pointer that was nil-ed concurrently (e.g. during browser restart).
func (*PagePool) Stats ¶
func (p *PagePool) Stats() PagePoolStats
Stats returns pool usage statistics.
type PagePoolOption ¶
type PagePoolOption func(*PagePool)
PagePoolOption configures a PagePool.
func WithPageReset ¶
func WithPageReset(fn func(any) error) PagePoolOption
WithPageReset sets a function called when a page is returned to the pool. The reset function should clear cookies, navigate to about:blank, etc.
func WithPoolReuseLimit ¶
func WithPoolReuseLimit(n int) PagePoolOption
WithPoolReuseLimit sets the maximum number of times a page can be reused before it is destroyed and replaced. Default 0 means unlimited.
type PagePoolStats ¶
type PagePoolStats struct {
MaxSize int
Created int64
Acquired int64
Released int64
Recycled int64 // pages destroyed due to reuse limit
Idle int64
Busy int64 // currently checked out (Acquired - Released)
Total int64 // created and not destroyed
}
PagePoolStats holds pool usage metrics.
type ResourceType ¶
type ResourceType string
ResourceType represents a browser resource type that can be blocked during page navigation. These correspond to the resource types reported by playwright's route.request.resource_type.
const ( // ResourceFont matches font file requests (woff, woff2, ttf, otf, eot). ResourceFont ResourceType = "font" // ResourceImage matches image requests (png, jpg, gif, svg, webp, etc.). ResourceImage ResourceType = "image" // ResourceMedia matches audio/video requests (mp4, webm, ogg, mp3, etc.). ResourceMedia ResourceType = "media" // ResourceBeacon matches navigator.sendBeacon() requests. ResourceBeacon ResourceType = "beacon" // ResourceObject matches plugin requests (Flash, Java applets). ResourceObject ResourceType = "object" // ResourceImageSet matches <picture> source requests. ResourceImageSet ResourceType = "imageset" // ResourceTextTrack matches video subtitle/caption track requests. ResourceTextTrack ResourceType = "texttrack" // ResourceWebSocket matches WebSocket connection requests. ResourceWebSocket ResourceType = "websocket" // ResourceCSPReport matches Content-Security-Policy violation reports. ResourceCSPReport ResourceType = "csp_report" // ResourceStylesheet matches CSS stylesheet requests. ResourceStylesheet ResourceType = "stylesheet" )
type SmartFetcher ¶
type SmartFetcher struct {
// contains filtered or unexported fields
}
SmartFetcher routes each job to the appropriate fetcher. It implements foxhound.Fetcher and can be used transparently wherever a Fetcher is expected.
func NewSmart ¶
func NewSmart(static, browser foxhound.Fetcher, opts ...SmartOption) *SmartFetcher
NewSmart creates a SmartFetcher. static must not be nil; browser may be nil (in which case FetchAuto will never escalate beyond the static result).
Additional SmartOption values may be used to override the detector or either fetcher after construction.
func (*SmartFetcher) Close ¶
func (f *SmartFetcher) Close() error
Close releases resources held by both the static and browser fetchers. Errors from both fetchers are collected; if both fail the errors are joined.
func (*SmartFetcher) Fetch ¶
Fetch dispatches the job according to its FetchMode:
- FetchBrowser: calls the browser fetcher directly; returns an error if no browser fetcher is configured.
- FetchStatic: calls the static fetcher; no escalation regardless of the response status.
- FetchAuto: calls the static fetcher first. If the response is flagged as blocked AND a browser fetcher is available, escalates to the browser. If no browser fetcher is available, returns the static result with a warning log.
type SmartOption ¶
type SmartOption func(*SmartFetcher)
SmartOption is a functional option for configuring a SmartFetcher after construction. Options override the fetchers and detector set in NewSmart.
func WithBlockDetector ¶
func WithBlockDetector(d BlockDetector) SmartOption
WithBlockDetector replaces the default block detector with a custom one.
func WithBrowserFetcher ¶
func WithBrowserFetcher(fetcher foxhound.Fetcher) SmartOption
WithBrowserFetcher replaces the browser (Camoufox) fetcher.
func WithCautiousTimeout ¶
func WithCautiousTimeout(d time.Duration) SmartOption
WithCautiousTimeout sets the timeout for static fetches when the domain scorer recommends caution (moderate risk). Default is 5 seconds.
func WithDomainScorer ¶
func WithDomainScorer(scorer *DomainScorer) SmartOption
WithDomainScorer enables adaptive domain learning. When a scorer is provided, FetchAuto uses Bayesian risk scores to decide whether to attempt static fetching or skip directly to browser.
func WithStaticFetcher ¶
func WithStaticFetcher(fetcher foxhound.Fetcher) SmartOption
WithStaticFetcher replaces the static (HTTP) fetcher.
type StealthFetcher ¶
type StealthFetcher struct {
// contains filtered or unexported fields
}
StealthFetcher is the non-impersonating fallback used when the binary is built without -tags tls. The TLS ClientHello is Go's crypto/tls default (well-known JA3) — header ordering from the identity profile still applies but the TLS layer will not match a real browser.
func NewStealth ¶
func NewStealth(opts ...StealthOption) *StealthFetcher
NewStealth creates a StealthFetcher. Call with any number of StealthOption functional options to configure identity, timeout, and proxy.
IMPORTANT: this build does NOT perform TLS impersonation. See the package doc and IsImpersonating().
func (*StealthFetcher) Close ¶
func (f *StealthFetcher) Close() error
Close is a no-op for StealthFetcher; the underlying http.Client manages its own idle connections via the transport.
func (*StealthFetcher) Fetch ¶
Fetch performs an HTTP request using the stealth client and returns a foxhound.Response. The response FetchMode is always FetchStatic.
Header ordering follows identity.HeaderOrder to match browser fingerprints. If no identity is set a bare request is sent with minimal headers.
func (*StealthFetcher) IsImpersonating ¶ added in v0.0.18
func (f *StealthFetcher) IsImpersonating() bool
IsImpersonating reports whether this fetcher performs real JA3/JA4 TLS fingerprint impersonation. In the default (non-tls) build it always returns false; build with -tags tls to enable real impersonation.
type StealthOption ¶
type StealthOption func(*StealthFetcher)
StealthOption is a functional option for configuring a StealthFetcher.
func WithHTTP2Fingerprint ¶ added in v0.0.18
func WithHTTP2Fingerprint(_ string) StealthOption
WithHTTP2Fingerprint is a no-op in the default build. Build with -tags tls.
func WithHTTP3Fingerprint ¶ added in v0.0.18
func WithHTTP3Fingerprint(_ string) StealthOption
WithHTTP3Fingerprint is a no-op in the default build. Build with -tags tls.
func WithIdentity ¶
func WithIdentity(p *identity.Profile) StealthOption
WithIdentity sets the identity profile used to populate request headers. All headers (User-Agent, Accept-Language, Sec-Fetch-* etc.) are derived from this profile, ensuring internal consistency across UA, header order, and locale.
func WithJA3 ¶ added in v0.0.18
func WithJA3(_ string) StealthOption
WithJA3 is a no-op in the default (non-tls) build — the underlying net/http transport cannot customise the TLS ClientHello. Build with -tags tls for the real implementation.
func WithJA3Pool ¶ added in v0.0.18
func WithJA3Pool(pool []string) StealthOption
WithJA3Pool is a no-op in the default build. Build with -tags tls.
func WithProxy ¶
func WithProxy(proxyURL string) StealthOption
WithProxy sets a proxy URL on the underlying HTTP transport. The proxyURL must be a fully-qualified URL, e.g. "http://user:pass@host:port".
func WithTimeout ¶
func WithTimeout(d time.Duration) StealthOption
WithTimeout overrides the HTTP client timeout.
type StorageState ¶
type StorageState struct {
Cookies []BrowserCookie `json:"cookies"`
Origins []OriginStorage `json:"origins"`
ExportedAt time.Time `json:"exported_at"`
}
StorageState represents the full browser session state (cookies + localStorage + sessionStorage).
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package presets ships a single curated Firefox JA3 fingerprint that the stealth fetcher applies automatically when an identity profile is configured.
|
Package presets ships a single curated Firefox JA3 fingerprint that the stealth fetcher applies automatically when an identity profile is configured. |