bot

package
v0.0.0-...-48bd5f8 Latest Latest
Warning

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

Go to latest
Published: Apr 28, 2026 License: MIT Imports: 36 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// FingerprintModeSystem leaves the browser's native implementation in use.
	// No corresponding --fingerprint-* seed switch is passed.
	FingerprintModeSystem = fingerprint.ModeSystem
	// FingerprintModeFixed derives a stable seed from the browser profile
	// (user-data-dir) and persists it in go-bot's seed store.
	FingerprintModeFixed = fingerprint.ModeFixed
	// FingerprintModeRandom generates a fresh seed for every launch and does
	// not write it to the seed store.
	FingerprintModeRandom = fingerprint.ModeRandom
)
View Source
const (
	FingerprintWebRTCNative     = fingerprint.WebRTCModeNative
	FingerprintWebRTCReplace    = fingerprint.WebRTCModeReplace
	FingerprintWebRTCDisableUDP = fingerprint.WebRTCModeDisableUDP
)
View Source
const RetryAttemptsUnlimited = 0

RetryAttemptsUnlimited marks a retry policy as having no explicit attempt cap. The operation is then bounded only by its ambient context timeout. Prefer using this constant or RetryUnlimited over the zero value to make intent explicit.

Variables

View Source
var (
	ErrClosed            = errors.New("go-bot: closed")
	ErrPoolClosed        = errors.New("go-bot: browser pool closed")
	ErrNotImplemented    = errors.New("go-bot: not implemented")
	ErrTimeout           = errors.New("go-bot: timeout")
	ErrReconnectOverflow = errors.New("go-bot: reconnect event buffer overflow")
	ErrElementNotFound   = errors.New("go-bot: element not found")
	ErrShadowClosed      = errors.New("go-bot: shadow root is closed")
	ErrNavigationFailed  = errors.New("go-bot: navigation failed")
	ErrPageNotFound      = errors.New("go-bot: page not found")
	ErrContextNotFound   = errors.New("go-bot: context not found")
	ErrProfileInUse      = errors.New("go-bot: profile in use")
	ErrProfileBusy       = errors.New("go-bot: profile busy and endpoint unreachable")
	ErrStaleDevToolsPort = errors.New("go-bot: stale DevToolsActivePort")
)

Functions

func ClearContextCookiePreset

func ClearContextCookiePreset(ctx context.Context, c Context, preset CookieCleanupPreset, rawURL string) error

func ClearPageCookiePreset

func ClearPageCookiePreset(ctx context.Context, p Page, preset CookieCleanupPreset, rawURL string) error

func ExportContextCookiesToJar

func ExportContextCookiesToJar(ctx context.Context, c Context, jar http.CookieJar, rawURL string) error

func ExportPageCookiesToJar

func ExportPageCookiesToJar(ctx context.Context, p Page, jar http.CookieJar, rawURL string) error

func LoadContextCookiesFromJar

func LoadContextCookiesFromJar(ctx context.Context, c Context, jar http.CookieJar, rawURL string) error

func LoadPageCookiesFromJar

func LoadPageCookiesFromJar(ctx context.Context, p Page, jar http.CookieJar, rawURL string) error

func PiercingClick

func PiercingClick(ctx context.Context, page Page, backendNodeID int, opts ...ClickOption) error

PiercingClick performs an OS-level mouse click on the node identified by backendNodeID. Coordinates are computed via DOM.getBoxModel, which works for any node in the kernel's DOM tree — including nodes deep inside closed shadow roots that JS cannot see.

The click sequence (mouseMove + mousePressed + mouseReleased) is dispatched via the existing Page.Click(empty selector + position) path so that all the existing mouse-event hardening (button mapping, click count, delay, isTrusted handling) is reused.

Supported ClickOptions: WithClickButton, WithClickCount, WithClickDelay, WithClickPosition (interpreted as a pixel offset from the node's content-box center; useful when a node is large and you want to hit a specific corner).

func PiercingInputCheckbox

func PiercingInputCheckbox(n *PiercingNode) bool

PiercingInputCheckbox is a convenience predicate that matches <input type=checkbox> at any depth.

func PiercingRoleCheckbox

func PiercingRoleCheckbox(n *PiercingNode) bool

PiercingRoleCheckbox matches any element whose role attribute equals "checkbox" (case-insensitive). CF Turnstile and other ARIA-styled widgets often use a <div role=checkbox> instead of a real <input>.

func PiercingTagWithAttr

func PiercingTagWithAttr(tag, attr, value string) func(*PiercingNode) bool

PiercingTagWithAttr returns a predicate matching nodes whose NodeName equals tag (case-insensitive) AND whose attribute attr equals value (case-insensitive).

func RegisterFactory

func RegisterFactory(browser Browser, protocol Protocol, f comboFactory) error

func SupportedCombos

func SupportedCombos() []string

Types

type ActionChain

type ActionChain interface {
	Click(selector string, opts ...ClickOption) ActionChain
	DoubleClick(selector string, opts ...ClickOption) ActionChain
	RightClick(selector string, opts ...ClickOption) ActionChain
	MiddleClick(selector string, opts ...ClickOption) ActionChain
	Move(selector string) ActionChain
	Hover(selector string) ActionChain
	Type(selector string, text string, opts ...TypeOption) ActionChain
	Input(selector string, text string, opts ...TypeOption) ActionChain
	Press(selector string, key string, opts ...PressOption) ActionChain
	Combo(selector string, key string, opts ...PressOption) ActionChain
	KeyDown(selector string, key string) ActionChain
	KeyUp(selector string, key string) ActionChain
	Check(selector string) ActionChain
	Uncheck(selector string) ActionChain
	Select(selector string, values ...string) ActionChain
	DragTo(sourceSelector string, targetSelector string) ActionChain
	ScrollBy(dx float64, dy float64) ActionChain
	ScrollTo(selector string) ActionChain
	Humanize(minDelay time.Duration, maxDelay time.Duration) ActionChain
	Eval(js string, args ...any) ActionChain
	Wait(d time.Duration) ActionChain
	Run(ctx context.Context) error
	Len() int
	Reset() ActionChain
}

type AfterClickHook

type AfterClickHook func(selector string, err error)

type ArtifactsLevel

type ArtifactsLevel string
const (
	ArtifactsLevelAuto     ArtifactsLevel = ""
	ArtifactsLevelMeta     ArtifactsLevel = "meta"
	ArtifactsLevelMetaHTML ArtifactsLevel = "meta_html"
	ArtifactsLevelFull     ArtifactsLevel = "full"
)

func (ArtifactsLevel) IsValid

func (l ArtifactsLevel) IsValid() bool

func (ArtifactsLevel) String

func (l ArtifactsLevel) String() string

type BatchEval

type BatchEval interface {
	IsVisible(selector string) BatchEval
	Exists(selector string) BatchEval
	Text(selector string) BatchEval
	HTML(selector string) BatchEval
	Value(selector string) BatchEval
	Attribute(selector string, name string) BatchEval
	Run(ctx context.Context) (BatchEvalResult, error)
}

type BatchEvalItem

type BatchEvalItem struct {
	Operation BatchEvalOp
	Selector  string
	Name      string
	Bool      bool
	String    string
	Exists    bool
	Error     string
}

type BatchEvalOp

type BatchEvalOp string
const (
	BatchEvalOpIsVisible BatchEvalOp = "is_visible"
	BatchEvalOpExists    BatchEvalOp = "exists"
	BatchEvalOpText      BatchEvalOp = "text"
	BatchEvalOpHTML      BatchEvalOp = "html"
	BatchEvalOpValue     BatchEvalOp = "value"
	BatchEvalOpAttribute BatchEvalOp = "attribute"
)

type BatchEvalResult

type BatchEvalResult struct {
	Items []BatchEvalItem
}

func (BatchEvalResult) AttributeAt

func (r BatchEvalResult) AttributeAt(i int) (value string, exists bool, err error)

func (BatchEvalResult) BoolAt

func (r BatchEvalResult) BoolAt(i int) (bool, error)

func (BatchEvalResult) Item

func (r BatchEvalResult) Item(i int) (BatchEvalItem, error)

func (BatchEvalResult) Len

func (r BatchEvalResult) Len() int

func (BatchEvalResult) StringAt

func (r BatchEvalResult) StringAt(i int) (string, error)

type BeforeNavigateHook

type BeforeNavigateHook func(url string) error

type Browser

type Browser string
const (
	Chrome  Browser = "chrome"
	Edge    Browser = "edge"
	Firefox Browser = "firefox"
	Safari  Browser = "safari"
)

func ParseBrowser

func ParseBrowser(s string) (Browser, error)

func (Browser) IsValid

func (b Browser) IsValid() bool

func (Browser) String

func (b Browser) String() string

type BrowserPool

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

BrowserPool provides a fixed-size reusable pool of Engine instances.

Typical flow:

  1. Create with NewBrowserPool(...)
  2. lease, _ := pool.Acquire(ctx)
  3. use lease as a normal Engine
  4. defer lease.Release(ctx) (or defer lease.Close(ctx))
  5. pool.Close(ctx) on shutdown

Acquire blocks when all slots are in use; pass context timeout/cancel to bound wait time.

func MustNewBrowserPool

func MustNewBrowserPool(ctx context.Context, size int, opts ...BrowserPoolOption) *BrowserPool

func NewBrowserPool

func NewBrowserPool(ctx context.Context, size int, opts ...BrowserPoolOption) (*BrowserPool, error)

func (*BrowserPool) Acquire

func (p *BrowserPool) Acquire(ctx context.Context) (*PooledEngine, error)

func (*BrowserPool) Close

func (p *BrowserPool) Close(ctx context.Context) error

func (*BrowserPool) MustAcquire

func (p *BrowserPool) MustAcquire(ctx context.Context) *PooledEngine

func (*BrowserPool) Stats

func (p *BrowserPool) Stats() BrowserPoolStats

type BrowserPoolFactory

type BrowserPoolFactory func(ctx context.Context) (Engine, error)

BrowserPoolFactory creates one Engine instance for the pool.

The returned engine must be ready for immediate use. Factory calls are serialized per-slot, but multiple slots may initialize concurrently across goroutines calling Acquire.

type BrowserPoolHealthCheck

type BrowserPoolHealthCheck func(eng Engine) bool

BrowserPoolHealthCheck decides whether an engine can be reused.

Returning false (or panicking) marks the engine as unhealthy; the pool closes and recreates that slot on the next Acquire.

type BrowserPoolOption

type BrowserPoolOption func(*BrowserPoolOptions)

func WithBrowserPoolFactory

func WithBrowserPoolFactory(factory BrowserPoolFactory) BrowserPoolOption

WithBrowserPoolFactory sets a custom engine factory. When non-nil it takes precedence over WithBrowserPoolLaunchOptions.

func WithBrowserPoolHealthCheck

func WithBrowserPoolHealthCheck(check BrowserPoolHealthCheck) BrowserPoolOption

func WithBrowserPoolLaunchOptions

func WithBrowserPoolLaunchOptions(opts ...LaunchOption) BrowserPoolOption

WithBrowserPoolLaunchOptions configures Launch options used by pool slot creation when no custom Factory is set.

func WithBrowserPoolPrewarm

func WithBrowserPoolPrewarm(enabled bool) BrowserPoolOption

type BrowserPoolOptions

type BrowserPoolOptions struct {
	// Prewarm controls whether all slots are created during NewBrowserPool.
	// Default: true.
	Prewarm bool

	// LaunchOptions are used only when Factory is nil; the pool calls
	// Launch(ctx, LaunchOptions...) for each slot.
	LaunchOptions []LaunchOption

	// Factory overrides Launch-based creation. Useful for custom attach logic,
	// per-slot routing, or tests.
	Factory BrowserPoolFactory

	// HealthCheck decides whether a slot can be reused.
	// Nil => default check (!eng.Diagnostics().Closed).
	HealthCheck BrowserPoolHealthCheck
}

BrowserPoolOptions controls BrowserPool creation.

type BrowserPoolStats

type BrowserPoolStats struct {
	Size                int
	Idle                int
	InUse               int
	Waiters             int
	Closed              bool
	AcquireTotal        int64
	CreatedTotal        int64
	RecycledTotal       int64
	CreateFailuresTotal int64
	GeneratedAt         time.Time
}

BrowserPoolStats is a point-in-time snapshot of pool state.

type CDPBudgetStats

type CDPBudgetStats struct {
	// MethodCalls counts outgoing CDP calls by method name.
	MethodCalls map[string]uint64
	// DomainEnables counts "<Domain>.enable" calls by domain.
	DomainEnables map[string]uint64
	// Events counts inbound CDP events by event method name.
	Events map[string]uint64
	// InternalOps mirrors framework-issued bounded-context CDP ops
	// (rollback/domain-enable/route handler, etc).
	InternalOps map[string]InternalOpStats
	// BadListeners counts quarantined listeners by "method|session"
	// key. Helps spot user callbacks that repeatedly panic.
	BadListeners map[string]uint64
	// ListenerPanicsTotal is the cumulative panic count across all
	// listeners on the active transport.
	ListenerPanicsTotal int64
	// ListenerQuarantinesTotal is how many listeners were auto-removed
	// after crossing the panic threshold.
	ListenerQuarantinesTotal int64
}

CDPBudgetStats is a budget-friendly view over CDP transport telemetry. All counters are cumulative from adapter startup.

type CDPControlPath

type CDPControlPath string
const (
	CDPControlPathAuto           CDPControlPath = ""
	CDPControlPathBrowserSession CDPControlPath = "browser_session"
	CDPControlPathPageWSPrefer   CDPControlPath = "page_ws_prefer"
)

func (CDPControlPath) IsValid

func (p CDPControlPath) IsValid() bool

func (CDPControlPath) String

func (p CDPControlPath) String() string

type CDPReconnectStats

type CDPReconnectStats struct {
	// BrowserReconnectsTotal is the number of successful browser-ws
	// transport swaps performed by the supervisor.
	BrowserReconnectsTotal int64
	// BrowserReconnectFailures is the number of supervisor reconnect
	// loops that exhausted the downtime budget without recovering.
	BrowserReconnectFailures int64
	// BrowserGivenUp reflects whether the browser supervisor has
	// permanently abandoned reconnection. When true, all subsequent
	// cdpCall invocations fail fast with the give-up error.
	BrowserGivenUp bool

	// PageReconnectsTotal aggregates successful per-page reconnects
	// across every owned page-level supervisor (PageWSPrefer).
	PageReconnectsTotal int64
	// PageReconnectFailures aggregates per-page give-ups (a page
	// supervisor exhausted its downtime budget). The endpoint becomes
	// permanently dead until removed.
	PageReconnectFailures int64
	// PageSupervisorCount is the current number of live per-page
	// supervisors.
	PageSupervisorCount int
	// PageGivenUpTargets lists logical session ids whose page-level
	// supervisor is currently in give-up state.
	PageGivenUpTargets []string

	// CallRetryAttemptsTotal counts cdpCall invocations that hit a
	// transport-class error AND were eligible for transparent retry.
	CallRetryAttemptsTotal int64
	// CallRetrySkippedTotal counts cdpCall invocations that hit a
	// transport-class error but were NOT retried (mutating method
	// under CallRetryStrict mode).
	CallRetrySkippedTotal int64
}

CDPReconnectStats summarizes auto-reconnect activity for the CDP transport supervisors. All counters are cumulative across the adapter's lifetime.

Fields prefixed Browser* refer to the single browser-level reconnectSupervisor; Page* fields aggregate across all per-endpoint pageWSSupervisor instances. CallRetry* counts decisions made by callWithRetry under the configured CallRetryMode.

type CDPSessionKind

type CDPSessionKind string
const (
	CDPSessionKindUnknown          CDPSessionKind = ""
	CDPSessionKindPageAttached     CDPSessionKind = "page_attached"
	CDPSessionKindPageWebSocket    CDPSessionKind = "page_websocket"
	CDPSessionKindContextEphemeral CDPSessionKind = "context_ephemeral"
)

func (CDPSessionKind) IsValid

func (k CDPSessionKind) IsValid() bool

func (CDPSessionKind) String

func (k CDPSessionKind) String() string

type CDPTransportStats

type CDPTransportStats struct {
	// Connected reflects whether the transport is currently open.
	Connected bool
	// Uptime since the connection was established (or reconnected).
	Uptime time.Duration
	// ListenerCount is the number of active event listeners.
	ListenerCount int
	// PendingCallCount is the number of outstanding CDP requests awaiting
	// a response.
	PendingCallCount int
	// EventsDispatchedTotal counts events successfully handed to a
	// listener's inbox.
	EventsDispatchedTotal int64
	// EventDropsTotal counts events that could not be delivered because a
	// listener's inbox was full.
	EventDropsTotal int64
	// ListenerPanicsTotal counts recovered panics raised by listener
	// callbacks.
	ListenerPanicsTotal int64
	// ListenerQuarantinesTotal counts listeners auto-removed after
	// repeated panics.
	ListenerQuarantinesTotal int64
	// ReconnectOverflowTotal counts reconnect replay overflows where the
	// frozen event buffer hit its configured cap and started dropping
	// events.
	ReconnectOverflowTotal int64
	// CallsTotal counts outgoing CDP requests.
	CallsTotal int64
	// CallErrorsTotal counts CDP requests that returned an error or
	// timed out.
	CallErrorsTotal int64
	// PingsSent counts WebSocket ping frames emitted by the heartbeat
	// loop.
	PingsSent int64
	// PongsReceived counts WebSocket pong frames received.
	PongsReceived int64
	// WriteLatencyMax is the maximum observed WriteJSON latency.
	WriteLatencyMax time.Duration
	// WriteLatencySum is the cumulative WriteJSON latency; combined with
	// CallsTotal this yields an average.
	WriteLatencySum time.Duration
	// LastDisconnectAt records the most recent shutdown timestamp, if the
	// transport has ever been closed.
	LastDisconnectAt *time.Time
	// LastDisconnectReason mirrors the error that caused shutdown.
	LastDisconnectReason string

	// MethodCalls reports per-CDP-method invocation counts observed by
	// the active transport (for example: "Runtime.evaluate"=123).
	MethodCalls map[string]uint64
	// DomainEnables reports how many "*.enable" calls were sent per CDP
	// domain (for example: "Runtime"=3, "Fetch"=1).
	DomainEnables map[string]uint64
	// EventsFired reports inbound CDP event counts by event method name
	// (for example: "Network.requestWillBeSent"=456).
	EventsFired map[string]uint64
	// BadListeners reports quarantine counts keyed by
	// "method|session". Session may be empty for browser-scoped
	// subscriptions.
	BadListeners map[string]uint64

	// Reconnect aggregates auto-reconnect supervisor counters across
	// the browser-level transport and any owned page-level transports.
	// Nil for adapters that do not run a supervisor (Reconnect.Disabled
	// or stub adapters).
	Reconnect *CDPReconnectStats

	// InternalOps reports per-operation counters and latency summaries
	// for framework-issued CDP calls that do not inherit a caller
	// context (rollback, domain enable on event subscribe, route
	// handlers). Nil when no such calls have been made yet. The map
	// key is the op label passed to internalOpCtx (e.g.
	// "Domain.disable", "route.handler"). Use this to spot a wedged
	// browser that times out a particular subsystem under load.
	InternalOps map[string]InternalOpStats
}

CDPTransportStats captures observability counters for the CDP WebSocket transport. All counters are cumulative since the connection was established, except Connected/Uptime/PendingCallCount/ListenerCount which are point-in-time values.

type CallRetryMode

type CallRetryMode int

CallRetryMode classifies how aggressively callWithRetry replays CDP calls across a transport swap.

const (
	// CallRetryStrict (default) only auto-retries:
	//   - calls that never made it to the wire (write-phase failure)
	//   - calls whose method is in the built-in idempotency whitelist
	//     (see adapter_chrome_cdp_idempotency.go)
	// All other transport-class errors are surfaced to the caller.
	CallRetryStrict CallRetryMode = 0

	// CallRetryAll retries every transport-class error, regardless of
	// method semantics. Matches the pre-strict-mode behavior; useful
	// when callers wrap non-idempotent CDP usage in their own
	// at-most-once guard or accept the duplicate-fire risk.
	CallRetryAll CallRetryMode = 1
)

type Capabilities

type Capabilities struct {
	NativeActions     bool
	NetworkIntercept  bool
	EmulationUA       bool
	EmulationGeo      bool
	EmulationTimezone bool
	EmulationViewport bool
}

type CleanupPolicy

type CleanupPolicy string
const (
	CleanupPolicyAuto        CleanupPolicy = ""
	CleanupPolicyRemoveOwned CleanupPolicy = "remove_owned"
	CleanupPolicyPreserveAll CleanupPolicy = "preserve_all"
	CleanupPolicyRemoveAll   CleanupPolicy = "remove_all"
)

func (CleanupPolicy) IsValid

func (p CleanupPolicy) IsValid() bool

func (CleanupPolicy) String

func (p CleanupPolicy) String() string

type ClickOption

type ClickOption func(*ClickOptions)

func WithClickButton

func WithClickButton(btn MouseButton) ClickOption

func WithClickCount

func WithClickCount(n int) ClickOption

func WithClickDelay

func WithClickDelay(d time.Duration) ClickOption

func WithClickPosition

func WithClickPosition(x, y float64) ClickOption

func WithSkipActionability

func WithSkipActionability(skip bool) ClickOption

WithSkipActionability disables the pre-click actionability gate. Most callers should leave this alone — the default (false) guards against the flake patterns Playwright's auto-wait covers. Pass true only when you explicitly need the legacy "dispatch coordinates immediately, trust the caller" behaviour; see ClickOptions.SkipActionability for the full trade-off.

type ClickOptions

type ClickOptions struct {
	Button   MouseButton
	Count    int
	Delay    time.Duration
	Position *Point

	// SkipActionability bypasses the pre-click sanity checks
	// (connected / visible / stable rect / in-viewport /
	// hit-testable) and the post-resolve rebind loop. Default
	// (false) is the safer behaviour — we verify the element
	// is really clickable and re-sample its bounding box at
	// dispatch time so animations / reflows cannot make the
	// click fall through.
	//
	// Set to true in two narrow scenarios:
	//
	//   - You deliberately want to click an element that
	//     JS-level bot checks hide behind opacity:0 or a z-index
	//     overlay. The actionability gate would refuse; skipping
	//     it gets you the click, but the receiving handler may
	//     classify you as a bot.
	//   - You already ran your own actionability dance and a
	//     second round would be redundant latency.
	SkipActionability bool
}

type CloseAction

type CloseAction string
const (
	CloseActionNone     CloseAction = ""
	CloseActionClose    CloseAction = "close"
	CloseActionDetach   CloseAction = "detach"
	CloseActionShutdown CloseAction = "shutdown"
)

type CloseReport

type CloseReport struct {
	Action             CloseAction
	Mode               LaunchMode
	Managed            bool
	OwnsBrowser        bool
	CleanupPolicy      CleanupPolicy
	BrowserCloseSent   bool
	WebSocketClosed    bool
	ProcessExited      bool
	ProcessTreeKilled  bool
	UserDataDirRemoved bool
	DownloadDirRemoved bool
	StartedAt          time.Time
	FinishedAt         time.Time
}

type Config

type Config struct {
	Browser        Browser
	Protocol       Protocol
	Mode           LaunchMode
	CDPControlPath CDPControlPath

	Headless bool
	Binary   string
	Address  string
	Args     []string

	DownloadDir      string
	UserDataDir      string
	ProfileDirectory string
	Proxy            string

	DebugPort        int
	AutoPort         bool
	ExistingOnly     bool
	KeepBrowserAlive bool
	KeepUserDataDir  bool
	Leakless         bool
	SignalHandling   SignalHandlingMode

	DiagnosticsEnabled bool
	ArtifactsEnabled   bool
	ArtifactsDir       string
	ArtifactsLevel     ArtifactsLevel
	CleanupPolicy      CleanupPolicy
	RetryPolicy        RetryPolicy

	// HistoryLimits caps in-memory retention for trace and per-page
	// buffers. Leave fields at zero to use defaults.
	HistoryLimits HistoryLimits

	// LaunchArgsPolicy controls how go-bot composes the browser command
	// line in LaunchManaged mode. Leave empty for the default managed
	// policy; set to LaunchArgsPolicyPassthrough when driving a
	// fingerprint-chromium style build whose command line must not be
	// touched by the framework.
	LaunchArgsPolicy LaunchArgsPolicy

	// RemoteAllowOrigins overrides the list of origins allowed to
	// connect to the CDP websocket (Chromium's --remote-allow-origins
	// switch). Applies only in LaunchManaged mode.
	//
	// Default (nil / empty): the framework injects a scoped
	// "http://localhost:<port>" — the minimum needed for go-bot's own
	// transport to attach, with no extra origins exposed. This matters
	// because "--remote-allow-origins=*" is a widely-tracked fingerprint
	// signal used by bot-detection products.
	//
	// Pass []string{"*"} to opt back into the permissive behaviour
	// (e.g. attaching from a remote chrome-devtools-frontend), or pass
	// a specific allowlist such as []string{"http://localhost:9222",
	// "devtools://devtools"} for tight control.
	//
	// Ignored under LaunchArgsPolicyPassthrough — the caller's Args are
	// authoritative there.
	RemoteAllowOrigins []string

	// ExtensionsEnabled controls whether Chromium's built-in component
	// extensions (DevTools companion bits, Chrome-internal background
	// helpers) and any user-profile extensions are allowed to load.
	//
	// Default (false): the framework injects --disable-extensions and
	// --disable-component-extensions-with-background-pages. Each
	// loaded extension injects observable JS surfaces that bot-detection
	// products fingerprint; disabling by default gives a cleaner baseline.
	//
	// Set to true if you need extensions (testing a Chrome extension,
	// driving a user profile that depends on its extensions, etc.).
	//
	// Ignored under LaunchArgsPolicyPassthrough.
	ExtensionsEnabled bool

	// Reconnect controls automatic recovery when the CDP transport drops
	// (network blip, browser flush, OS pause). Leave at zero values to
	// use the framework default (auto-reconnect with exponential backoff).
	Reconnect ReconnectPolicy

	// CDPRecordPath enables NDJSON recording of outgoing CDP calls.
	// Applies only when Protocol=CDP. The file is opened in append mode.
	//
	// Each call emits one line with timestamp, method, session, duration
	// and optional error text. This is useful for footprint budgeting and
	// regression baselines in fingerprint-browser workflows.
	CDPRecordPath string

	// CDPDryRun, when true, records CDP calls but does not send them to
	// the browser transport. This mode still validates/wires the engine,
	// but all protocol calls become no-op records and any response output
	// objects are left at their zero values.
	//
	// Requires CDPRecordPath to be non-empty.
	CDPDryRun bool

	// Logger receives structured events from the engine, adapters and the
	// underlying transport. When nil the framework emits no logs.
	// Callers are expected to supply a project-wide slog.Logger.
	Logger *slog.Logger

	// CDPMethodRateLimits applies per-method rate limiting (requests per
	// second) to outgoing CDP calls. It is currently used by the Chrome
	// CDP adapter and intended to protect high-QPS loops
	// (Input.dispatch* floods) from overwhelming the transport.
	//
	// Nil: use framework defaults for known-hot methods.
	// Empty map: disable all method limits.
	// Value <= 0: disable limit for that specific method key.
	CDPMethodRateLimits map[string]int

	// ListenerPanicThreshold controls the CDP event listener circuit
	// breaker. When a listener callback panics this many times
	// consecutively, go-bot automatically quarantines (unsubscribes) that
	// listener to prevent runaway panic loops.
	//
	// 0: use default (5)
	// <0: disable auto-quarantine
	ListenerPanicThreshold int
	// contains filtered or unexported fields
}

func (Config) Validate

func (c Config) Validate() error

type ConsoleMessage

type ConsoleMessage struct {
	Type string
	Text string
	Args []any
}

type Context

type Context interface {
	ID() string
	NewPage(ctx context.Context, opts ...PageOption) (Page, error)
	NewTab(ctx context.Context, opts ...PageOption) (Page, error)
	Pages() []Page
	Tabs() []Page
	Tab(id string) (Page, bool)
	ActivateTab(ctx context.Context, id string) error
	CloseOtherTabs(ctx context.Context, keepID string) error
	FindTabByTitle(ctx context.Context, keyword string) (Page, bool)
	FindTabByURL(ctx context.Context, keyword string) (Page, bool)
	Cookies(ctx context.Context) ([]Cookie, error)
	SetCookies(ctx context.Context, cookies ...CookieInput) error
	DeleteCookies(ctx context.Context, selectors ...CookieSelector) error
	ClearCookies(ctx context.Context) error
	Close(ctx context.Context) error
}

type ContextOption

type ContextOption func(*ContextOptions)

func WithContextEnv

func WithContextEnv(env EnvProfile) ContextOption

func WithContextName

func WithContextName(name string) ContextOption

type ContextOptions

type ContextOptions struct {
	Name string
	Env  *EnvProfile
}

type ContinueOption

type ContinueOption func(*ContinueOptions)

func WithContinueHeaders

func WithContinueHeaders(headers http.Header) ContinueOption

func WithContinueMethod

func WithContinueMethod(method string) ContinueOption

func WithContinuePostData

func WithContinuePostData(body []byte) ContinueOption

func WithContinueURL

func WithContinueURL(url string) ContinueOption

type ContinueOptions

type ContinueOptions struct {
	URL      string
	Method   string
	Headers  http.Header
	PostData []byte
}
type Cookie struct {
	Name     string
	Value    string
	Domain   string
	Path     string
	Expires  float64
	HTTPOnly bool
	Secure   bool
	SameSite string
}

type CookieCleanupPreset

type CookieCleanupPreset string
const (
	CookieCleanupPresetOneTrust      CookieCleanupPreset = "onetrust"
	CookieCleanupPresetCookiebot     CookieCleanupPreset = "cookiebot"
	CookieCleanupPresetCommonConsent CookieCleanupPreset = "common-consent"
)

type CookieInput

type CookieInput struct {
	Name     string
	Value    string
	URL      string
	Domain   string
	Path     string
	Expires  *float64
	HTTPOnly bool
	Secure   bool
	SameSite string
}

type CookieSelector

type CookieSelector struct {
	Name   string
	URL    string
	Domain string
	Path   string
}

func CookieCleanupSelectors

func CookieCleanupSelectors(preset CookieCleanupPreset, rawURL string) ([]CookieSelector, error)

type DialogEvent

type DialogEvent struct {
	Type          string
	Message       string
	DefaultPrompt string
	Accept        func(ctx context.Context, promptText ...string) error
	Dismiss       func(ctx context.Context) error
}

type DownloadEvent

type DownloadEvent struct {
	GUID              string
	URL               string
	SuggestedFilename string
	State             string
	TotalBytes        float64
	ReceivedBytes     float64
	FilePath          string
	Cancel            func(ctx context.Context) error
}

type DownloadManager

type DownloadManager interface {
	// Context convention:
	//   - methods that call CDP / block / do IO take context.Context
	//   - pure in-memory snapshots do not take context.Context
	SetPath(ctx context.Context, path string) error
	Wait(ctx context.Context, timeout time.Duration) (DownloadEvent, error)
	WaitState(ctx context.Context, state string, timeout time.Duration) (DownloadEvent, error)
	Verify(ctx context.Context, ev DownloadEvent) error
	Events() []DownloadEvent
	Clear()
	Close(ctx context.Context) error
}

type Element

type Element interface {
	Selector() string
	Page() Page
	Waiter() ElementWaiter
	WithShadow(path ...string) Element
	ShadowRoot(selector string) Element
	Parent() Element
	Child(selector string) Element
	Within(selector string) Element
	Nth(index int) Element
	First() Element
	Last() Element

	Hover(ctx context.Context) error
	Text(ctx context.Context) (string, error)
	HTML(ctx context.Context) (string, error)
	Attribute(ctx context.Context, name string) (string, bool, error)
	Value(ctx context.Context) (string, error)
	Exists(ctx context.Context) (bool, error)
	IsVisible(ctx context.Context) (bool, error)
	IsEnabled(ctx context.Context) (bool, error)
	IsChecked(ctx context.Context) (bool, error)
	IsEditable(ctx context.Context) (bool, error)
	BoundingBox(ctx context.Context) (Rect, error)
	IsInViewport(ctx context.Context) (bool, error)
	HasAttribute(ctx context.Context, name string) (bool, error)
	WaitVisible(ctx context.Context, timeout time.Duration) error
	WaitHidden(ctx context.Context, timeout time.Duration) error
	Check(ctx context.Context) error
	Uncheck(ctx context.Context) error
	Select(ctx context.Context, values ...string) error
	Click(ctx context.Context, opts ...ClickOption) error
	Type(ctx context.Context, text string, opts ...TypeOption) error
	Input(ctx context.Context, text string, opts ...TypeOption) error
	Press(ctx context.Context, key string, opts ...PressOption) error
	SetInputFiles(ctx context.Context, paths ...string) error
	Screenshot(ctx context.Context, opts ...ScreenshotOption) ([]byte, error)
}

type ElementWaiter

type ElementWaiter interface {
	Visible(ctx context.Context, timeout time.Duration) error
	Hidden(ctx context.Context, timeout time.Duration) error
	Exists(ctx context.Context, timeout time.Duration) error

	// Builder-style sugar mirroring PageWaiter task helpers.
	VisibleTask() WaitTask
	HiddenTask() WaitTask
	ExistsTask() WaitTask
}

type EmulatedColorScheme

type EmulatedColorScheme string
const (
	EmulatedColorSchemeUnset        EmulatedColorScheme = ""
	EmulatedColorSchemeLight        EmulatedColorScheme = "light"
	EmulatedColorSchemeDark         EmulatedColorScheme = "dark"
	EmulatedColorSchemeNoPreference EmulatedColorScheme = "no-preference"
)

type EmulatedForcedColors

type EmulatedForcedColors string
const (
	EmulatedForcedColorsUnset  EmulatedForcedColors = ""
	EmulatedForcedColorsNone   EmulatedForcedColors = "none"
	EmulatedForcedColorsActive EmulatedForcedColors = "active"
)

type EmulatedReducedMotion

type EmulatedReducedMotion string
const (
	EmulatedReducedMotionUnset        EmulatedReducedMotion = ""
	EmulatedReducedMotionReduce       EmulatedReducedMotion = "reduce"
	EmulatedReducedMotionNoPreference EmulatedReducedMotion = "no-preference"
)

type EmulationManager

type EmulationManager interface {
	// Context convention:
	//   - methods that call CDP / block / do IO take context.Context
	//   - pure in-memory snapshots do not take context.Context
	Apply(ctx context.Context, profile EnvProfile) error
	UserAgent(ctx context.Context, userAgent string) error
	Locale(ctx context.Context, locale string) error
	Timezone(ctx context.Context, timezoneID string) error
	Viewport(ctx context.Context, width int, height int) error
	Geolocation(ctx context.Context, lat float64, lon float64, accuracy float64) error
	ColorScheme(ctx context.Context, scheme EmulatedColorScheme) error
	ReducedMotion(ctx context.Context, motion EmulatedReducedMotion) error
	ForcedColors(ctx context.Context, forcedColors EmulatedForcedColors) error
	HardwareConcurrency(ctx context.Context, concurrency int) error
	MobilePresets() []MobilePreset
	UseMobilePreset(ctx context.Context, name string) error
	Profile() EnvProfile
	Close(ctx context.Context) error
}

type Engine

type Engine interface {
	Meta() Meta
	Caps() Capabilities
	Ownership() EngineOwnership
	LastCloseReport() CloseReport
	Diagnostics() EngineDiagnostics
	Monitor(limit int) MonitorSnapshot
	ServeMonitor(addr string) (MonitorServer, error)
	ServeMonitorWithOptions(addr string, opts ...MonitorServeOption) (MonitorServer, error)
	NewContext(ctx context.Context, opts ...ContextOption) (Context, error)
	OnPageCreated(fn PageCreatedHook) (Subscription, error)
	OnTrace(fn func(TraceEvent)) (Subscription, error)
	TraceToFile(path string) (Subscription, error)
	TraceToRollingFile(path string, opts ...TraceFileOption) (Subscription, error)
	OnEvent(method string, fn func(ProtocolEvent)) (Subscription, error)
	EachEvent(fn func(ProtocolEvent), methods ...string) (Subscription, error)
	WaitEvent(ctx context.Context, method string, timeout time.Duration) (ProtocolEvent, error)
	Close(ctx context.Context) error
	Detach(ctx context.Context) error
	Shutdown(ctx context.Context) error

	// Reconnect attempts a user-initiated transport reconnection. Use
	// this to recover after the auto-reconnect supervisor has given up
	// (Diagnostics().Transport.Reconnect.BrowserGivenUp == true), for
	// example because the browser was paused longer than MaxDowntime.
	//
	// On success the transport, every subscription and every replayable
	// CDP domain are re-established and BrowserGivenUp returns to false.
	// On failure the engine remains in the given-up state and the error
	// is returned for inspection.
	//
	// Reconnect returns ErrNotImplemented for adapters whose underlying
	// transport does not (yet) support recovery (e.g. BiDi or stub).
	// It is a no-op (returning nil) when the transport is already
	// healthy and no give-up flag is set.
	Reconnect(ctx context.Context) error

	// ReconnectTarget attempts a user-initiated reconnect for one logical
	// target. This is useful when one page/session has failed while the
	// rest of the engine remains healthy.
	//
	// On PageWSPrefer endpoints this re-dials that page websocket.
	// On browser-session endpoints this re-attaches that target and
	// replays only that session's subscriptions/domains.
	//
	// targetID accepts:
	//   - page id (Page.ID())
	//   - Chrome target id
	//   - logical session id
	//   - "browser" (alias for Reconnect)
	//
	// Returns ErrNotImplemented for adapters that do not support
	// target-scoped reconnect.
	ReconnectTarget(ctx context.Context, targetID string) error
}

func Attach

func Attach(ctx context.Context, address string, opts ...LaunchOption) (Engine, error)

func Launch

func Launch(ctx context.Context, opts ...LaunchOption) (Engine, error)

func LaunchOrAttach

func LaunchOrAttach(ctx context.Context, opts ...LaunchOption) (Engine, error)

func LaunchPersistent

func LaunchPersistent(ctx context.Context, userDataDir string, opts ...LaunchOption) (Engine, error)

func MustAttach

func MustAttach(ctx context.Context, address string, opts ...LaunchOption) Engine

func MustLaunch

func MustLaunch(ctx context.Context, opts ...LaunchOption) Engine

func MustLaunchOrAttach

func MustLaunchOrAttach(ctx context.Context, opts ...LaunchOption) Engine

func MustLaunchPersistent

func MustLaunchPersistent(ctx context.Context, userDataDir string, opts ...LaunchOption) Engine

func MustNew

func MustNew(ctx context.Context, cfg Config) Engine

func New

func New(ctx context.Context, cfg Config) (Engine, error)

type EngineDiagnostics

type EngineDiagnostics struct {
	Meta               Meta
	Caps               Capabilities
	Ownership          EngineOwnership
	LastCloseReport    CloseReport
	DiagnosticsEnabled bool
	ArtifactsEnabled   bool
	ArtifactsDir       string
	ArtifactsLevel     ArtifactsLevel
	CleanupPolicy      CleanupPolicy
	CDPControlPath     CDPControlPath
	LastArtifactOp     string
	LastArtifactError  string
	LastArtifactDir    string
	LastArtifactFiles  []string
	LastArtifactAt     time.Time
	Pages              []PageDiagnostics
	Closed             bool
	ContextCount       int
	PageCount          int
	// Transport carries low-level CDP/WebSocket counters when the active
	// adapter supports it. Nil for adapters that don't expose transport
	// telemetry (e.g. stub adapter in tests).
	Transport *CDPTransportStats
	// CDP is a budget-oriented projection of the transport counters:
	// per-method calls, per-domain enables, per-event counts and
	// internal framework op stats. Nil when transport telemetry is
	// unavailable (non-CDP adapters / pre-connect states).
	CDP         *CDPBudgetStats
	GeneratedAt time.Time
}

type EngineOwnership

type EngineOwnership struct {
	Mode             LaunchMode
	CDPControlPath   CDPControlPath
	OwnsBrowser      bool
	Managed          bool
	KeepBrowserAlive bool
	KeepUserDataDir  bool
	CleanupPolicy    CleanupPolicy
	DebugAddress     string
	UserDataDir      string
}

type EnvProfile

type EnvProfile struct {
	UserAgent           string
	Locale              string
	TimezoneID          string
	Geolocation         *Geolocation
	Viewport            *Viewport
	DeviceScaleFactor   float64
	TouchEnabled        bool
	ColorScheme         EmulatedColorScheme
	ReducedMotion       EmulatedReducedMotion
	ForcedColors        EmulatedForcedColors
	HardwareConcurrency int
}

EnvProfile is a runtime "environment override" applied via CDP (Network.setUserAgentOverride + Emulation.setTimezoneOverride / setGeolocationOverride / setDeviceMetricsOverride / setTouchEmulationEnabled / setLocaleOverride / setEmulatedMedia / setHardwareConcurrencyOverride).

Intended audience: vanilla Chrome / Edge / Chromium. EnvProfile only covers a handful of dimensions (UA, language, timezone, viewport, touch, geolocation, media preferences, hardwareConcurrency) and never attempts a holistic, internally- consistent identity rewrite — for that you want a fingerprint-browser build whose Persona is baked in at the C++ layer.

IMPORTANT — do NOT use EnvProfile.UserAgent / Locale / TimezoneID / Viewport / DeviceScaleFactor / TouchEnabled / ColorScheme / ReducedMotion / ForcedColors / HardwareConcurrency when driving a fingerprint browser. The Persona already controls these (and a few dozen other dimensions go-bot has no CDP for: navigator.platform, userAgentData, hardwareConcurrency, WebGL renderer, AudioContext hash, fonts, WebRTC, ...). Layering a CDP override on top will silently break Persona consistency and produce a fingerprint that is easier to detect than either layer alone. Geolocation is the one field a Persona generally leaves alone, so overriding it from EnvProfile is safe.

type ExposedFunction

type ExposedFunction func(ctx context.Context, args ...any) (any, error)

type FileDialogEvent

type FileDialogEvent struct {
	Mode      string
	SetFiles  func(ctx context.Context, paths ...string) error
	Accept    func(ctx context.Context, paths ...string) error
	Dismiss   func(ctx context.Context) error
	PageID    string
	FrameID   string
	BackendID int
}

type FingerprintAudioOption

type FingerprintAudioOption func(*fingerprintAudioConfig)

FingerprintAudioOption customizes LaunchWithFingerprintAudio. When omitted, noise defaults to conservative and context defaults to a realistic 48kHz desktop AudioContext surface.

func WithFingerprintAudioContext

func WithFingerprintAudioContext(contextJSON string) FingerprintAudioOption

func WithFingerprintAudioNoise

func WithFingerprintAudioNoise(noise string) FingerprintAudioOption

type FingerprintMode

type FingerprintMode = fingerprint.Mode

FingerprintMode controls whether a signal is left native, kept stable per browser profile, or randomized for every browser launch.

type FingerprintWebRTCMode

type FingerprintWebRTCMode = fingerprint.WebRTCMode

FingerprintWebRTCMode maps to the fingerprint browser's WebRTC policy.

type Frame

type Frame interface {
	Selector() string
	Page() Page
	Ele(selector string) Element
	WithFrame(path ...string) Frame
	WithShadow(path ...string) Element
}

type FulfillResponse

type FulfillResponse struct {
	Status  int
	Headers http.Header
	Body    []byte

	// BodyRewrite rewrites an upstream response body. It is only valid
	// on Fetch response-stage pauses. When set, go-bot reads the paused
	// upstream body (Fetch.getResponseBody), passes it to this callback,
	// then fulfills with the returned bytes.
	//
	// If Body is also set, BodyRewrite is ignored and Body is used as-is.
	BodyRewrite func(original []byte) []byte
}

type Geolocation

type Geolocation struct {
	Lat      float64
	Lon      float64
	Accuracy float64
}

type GotoOption

type GotoOption func(*GotoOptions)

func WithGotoTimeout

func WithGotoTimeout(d time.Duration) GotoOption

func WithPageGotoTimeout

func WithPageGotoTimeout(d time.Duration) GotoOption

WithPageGotoTimeout is an alias of WithGotoTimeout for callers that prefer the Page-prefixed naming style.

func WithPageWaitUntil

func WithPageWaitUntil(state LoadState) GotoOption

WithPageWaitUntil is an alias of WithWaitUntil for naming symmetry.

func WithWaitUntil

func WithWaitUntil(state LoadState) GotoOption

type GotoOptions

type GotoOptions struct {
	Timeout   time.Duration
	WaitUntil LoadState
}

type HistoryLimits

type HistoryLimits struct {
	// TraceRecent caps engine-level TraceEvent entries retained in
	// memory (used by Engine.Monitor, monitor HTTP endpoints, and
	// close-report artifact snapshots). Default: 512.
	TraceRecent int
	// Network caps requests/responses/packets/transactions retained by
	// NetworkManager. Default: 4096.
	Network int
	// ArtifactRecent caps the per-page console and network artifact
	// records retained for failure capture. Default: 64.
	ArtifactRecent int
	// Downloads caps DownloadEvent records retained by
	// DownloadManager. Default: 1024.
	//
	// The limit applies to the per-page events() history only;
	// the underlying adapter-level download GUID index is
	// trimmed separately by the adapter's own timestamped GC
	// (see adapter_chrome_cdp_events.go).
	Downloads int
	// Navigation caps NavigationEvent records retained by
	// NavigationManager. Default: 512.
	Navigation int
	// Intercept caps InterceptEvent records retained by
	// InterceptManager. Default: 4096.
	Intercept int
}

HistoryLimits configures the upper bound of in-memory retention for per-page buffers. All values are "most-recent-N"; entries exceeding the limit are dropped oldest-first.

Any field set to zero falls back to the framework default; set to a negative value to disable that buffer entirely.

type IndexedDBDatabase

type IndexedDBDatabase struct {
	Name string
}

type IndexedDBRecord

type IndexedDBRecord struct {
	Key        any
	PrimaryKey any
	Value      any
}

type IndexedDBScope

type IndexedDBScope interface {
	Databases(ctx context.Context) ([]IndexedDBDatabase, error)
	Read(ctx context.Context, database string, objectStore string) ([]IndexedDBRecord, error)
	Clear(ctx context.Context, database string, objectStore string) error
}

type InterceptEvent

type InterceptEvent struct {
	Phase    InterceptPhase
	Request  RequestEvent
	Response *ResponseEvent
	Time     time.Time
}

type InterceptFilter

type InterceptFilter struct {
	Methods       []string
	ResourceTypes []string
	Statuses      []int
	StatusMin     int
	StatusMax     int
}

type InterceptHandler

type InterceptHandler func(ctx context.Context, req InterceptedRequest) error

type InterceptManager

type InterceptManager interface {
	// Context convention:
	//   - methods that call CDP / block / do IO take context.Context
	//   - pure in-memory snapshots do not take context.Context
	Start(pattern string, handler InterceptHandler, opts ...InterceptOption) error
	Stop() error
	Active() bool
	Wait(ctx context.Context, timeout time.Duration) (InterceptEvent, error)
	Events() []InterceptEvent
	Clear()
	Close(ctx context.Context) error
}

type InterceptOption

type InterceptOption func(*InterceptOptions)

func WithInterceptFilter

func WithInterceptFilter(filter InterceptFilter) InterceptOption

func WithInterceptMethods

func WithInterceptMethods(methods ...string) InterceptOption

func WithInterceptPhases

func WithInterceptPhases(phases ...InterceptPhase) InterceptOption

func WithInterceptResourceTypes

func WithInterceptResourceTypes(resourceTypes ...string) InterceptOption

func WithInterceptStatusRange

func WithInterceptStatusRange(min, max int) InterceptOption

func WithInterceptStatuses

func WithInterceptStatuses(statuses ...int) InterceptOption

type InterceptOptions

type InterceptOptions struct {
	Phases []InterceptPhase
	Filter InterceptFilter
}

type InterceptPhase

type InterceptPhase string
const (
	InterceptBeforeRequest InterceptPhase = "beforeRequestSent"
	InterceptResponse      InterceptPhase = "responseStarted"
)

type InterceptedRequest

type InterceptedRequest interface {
	Event() InterceptEvent
	Continue(ctx context.Context, opts ...ContinueOption) error
	Abort(ctx context.Context, reason string) error
	Fail(ctx context.Context, reason string) error
	Fulfill(ctx context.Context, resp FulfillResponse) error
	Mock(ctx context.Context, body []byte, status int, headers http.Header) error
}

type InternalOpStats

type InternalOpStats struct {
	Op            string
	Count         int64
	Timeouts      int64
	LatencyMax    time.Duration
	LatencySum    time.Duration
	LatencyP99    time.Duration
	LastSampledAt time.Time
}

InternalOpStats captures per-op telemetry for framework-issued CDP calls that run on a bounded internal context (rollbacks, domain enable on subscribe, fetch auto-continue, route handlers).

Latency fields cover the full lifetime of the bounded context, from internalOpCtx allocation to its cancel. A "timeout" is recorded when the context's deadline elapses BEFORE the caller cancels (i.e. the bounded budget was insufficient); other terminations count as successes. P99 is approximated from a per-op ring buffer of recent samples (best-effort observability, not exact stats).

type LaunchArgsPolicy

type LaunchArgsPolicy string

LaunchArgsPolicy controls how go-bot composes the Chromium/Edge command line in LaunchManaged mode. It has no effect when attaching to an existing browser via Address.

const (
	// LaunchArgsPolicyManaged (the default, empty string) asks go-bot to
	// inject a curated set of automation-friendly flags
	// (--remote-debugging-port, --user-data-dir, --no-first-run,
	// --disable-background-networking, ...) and append Config.Args after
	// them. This is the safest policy for plain Chrome/Chromium.
	LaunchArgsPolicyManaged LaunchArgsPolicy = ""

	// LaunchArgsPolicyPassthrough tells go-bot to launch the browser with
	// ONLY --remote-debugging-port=<port> plus Config.Args. Nothing else
	// is injected — no --user-data-dir, no headless flag, no baseline
	// disables. The caller is fully responsible for every other argument.
	//
	// This is intended for fingerprint-browser style custom Chromium
	// builds that set up their own profile directory and need full
	// control over the command line. Callers using this policy must
	// supply their own --user-data-dir in Config.Args (or accept the
	// browser's default), because go-bot will not create a temp dir.
	LaunchArgsPolicyPassthrough LaunchArgsPolicy = "passthrough"
)

func (LaunchArgsPolicy) IsValid

func (p LaunchArgsPolicy) IsValid() bool

IsValid reports whether p is a recognised launch-args policy.

type LaunchMode

type LaunchMode string
const (
	LaunchModeAuto  LaunchMode = ""
	LaunchManaged   LaunchMode = "launch_managed"
	AttachUnmanaged LaunchMode = "attach_unmanaged"
	AttachManaged   LaunchMode = "attach_managed"
)

func (LaunchMode) IsValid

func (m LaunchMode) IsValid() bool

func (LaunchMode) String

func (m LaunchMode) String() string

type LaunchOption

type LaunchOption func(*Config)

func LaunchWithAddress

func LaunchWithAddress(address string) LaunchOption

func LaunchWithArgs

func LaunchWithArgs(args ...string) LaunchOption

func LaunchWithArtifacts

func LaunchWithArtifacts(enabled bool) LaunchOption

func LaunchWithArtifactsDir

func LaunchWithArtifactsDir(dir string) LaunchOption

func LaunchWithArtifactsLevel

func LaunchWithArtifactsLevel(level ArtifactsLevel) LaunchOption

func LaunchWithAutoPort

func LaunchWithAutoPort(enabled bool) LaunchOption

func LaunchWithBinary

func LaunchWithBinary(binary string) LaunchOption

func LaunchWithBrowser

func LaunchWithBrowser(browser Browser) LaunchOption

func LaunchWithCDPControlPath

func LaunchWithCDPControlPath(path CDPControlPath) LaunchOption

func LaunchWithCDPMethodRateLimit

func LaunchWithCDPMethodRateLimit(method string, qps int) LaunchOption

LaunchWithCDPMethodRateLimit sets a single CDP method rate limit (requests per second) on top of any existing map on Config.

func LaunchWithCDPMethodRateLimits

func LaunchWithCDPMethodRateLimits(limits map[string]int) LaunchOption

LaunchWithCDPMethodRateLimits sets per-method CDP call rate limits (requests per second). Nil restores framework defaults; empty map disables all method limits.

func LaunchWithCDPRecord

func LaunchWithCDPRecord(path string) LaunchOption

LaunchWithCDPRecord enables NDJSON recording of outgoing CDP calls. The file is opened in append mode.

func LaunchWithCleanupPolicy

func LaunchWithCleanupPolicy(policy CleanupPolicy) LaunchOption

func LaunchWithDebugPort

func LaunchWithDebugPort(port int) LaunchOption

func LaunchWithDiagnostics

func LaunchWithDiagnostics(enabled bool) LaunchOption

func LaunchWithDownloadDir

func LaunchWithDownloadDir(dir string) LaunchOption

func LaunchWithDryRun

func LaunchWithDryRun(path string) LaunchOption

LaunchWithDryRun enables CDP dry-run mode: calls are recorded but not sent to the browser transport. If path is non-empty it also sets CDPRecordPath; otherwise any previously configured record path is kept.

Dry-run requires a non-empty record path (validated by Config.Validate).

func LaunchWithExistingOnly

func LaunchWithExistingOnly(existingOnly bool) LaunchOption

func LaunchWithExtensions

func LaunchWithExtensions(enabled bool) LaunchOption

LaunchWithExtensions toggles whether Chromium component / user extensions are allowed to load. Default is false — the framework injects --disable-extensions (quieter fingerprint baseline). Call with true when you need extensions (e.g. extension development, password-manager-backed profiles).

Has no effect in LaunchArgsPolicyPassthrough.

func LaunchWithFingerprintAudio

func LaunchWithFingerprintAudio(mode FingerprintMode, opts ...FingerprintAudioOption) LaunchOption

LaunchWithFingerprintAudio controls audio seed handling. Defaults for noise and context are applied in fixed/random modes unless overridden by opts.

func LaunchWithFingerprintCPU

func LaunchWithFingerprintCPU(cores int) LaunchOption

LaunchWithFingerprintCPU sets navigator.hardwareConcurrency via the fingerprint browser switch.

func LaunchWithFingerprintCanvas

func LaunchWithFingerprintCanvas(mode FingerprintMode) LaunchOption

LaunchWithFingerprintCanvas controls canvas seed handling.

  • system: no canvas seed switch is passed
  • fixed: stable per user-data-dir, persisted in go-bot seed cache
  • random: fresh seed per launch, not persisted

func LaunchWithFingerprintDisplay

func LaunchWithFingerprintDisplay(width, height int) LaunchOption

LaunchWithFingerprintDisplay sets the screen size and derives a plausible desktop viewport/outer/available geometry from it. Use raw --fingerprint-* switches for uncommon layouts that require exact control.

func LaunchWithFingerprintLanguage

func LaunchWithFingerprintLanguage(language string, languages []string, acceptLanguage string) LaunchOption

LaunchWithFingerprintLanguage sets navigator.language, navigator.languages and Accept-Language independently. Empty values are not passed.

func LaunchWithFingerprintMemory

func LaunchWithFingerprintMemory(gb int) LaunchOption

LaunchWithFingerprintMemory sets navigator.deviceMemory via the fingerprint browser switch. Chromium normally exposes bucketed values; prefer 1/2/4/8.

func LaunchWithFingerprintTimezone

func LaunchWithFingerprintTimezone(timezone string) LaunchOption

LaunchWithFingerprintTimezone sets a fixed browser timezone. Empty timezone removes the fixed timezone switches from the generated command line.

func LaunchWithFingerprintUILocale

func LaunchWithFingerprintUILocale(uiLocale string) LaunchOption

LaunchWithFingerprintUILocale sets Chrome's UI locale surfaces. Empty value removes the UI locale switch from the generated command line.

func LaunchWithFingerprintWebRTC

func LaunchWithFingerprintWebRTC(mode FingerprintWebRTCMode, publicIP string) LaunchOption

LaunchWithFingerprintWebRTC sets the browser-level WebRTC leak policy. In replace mode publicIP must be non-empty and should match the proxy exit IP.

func LaunchWithHeadless

func LaunchWithHeadless(headless bool) LaunchOption

func LaunchWithHistoryLimits

func LaunchWithHistoryLimits(limits HistoryLimits) LaunchOption

LaunchWithHistoryLimits caps in-memory retention for engine trace and per-page buffers (network/download/navigation/intercept/artifacts). Leave individual fields at zero to use the framework defaults; pass a negative value to disable a particular buffer.

func LaunchWithKeepBrowserAlive

func LaunchWithKeepBrowserAlive(keep bool) LaunchOption

func LaunchWithKeepUserDataDir

func LaunchWithKeepUserDataDir(keep bool) LaunchOption

func LaunchWithLaunchArgsPolicy

func LaunchWithLaunchArgsPolicy(policy LaunchArgsPolicy) LaunchOption

LaunchWithLaunchArgsPolicy controls how go-bot composes the browser command line in LaunchManaged mode.

  • LaunchArgsPolicyManaged (default, ""): the framework prepends its standard Chromium switches and validates user-supplied Args against the managed-only switch list (rejecting e.g. --remote-debugging-port).
  • LaunchArgsPolicyPassthrough: the framework treats Config.Args as authoritative and does not prepend / mutate them. Use this when driving a fingerprint-chromium build whose command line must not be touched.

func LaunchWithLeakless

func LaunchWithLeakless(enabled bool) LaunchOption

func LaunchWithListenerPanicThreshold

func LaunchWithListenerPanicThreshold(threshold int) LaunchOption

LaunchWithListenerPanicThreshold configures the CDP listener circuit-breaker threshold.

  • 0: use framework default (5)
  • <0: disable auto-quarantine
  • >0: quarantine after N consecutive panics

func LaunchWithLogger

func LaunchWithLogger(logger *slog.Logger) LaunchOption

LaunchWithLogger installs a structured logger. The framework calls logger.With/InfoContext/WarnContext/ErrorContext from supervisors, adapters and the underlying transport. Pass nil (the default) to silence all framework-emitted logs.

func LaunchWithMode

func LaunchWithMode(mode LaunchMode) LaunchOption

func LaunchWithProfileDirectory

func LaunchWithProfileDirectory(profile string) LaunchOption

func LaunchWithProtocol

func LaunchWithProtocol(protocol Protocol) LaunchOption

func LaunchWithProxy

func LaunchWithProxy(proxy string) LaunchOption

func LaunchWithReconnect

func LaunchWithReconnect(policy ReconnectPolicy) LaunchOption

LaunchWithReconnect overrides the default CDP auto-reconnect policy. Pass ReconnectPolicy{Disabled: true} to opt out entirely; otherwise any zero-valued field falls back to the framework default (see ReconnectPolicy.effective).

func LaunchWithRemoteAllowOrigins

func LaunchWithRemoteAllowOrigins(origins ...string) LaunchOption

LaunchWithRemoteAllowOrigins sets the --remote-allow-origins switch value for the managed launch. Call with nil or no args to restore the framework default (scoped to http://localhost:<port>). Call with "*" to opt back into permissive mode when you genuinely need cross-origin devtools attach.

Has no effect in LaunchArgsPolicyPassthrough — the caller's Args are authoritative there.

func LaunchWithRetryPolicy

func LaunchWithRetryPolicy(policy RetryPolicy) LaunchOption

func LaunchWithSignalHandling

func LaunchWithSignalHandling(mode SignalHandlingMode) LaunchOption

func LaunchWithUserDataDir

func LaunchWithUserDataDir(dir string) LaunchOption

type LoadState

type LoadState string
const (
	LoadStateDOMContentLoaded LoadState = "domcontentloaded"
	LoadStateLoad             LoadState = "load"
	LoadStateNetworkIdle      LoadState = "networkidle"
)

type Meta

type Meta struct {
	Browser  Browser
	Protocol Protocol
	Driver   string
	Version  string
}

type MobilePreset

type MobilePreset struct {
	Name              string
	UserAgent         string
	Viewport          Viewport
	DeviceScaleFactor float64
	TouchEnabled      bool
}

type MonitorServeOption

type MonitorServeOption func(*MonitorServeOptions)

func WithMonitorToken

func WithMonitorToken(token string) MonitorServeOption

type MonitorServeOptions

type MonitorServeOptions struct {
	// Token enables simple token auth for monitor endpoints.
	// When set, callers must provide one of:
	//   - query: ?token=<token>
	//   - header: Authorization: Bearer <token>
	//   - header: X-GoBot-Monitor-Token: <token>
	Token string
}

type MonitorServer

type MonitorServer interface {
	Addr() string
	URL() string
	Close(ctx context.Context) error
}

type MonitorSnapshot

type MonitorSnapshot struct {
	GeneratedAt time.Time
	Engine      EngineDiagnostics
	Traces      []TraceEvent
}

type MouseButton

type MouseButton string
const (
	MouseLeft   MouseButton = "left"
	MouseMiddle MouseButton = "middle"
	MouseRight  MouseButton = "right"
)
type NavigationAction string
const (
	NavigationGoto    NavigationAction = "goto"
	NavigationReload  NavigationAction = "reload"
	NavigationBack    NavigationAction = "back"
	NavigationForward NavigationAction = "forward"
)
type NavigationEvent struct {
	Action NavigationAction
	URL    string
	Time   time.Time
}
type NavigationManager interface {
	// Context convention:
	//   - methods that call CDP / block / do IO take context.Context
	//   - pure in-memory snapshots do not take context.Context
	Goto(ctx context.Context, url string, opts ...GotoOption) error
	Reload(ctx context.Context, opts ...GotoOption) error
	Back(ctx context.Context, opts ...GotoOption) error
	Forward(ctx context.Context, opts ...GotoOption) error
	Wait(ctx context.Context, timeout time.Duration) (NavigationEvent, error)
	Events() []NavigationEvent
	Clear()
	Close(ctx context.Context) error
}

type NetworkFilter

type NetworkFilter struct {
	RequestID    string
	URLPattern   string
	Method       string
	ResourceType string
	Status       int
	StatusMin    int
	StatusMax    int
	PacketTypes  []PacketType
}

type NetworkManager

type NetworkManager interface {
	// Context convention:
	//   - methods that call CDP / block / do IO take context.Context
	//   - pure in-memory snapshots do not take context.Context
	SetHeaders(ctx context.Context, headers http.Header) error
	SetOffline(ctx context.Context, offline bool) error
	SetCacheDisabled(ctx context.Context, disabled bool) error
	OnRequest(fn func(RequestEvent)) (Subscription, error)
	OnResponse(fn func(ResponseEvent)) (Subscription, error)
	OnEvent(method string, fn func(ProtocolEvent)) (Subscription, error)
	EachEvent(fn func(ProtocolEvent), methods ...string) (Subscription, error)
	WaitEvent(ctx context.Context, method string, timeout time.Duration) (ProtocolEvent, error)
	OnFileDialog(fn func(FileDialogEvent)) (Subscription, error)
	HandleFileDialog(paths ...string) (Subscription, error)
	HandleAuth(username string, password string) (Subscription, error)
	SetBlockedURLs(ctx context.Context, patterns ...string) error
	Route(pattern string, handler RouteHandler) (Subscription, error)
	WaitRequest(ctx context.Context, timeout time.Duration) (RequestEvent, error)
	WaitResponse(ctx context.Context, timeout time.Duration) (ResponseEvent, error)
	WaitPacket(ctx context.Context, timeout time.Duration) (NetworkPacket, error)
	WaitPacketMatch(ctx context.Context, timeout time.Duration, filter NetworkFilter) (NetworkPacket, error)
	WaitTransaction(ctx context.Context, timeout time.Duration) (NetworkTransaction, error)
	WaitTransactionMatch(ctx context.Context, timeout time.Duration, filter NetworkFilter) (NetworkTransaction, error)
	Requests() []RequestEvent
	Responses() []ResponseEvent
	Packets() []NetworkPacket
	Transactions() []NetworkTransaction
	ResponseData(ctx context.Context, requestID string) (NetworkResponseData, error)
	ExportHAR(ctx context.Context, path string) error
	ReplayHAR(ctx context.Context, path string) (Subscription, error)
	Intercept() InterceptManager
	Clear()
	Close(ctx context.Context) error
}

type NetworkPacket

type NetworkPacket struct {
	Type     PacketType
	Time     time.Time
	Request  *RequestEvent
	Response *ResponseEvent
}

type NetworkResponseData

type NetworkResponseData struct {
	RequestID string
	Body      []byte
	Text      string
	Size      int
}

type NetworkTransaction

type NetworkTransaction struct {
	RequestID  string
	Request    RequestEvent
	Response   *ResponseEvent
	StartedAt  time.Time
	ResponseAt time.Time
}

type PDFOption

type PDFOption func(*PDFOptions)

func WithPDFLandscape

func WithPDFLandscape(v bool) PDFOption

func WithPDFMargins

func WithPDFMargins(top, right, bottom, left float64) PDFOption

func WithPDFPageRanges

func WithPDFPageRanges(v string) PDFOption

func WithPDFPaperSize

func WithPDFPaperSize(width, height float64) PDFOption

func WithPDFPrintBackground

func WithPDFPrintBackground(v bool) PDFOption

func WithPDFScale

func WithPDFScale(v float64) PDFOption

type PDFOptions

type PDFOptions struct {
	Landscape       bool
	PrintBackground bool
	Scale           float64
	PaperWidth      float64
	PaperHeight     float64
	MarginTop       float64
	MarginRight     float64
	MarginBottom    float64
	MarginLeft      float64
	PageRanges      string
}

type PacketType

type PacketType string
const (
	PacketRequest  PacketType = "request"
	PacketResponse PacketType = "response"
)

type PageCreatedHook

type PageCreatedHook func(page Page)

type PageDiagnostics

type PageDiagnostics struct {
	ID             string
	ContextID      string
	TargetID       string
	FrameID        string
	URL            string
	ControlPath    CDPControlPath
	SessionKind    CDPSessionKind
	UsedFallback   bool
	FallbackFrom   CDPControlPath
	FallbackReason string
	Closed         bool
	GeneratedAt    time.Time
}

type PageEnvironment

type PageEnvironment interface {
	SetEnv(ctx context.Context, env EnvProfile) error
}

type PageHooks

type PageHooks interface {
	OnBeforeNavigate(fn BeforeNavigateHook) (Subscription, error)
	OnAfterClick(fn AfterClickHook) (Subscription, error)
}

type PageInteraction

type PageInteraction interface {
	Hover(ctx context.Context, selector string) error
	Text(ctx context.Context, selector string) (string, error)
	HTML(ctx context.Context, selector string) (string, error)
	Attribute(ctx context.Context, selector, name string) (string, bool, error)
	Value(ctx context.Context, selector string) (string, error)
	Exists(ctx context.Context, selector string) (bool, error)
	Count(ctx context.Context, selector string) (int, error)
	IsVisible(ctx context.Context, selector string) (bool, error)
	WaitVisible(ctx context.Context, selector string, timeout time.Duration) error
	WaitHidden(ctx context.Context, selector string, timeout time.Duration) error
	Check(ctx context.Context, selector string) error
	Uncheck(ctx context.Context, selector string) error
	Select(ctx context.Context, selector string, values ...string) error
	Click(ctx context.Context, selector string, opts ...ClickOption) error
	Type(ctx context.Context, selector, text string, opts ...TypeOption) error
	Press(ctx context.Context, selector, key string, opts ...PressOption) error
	SetInputFiles(ctx context.Context, selector string, paths ...string) error
	Eval(ctx context.Context, js string, args ...any) (any, error)
	ExposeFunction(ctx context.Context, name string, fn ExposedFunction) (Subscription, error)
	AddScriptTag(ctx context.Context, opts ...ScriptTagOption) error
	AddStyleTag(ctx context.Context, opts ...StyleTagOption) error
	EvalOnNewDocument(ctx context.Context, js string) (Subscription, error)
	Wait(ctx context.Context, selector string, timeout time.Duration) error
	Screenshot(ctx context.Context, opts ...ScreenshotOption) ([]byte, error)
	PDF(ctx context.Context, opts ...PDFOption) ([]byte, error)
}

type PageLifecycle

type PageLifecycle interface {
	ID() string
	URL() string
	Diagnostics() PageDiagnostics
	DefaultTimeout() time.Duration
	SetDefaultTimeout(timeout time.Duration)
	RetryPolicy() RetryPolicy
	SetRetryPolicy(policy RetryPolicy)
	Raw() RawBridge
	// Context returns the Context that owns this Page.
	//
	// Use when you need to create a sibling page / tab from deep
	// inside code that only has a Page handle, or when you want to
	// share cookies / storage with another automation thread. The
	// returned Context is the exact same object held by the engine,
	// so it reflects all mutations made elsewhere.
	Context() Context
	// Engine returns the Engine that owns this Page's Context.
	//
	// Provided as a convenience so callers do not have to chain
	// page.Context().(unexported-type).engine; common use cases are
	// reaching Diagnostics / Reconnect / closing the entire engine
	// when only a Page reference is in scope.
	Engine() Engine
	Close(ctx context.Context) error
}

type PageManagers

type PageManagers interface {
	Navigation() NavigationManager
	Emulation() EmulationManager
	Actions() ActionChain
	Downloads() DownloadManager
	Network() NetworkManager
	Intercept() InterceptManager
	Storage() StorageManager
	Window() WindowManager
}
type PageNavigation interface {
	Goto(ctx context.Context, url string, opts ...GotoOption) error
	Reload(ctx context.Context, opts ...GotoOption) error
	GoBack(ctx context.Context, opts ...GotoOption) error
	GoForward(ctx context.Context, opts ...GotoOption) error
	Title(ctx context.Context) (string, error)
	Content(ctx context.Context) (string, error)
	SetContent(ctx context.Context, html string, opts ...SetContentOption) error
}

type PageNetworkControl

type PageNetworkControl interface {
	// Deprecated: use Page.Network().SetHeaders instead. The Page-level
	// alias is retained for backwards compatibility and will be removed
	// in a future release.
	SetExtraHTTPHeaders(ctx context.Context, headers http.Header) error
	// Deprecated: use Page.Network().SetOffline instead. The Page-level
	// alias is retained for backwards compatibility and will be removed
	// in a future release.
	SetOffline(ctx context.Context, offline bool) error
	// Deprecated: use Page.Network().SetCacheDisabled instead. The
	// Page-level alias is retained for backwards compatibility and will
	// be removed in a future release.
	SetCacheDisabled(ctx context.Context, disabled bool) error
	ResponseBody(ctx context.Context, requestID string) ([]byte, error)
	OnConsole(fn func(ConsoleMessage)) (Subscription, error)
	OnDialog(fn func(DialogEvent)) (Subscription, error)
	OnRequest(fn func(RequestEvent)) (Subscription, error)
	OnResponse(fn func(ResponseEvent)) (Subscription, error)
	OnDownload(fn func(DownloadEvent)) (Subscription, error)
	OnEvent(method string, fn func(ProtocolEvent)) (Subscription, error)
	EachEvent(fn func(ProtocolEvent), methods ...string) (Subscription, error)
	WaitEvent(ctx context.Context, method string, timeout time.Duration) (ProtocolEvent, error)
	OnFileDialog(fn func(FileDialogEvent)) (Subscription, error)
	HandleFileDialog(paths ...string) (Subscription, error)
	HandleAuth(username string, password string) (Subscription, error)
	SetBlockedURLs(ctx context.Context, patterns ...string) error
	Route(pattern string, handler RouteHandler) (Subscription, error)
	CancelDownload(ctx context.Context, guid string) error
}

type PageOption

type PageOption func(*PageOptions)

func WithInitialURL

func WithInitialURL(url string) PageOption

func WithPageDefaultTimeout

func WithPageDefaultTimeout(d time.Duration) PageOption

func WithPageEnv

func WithPageEnv(env EnvProfile) PageOption

func WithPageInitialURL

func WithPageInitialURL(url string) PageOption

WithPageInitialURL is an alias of WithInitialURL, retained for naming consistency with the rest of the PageOption family.

func WithPageRetryPolicy

func WithPageRetryPolicy(policy RetryPolicy) PageOption

type PageOptions

type PageOptions struct {
	InitialURL     string
	Env            *EnvProfile
	DefaultTimeout time.Duration
	RetryPolicy    RetryPolicy
}

type PageQuery

type PageQuery interface {
	Ele(selector string) Element
	Batch() BatchEval
	ByRole(role string, opts ...RoleOption) Element
	ByLabel(text string) Element
	ByTestID(testID string) Element
	ByText(text string) Element
	ByTextRegex(re *regexp.Regexp) Element
	ElementX(xpath string) Element
	ElementsX(ctx context.Context, xpath string) []Element
	HasX(ctx context.Context, xpath string) (bool, error)
	ElementByJS(ctx context.Context, js string, args ...any) (Element, error)
	Search(ctx context.Context, query string) ([]Element, error)
	// Eles resolves a selector into a slice of Element handles.
	//
	// Unlike Ele — which is purely lazy and does no I/O — Eles must
	// issue a CDP query to know how many matches exist, so it takes
	// a context to let callers propagate deadlines / cancellation.
	// The context is honoured for the underlying count query and any
	// internal retries.
	//
	// An empty (or whitespace-only) selector returns an empty slice,
	// not nil — safe to len()/range without guard.
	Eles(ctx context.Context, selector string) []Element
	WithShadow(path ...string) Element
	WithFrame(path ...string) Frame
	Waiter() PageWaiter
	Race() RaceBuilder
}

type PageTabs

type PageTabs interface {
	NewTab(ctx context.Context, opts ...PageOption) (Page, error)
	Tabs() []Page
	Tab(id string) (Page, bool)
	LatestTab() (Page, bool)
	Activate(ctx context.Context) error
	CloseOtherTabs(ctx context.Context) error
	FindTabByTitle(ctx context.Context, keyword string) (Page, bool)
	FindTabByURL(ctx context.Context, keyword string) (Page, bool)
}

type PageWaiter

type PageWaiter interface {
	Visible(ctx context.Context, selector string, timeout time.Duration) error
	Hidden(ctx context.Context, selector string, timeout time.Duration) error
	Exists(ctx context.Context, selector string, timeout time.Duration) error
	TitleContains(ctx context.Context, substr string, timeout time.Duration) error
	URLContains(ctx context.Context, substr string, timeout time.Duration) error
	LoadState(ctx context.Context, state LoadState, timeout time.Duration) error
	WaitForFunction(ctx context.Context, jsPredicate string, timeout time.Duration, args ...any) error
	WaitForFunctionValue(ctx context.Context, jsPredicate string, timeout time.Duration, args ...any) (any, error)
	WaitForResponse(ctx context.Context, urlPattern string, timeout time.Duration) (ResponseEvent, error)
	WaitForResponseMatch(ctx context.Context, filter NetworkFilter, timeout time.Duration) (ResponseEvent, error)
	WaitForDownload(ctx context.Context, timeout time.Duration) (DownloadEvent, error)
	WaitForDialog(ctx context.Context, timeout time.Duration) (DialogEvent, error)
	WaitRequestIdle(ctx context.Context, quiet time.Duration, timeout time.Duration) error
	WaitDOMStable(ctx context.Context, quiet time.Duration, timeout time.Duration) error
	WaitStable(ctx context.Context, quiet time.Duration, timeout time.Duration) error
	WaitForNetworkIdle(ctx context.Context, quiet time.Duration, timeout time.Duration) error

	// Builder-style sugar so callers can reuse page default timeout
	// without passing an explicit duration every call:
	//   page.Waiter().URLContainsTask("foo").Timeout(5*time.Second).Run(ctx)
	//   page.Waiter().VisibleTask("#btn").Run(ctx) // uses page default timeout
	VisibleTask(selector string) WaitTask
	HiddenTask(selector string) WaitTask
	ExistsTask(selector string) WaitTask
	TitleContainsTask(substr string) WaitTask
	URLContainsTask(substr string) WaitTask
	LoadStateTask(state LoadState) WaitTask
}

type PiercingBox

type PiercingBox struct {
	Left   float64
	Top    float64
	Width  float64
	Height float64
}

PiercingBox describes a node's content-box rectangle in viewport CSS-pixel coordinates of the top-level frame, as reported by DOM.getBoxModel.

This is the most useful coordinate space for caller-driven mouse dispatch — Input.dispatchMouseEvent expects the same coordinate system, so callers can pass these values directly to page.Click(ctx, "", bot.WithClickPosition(box.Left+dx, box.Top+dy)).

func PiercingNodeBox

func PiercingNodeBox(ctx context.Context, page Page, backendNodeID int) (PiercingBox, error)

PiercingNodeBox returns the content-box rectangle of the node with the given backend node id. Works for any node visible to the kernel — including those inside closed shadow roots and same-process iframes.

Use case: after PiercingDocument finds an iframe whose contents are out-of-process (so PiercingClick on a node inside the iframe is not possible), the caller can fetch the iframe element's box, compute a known interior offset (e.g. "30px from the left edge"), and dispatch a click into the parent viewport at that absolute coordinate. The click will then propagate into the OOPIF at the input layer — no session juggling required.

type PiercingNode

type PiercingNode struct {
	NodeID        int
	BackendNodeID int
	NodeType      int    // standard DOM node types: 1 element, 3 text, 9 document, 11 documentFragment
	NodeName      string // upper-case tag, e.g. "DIV", or "#text", "#document", "#document-fragment"
	NodeValue     string // text content for #text nodes, empty for elements

	Attributes map[string]string

	// Children are normal DOM children.
	Children []*PiercingNode

	// ShadowRoots holds attached shadow roots (open AND closed). A
	// regular DOM tree walk should usually descend into these too.
	ShadowRoots []*PiercingNode

	// ShadowRootType is set on shadow root nodes themselves: "open" or
	// "closed". Empty for non-shadow-root nodes.
	ShadowRootType string

	// ContentDocument is set for <iframe> / <frame> nodes, pointing at
	// the embedded document. Same-process only.
	ContentDocument *PiercingNode

	// FrameID is set on frame owner nodes (<iframe>, <frame>) and on
	// the document node of each frame. Useful when correlating with
	// Page.getFrameTree.
	FrameID string

	// Parent is the immediate ancestor in the walk order (children,
	// shadowRoots, contentDocument). nil for the root.
	Parent *PiercingNode `json:"-"`
}

PiercingNode is a Go representation of a single CDP DOM node, with children/shadowRoots/contentDocument linked into a tree.

The struct is intentionally minimal — we only surface the fields callers commonly need to identify a node (tag, attributes, text). Callers that need more (e.g. computed style) can call CDP directly using the BackendNodeID.

func PiercingDocument

func PiercingDocument(ctx context.Context, page Page) (*PiercingNode, error)

PiercingDocument fetches the entire DOM tree as the browser kernel sees it, including all open and closed shadow roots and same-process iframe documents. The returned root is the top-level #document node.

Internally this issues a single CDP DOM.getDocument call with depth=-1 and pierce=true. For pages with very large DOMs this can be slow; for typical interstitial / Turnstile pages it is sub-millisecond.

func (*PiercingNode) Attribute

func (n *PiercingNode) Attribute(name string) string

Attribute returns the named attribute's value (case-insensitive on the name). Empty string if missing.

func (*PiercingNode) Find

func (n *PiercingNode) Find(pred func(*PiercingNode) bool) *PiercingNode

Find returns the first descendant (including the receiver itself) for which pred returns true. nil if none match.

func (*PiercingNode) FindAll

func (n *PiercingNode) FindAll(pred func(*PiercingNode) bool) []*PiercingNode

FindAll returns every descendant (including the receiver) where pred returns true.

func (*PiercingNode) Walk

func (n *PiercingNode) Walk(visit func(*PiercingNode) bool)

Walk descends through Children, ShadowRoots and ContentDocument in depth-first order, calling visit at every node. The walk stops as soon as visit returns false.

type Point

type Point struct {
	X float64
	Y float64
}

type PooledEngine

type PooledEngine struct {
	Engine
	// contains filtered or unexported fields
}

PooledEngine is one checked-out slot from BrowserPool.

It forwards all Engine methods to the underlying Engine. Calling Close on a PooledEngine returns the slot to the pool (it does not close the pool).

func (*PooledEngine) Close

func (e *PooledEngine) Close(ctx context.Context) error

Close is an alias of Release so pooled engines can be used with `defer` in the same style as regular Engine lifecycle code.

func (*PooledEngine) Release

func (e *PooledEngine) Release(ctx context.Context) error

func (*PooledEngine) Underlying

func (e *PooledEngine) Underlying() Engine

type PressOption

type PressOption func(*PressOptions)

func WithPressDelay

func WithPressDelay(d time.Duration) PressOption

type PressOptions

type PressOptions struct {
	Delay time.Duration
}

type Protocol

type Protocol string
const (
	CDP  Protocol = "cdp"
	BiDi Protocol = "bidi"
)

func ParseProtocol

func ParseProtocol(s string) (Protocol, error)

func (Protocol) IsValid

func (p Protocol) IsValid() bool

func (Protocol) String

func (p Protocol) String() string

type ProtocolEvent

type ProtocolEvent struct {
	Method    string
	SessionID string
	Params    json.RawMessage
}

func (ProtocolEvent) Decode

func (e ProtocolEvent) Decode(v any) error

type RaceBuilder

type RaceBuilder interface {
	Element(selector string) *RaceElementBuilder
	Locator(name string, element Element) *RaceElementBuilder
	URLContains(substr string) RaceBuilder
	TitleContains(substr string) RaceBuilder
	Function(jsPredicate string, args ...any) RaceBuilder
	Event(method string) RaceBuilder
	Task(name string, task WaitTask) RaceBuilder
	Do(name string, fn func(ctx context.Context) error) RaceBuilder
	Run(ctx context.Context) (RaceResult, error)
}

type RaceElementBuilder

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

func (*RaceElementBuilder) Exists

func (b *RaceElementBuilder) Exists() RaceBuilder

func (*RaceElementBuilder) Hidden

func (b *RaceElementBuilder) Hidden() RaceBuilder

func (*RaceElementBuilder) Named

func (*RaceElementBuilder) Visible

func (b *RaceElementBuilder) Visible() RaceBuilder

type RaceResult

type RaceResult struct {
	Name    string
	Element Element
	Value   any
	Event   *ProtocolEvent
}

type RawBridge

type RawBridge interface {
	BiDi(ctx context.Context, method string, params map[string]any) (any, error)
	CDP(ctx context.Context, method string, params map[string]any) (any, error)
}

RawBridge is an escape hatch to the underlying wire protocol.

Calls made through RawBridge bypass most of go-bot's higher-level ergonomics (auto-wait/actionability, typed wrappers, helper defaults and some replay/retry safeguards). Prefer Page/Manager APIs unless you explicitly need a protocol method that is not yet surfaced.

type ReconnectPolicy

type ReconnectPolicy struct {
	// Disabled turns off automatic reconnection entirely. When true,
	// transport drops surface immediately as ErrClosed and the adapter
	// must be discarded.
	Disabled bool

	// InitialBackoff is the wait before the first reconnect attempt.
	// Default: 500ms. Must be > 0 when not Disabled.
	InitialBackoff time.Duration

	// MaxBackoff caps the exponential backoff between attempts.
	// Default: 30s. Must be >= InitialBackoff.
	MaxBackoff time.Duration

	// MaxDowntime is the total budget for a single reconnect storm
	// (sum of all backoffs + dial attempts). Once exceeded the adapter
	// gives up and shuts down. Zero (default) means 5 minutes.
	// Set to a negative value to retry forever.
	MaxDowntime time.Duration

	// CallRetryBudget is the per-call timeout window during which
	// in-flight cdpCall invocations will block waiting for the
	// transport to come back, before failing with the underlying
	// transport error. Zero (default) means 30s; negative disables
	// transparent retries (callers see the immediate failure).
	CallRetryBudget time.Duration

	// CallRetryMode controls which CDP method invocations are
	// transparently retried after a transport drop. Default
	// (CallRetryStrict) only retries known-idempotent methods (and any
	// call whose bytes never reached the wire); use CallRetryAll to
	// preserve the legacy behavior of retrying every transport-class
	// failure regardless of method semantics.
	//
	// "Strict" is the safer default — replaying a non-idempotent CDP
	// call (e.g. Input.dispatchKeyEvent, Page.captureScreenshot) after
	// the browser already processed it can double-fire side effects.
	CallRetryMode CallRetryMode
}

ReconnectPolicy configures how the adapter recovers from a dropped CDP websocket. The defaults are tuned for typical interactive automation (a blip should not lose your session); long-running batch jobs may want a larger MaxDowntime so they can survive a browser restart.

type Rect

type Rect struct {
	X      float64
	Y      float64
	Width  float64
	Height float64
}

type RedirectResponse

type RedirectResponse struct {
	URL        string
	Status     int
	StatusText string
	Headers    map[string]string
	MimeType   string
}

RedirectResponse describes the prior hop in an HTTP 3xx chain that Chromium reports inline on the next Network.requestWillBeSent event (via the redirectResponse field). It mirrors the relevant subset of the CDP Network.Response object — enough to print/audit a redirect chain without paying for a separate event subscription.

type RequestEvent

type RequestEvent struct {
	// Core HTTP envelope (always set).
	RequestID string
	URL       string
	Method    string
	Headers   map[string]string
	PostData  string

	// NetworkID is Chromium's network-level request id (when available).
	// On the Network event path this is usually equal to RequestID. On
	// the Fetch interception path, RequestID is interception-scoped while
	// NetworkID carries the underlying request id used across request/response
	// pause stages.
	NetworkID string

	// ResourceType is the browser's classification of the request:
	// "Document", "Stylesheet", "Image", "Media", "Font", "Script",
	// "TextTrack", "XHR", "Fetch", "Prefetch", "EventSource",
	// "WebSocket", "Manifest", "SignedExchange", "Ping", "CSPViolationReport",
	// "Preflight", "FedCM", "Other". Names follow the CDP enum
	// (Network.ResourceType).
	ResourceType string

	// FrameID is the id of the frame that initiated the request.
	// Populated for both Network.requestWillBeSent and Fetch.requestPaused
	// flows. Empty if the source event did not carry one (e.g. main
	// browsing context background fetches).
	FrameID string

	// LoaderID is Chromium's loader id for the request. For navigation
	// requests, LoaderID == RequestID — this equality is the canonical
	// CDP signal that a request initiates a navigation. Only set on
	// the Network event path; the Fetch interception path does not
	// expose loader id.
	LoaderID string

	// DocumentURL is the URL of the document that owns the request at
	// the moment the request was issued. For top-level navigations
	// this is the *previous* page's URL (the navigation target lives
	// in URL above). Only set on the Network event path.
	DocumentURL string

	// IsNavigationRequest is true when this request was issued to
	// load a document for a frame (top-level or sub-frame). Derived
	// from two signals depending on the source:
	//
	//   - Network.requestWillBeSent: LoaderID != "" && LoaderID == RequestID
	//     This is the authoritative Chromium signal.
	//
	//   - Fetch.requestPaused: ResourceType == "Document"
	//     Best-effort approximation. Fetch events do not carry loader
	//     id, so we fall back to the resource-type heuristic. This
	//     matches Playwright/Puppeteer's behaviour.
	//
	// Use this flag (rather than ResourceType=="Document") whenever
	// you want "is this the request that just took the page to a new
	// URL?" because it correctly excludes prefetch / prerender /
	// Document-typed sub-resources.
	IsNavigationRequest bool

	// HasUserGesture is true when the request was triggered by a
	// user activation (click, key press) propagated through the
	// renderer. Useful for distinguishing programmatic fetches from
	// user-driven navigations. Only set on the Network event path.
	HasUserGesture bool

	// RedirectResponse, when non-nil, carries the *previous* hop in
	// an HTTP 3xx redirect chain. Chromium does not emit a separate
	// Network.responseReceived event for the 3xx itself; instead it
	// piggybacks the prior response onto the next requestWillBeSent
	// event whose RequestID matches the one being redirected. Use
	// this to reconstruct a complete redirect chain (e.g.
	// http://github.com → 301 → https://github.com → 200) without
	// missing the intermediate status codes/headers.
	//
	// Only set on the Network event path. Always nil for the very
	// first hop of a request, the Fetch interception path, and any
	// non-redirect followup.
	RedirectResponse *RedirectResponse

	// PauseStage indicates which Fetch pause stage produced this event.
	// Empty for Network.* events and for Fetch payloads that don't carry
	// an explicit response-stage signal.
	PauseStage RoutePauseStage

	// ResponseStatus / ResponseStatusText / ResponseHeaders are only set
	// for Fetch response-stage pauses (PauseStage == RoutePauseStageResponse).
	// They mirror the paused response metadata and are useful when
	// rewriting a live upstream response via Route.Fulfill.
	ResponseStatus     int
	ResponseStatusText string
	ResponseHeaders    map[string]string
}

RequestEvent describes a single HTTP request observed by go-bot's network layer. The struct is shared across:

  • the streaming subscription path (Page.Network().OnRequest)
  • the request snapshot list (Page.Network().Requests())
  • the intercept manager (delivered as InterceptEvent.Request)
  • the route handler (Route.Request())

Fields beyond the basic HTTP envelope are set on a best-effort basis; callers should treat empty strings / zero values as "unknown" and not as semantic absence (e.g. an empty FrameID does not mean "main frame", it means "the source event did not carry a frame id").

type ResponseEvent

type ResponseEvent struct {
	// Core HTTP envelope (always set).
	RequestID  string
	URL        string
	Status     int
	StatusText string
	Headers    map[string]string
	MimeType   string

	// ResourceType mirrors RequestEvent.ResourceType for the matching
	// request.
	ResourceType string

	// FrameID is the id of the frame that owns the response. Same
	// semantics as RequestEvent.FrameID.
	FrameID string
}

ResponseEvent describes a single HTTP response observed by go-bot's network layer. See RequestEvent for the field-population contract.

type RetryPolicy

type RetryPolicy struct {
	Interval    time.Duration
	MaxAttempts int
}

RetryPolicy controls how operations retry on transient failures.

Semantics:

  • Interval <= 0 falls back to the framework default polling interval.
  • MaxAttempts > 0 caps the total number of attempts (including the first one). After that many failures the last error is returned.
  • MaxAttempts == 0 (zero value, equal to RetryAttemptsUnlimited) means "no explicit cap"; retries continue until the caller-supplied context deadline expires. Because framework callers always pass a context with a timeout, this is safe but can be surprising when the timeout is long. Set MaxAttempts explicitly when you want a bounded number of attempts.
  • MaxAttempts < 0 is invalid (see IsValid).

The helper constructors RetryOnce, RetryUpTo and RetryUnlimited are recommended for readability at call sites.

func RetryOnce

func RetryOnce() RetryPolicy

RetryOnce returns a policy that performs exactly one attempt (no retry).

func RetryUnlimited

func RetryUnlimited(interval time.Duration) RetryPolicy

RetryUnlimited returns a policy that retries with the given interval until the ambient context deadline fires.

func RetryUpTo

func RetryUpTo(attempts int, interval time.Duration) RetryPolicy

RetryUpTo returns a policy that retries up to attempts times (attempts must be > 0 to be meaningful; values <= 0 are treated as "no cap").

func (RetryPolicy) IsValid

func (p RetryPolicy) IsValid() bool

func (RetryPolicy) Unlimited

func (p RetryPolicy) Unlimited() bool

Unlimited reports whether the policy has no explicit attempt cap.

type RoleOption

type RoleOption func(*RoleOptions)

func WithRoleCaseSensitive

func WithRoleCaseSensitive(enabled bool) RoleOption

func WithRoleExact

func WithRoleExact(exact bool) RoleOption

func WithRoleName

func WithRoleName(name string) RoleOption

type RoleOptions

type RoleOptions struct {
	Name          string
	Exact         bool
	CaseSensitive bool
}

type Route

type Route interface {
	Request() RequestEvent
	Continue(ctx context.Context, opts ...ContinueOption) error
	Abort(ctx context.Context, reason string) error
	Fulfill(ctx context.Context, resp FulfillResponse) error
}

type RouteHandler

type RouteHandler func(ctx context.Context, route Route) error

type RoutePauseStage

type RoutePauseStage string
const (
	RoutePauseStageUnknown  RoutePauseStage = ""
	RoutePauseStageRequest  RoutePauseStage = "request"
	RoutePauseStageResponse RoutePauseStage = "response"
)

type ScreenshotOption

type ScreenshotOption func(*ScreenshotOptions)

func WithScreenshotClip

func WithScreenshotClip(x, y, width, height float64) ScreenshotOption

func WithScreenshotFullPage

func WithScreenshotFullPage(v bool) ScreenshotOption

func WithScreenshotQuality

func WithScreenshotQuality(v int) ScreenshotOption

func WithScreenshotSelector

func WithScreenshotSelector(selector string) ScreenshotOption

func WithScreenshotType

func WithScreenshotType(v string) ScreenshotOption

type ScreenshotOptions

type ScreenshotOptions struct {
	FullPage bool
	Type     string
	Quality  int
	Clip     *Rect
	Selector string
}

type ScriptTagOption

type ScriptTagOption func(*ScriptTagOptions)

func WithScriptTagAsync

func WithScriptTagAsync(enabled bool) ScriptTagOption

func WithScriptTagContent

func WithScriptTagContent(content string) ScriptTagOption

func WithScriptTagDefer

func WithScriptTagDefer(enabled bool) ScriptTagOption

func WithScriptTagType

func WithScriptTagType(typ string) ScriptTagOption

func WithScriptTagURL

func WithScriptTagURL(url string) ScriptTagOption

type ScriptTagOptions

type ScriptTagOptions struct {
	URL     string
	Content string
	Type    string
	Async   bool
	Defer   bool
}

type SetContentOption

type SetContentOption func(*SetContentOptions)

func WithSetContentTimeout

func WithSetContentTimeout(d time.Duration) SetContentOption

func WithSetContentWaitUntil

func WithSetContentWaitUntil(state LoadState) SetContentOption

type SetContentOptions

type SetContentOptions struct {
	Timeout   time.Duration
	WaitUntil LoadState
}

type SignalHandlingMode

type SignalHandlingMode string
const (
	SignalHandlingAuto   SignalHandlingMode = ""
	SignalHandlingManual SignalHandlingMode = "manual"
	SignalHandlingOff    SignalHandlingMode = "off"
)

func (SignalHandlingMode) IsValid

func (m SignalHandlingMode) IsValid() bool

func (SignalHandlingMode) String

func (m SignalHandlingMode) String() string

type StorageManager

type StorageManager interface {
	// Context convention:
	//   - methods that call CDP / block / do IO take context.Context
	//   - pure in-memory snapshots do not take context.Context
	Local() StorageScope
	Session() StorageScope
	IndexedDB() IndexedDBScope
	Close(ctx context.Context) error
}

type StorageScope

type StorageScope interface {
	Get(ctx context.Context, key string) (value string, exists bool, err error)
	Set(ctx context.Context, key string, value string) error
	Delete(ctx context.Context, key string) error
	Clear(ctx context.Context) error
	All(ctx context.Context) (map[string]string, error)
}

type StyleTagOption

type StyleTagOption func(*StyleTagOptions)

func WithStyleTagContent

func WithStyleTagContent(content string) StyleTagOption

func WithStyleTagMedia

func WithStyleTagMedia(media string) StyleTagOption

func WithStyleTagURL

func WithStyleTagURL(url string) StyleTagOption

type StyleTagOptions

type StyleTagOptions struct {
	URL     string
	Content string
	Media   string
}

type Subscription

type Subscription interface {
	Close() error
}

type TraceEvent

type TraceEvent struct {
	ID        uint64
	Time      time.Time
	Scope     string
	Operation string
	ContextID string
	PageID    string
	Success   bool
	Error     string
	Duration  time.Duration
	Details   map[string]any
}

type TraceFileOption

type TraceFileOption func(*TraceFileOptions)

func WithTraceFileMaxBackups

func WithTraceFileMaxBackups(maxBackups int) TraceFileOption

func WithTraceFileMaxBytes

func WithTraceFileMaxBytes(maxBytes int64) TraceFileOption

func WithTraceFileRotateDaily

func WithTraceFileRotateDaily(enabled bool) TraceFileOption

type TraceFileOptions

type TraceFileOptions struct {
	// MaxBytes controls size-based rotation.
	// <= 0 disables size rotation.
	MaxBytes int64
	// RotateDaily controls date-based rotation at day boundary.
	RotateDaily bool
	// MaxBackups caps the number of rotated files kept on disk.
	// <= 0 means unlimited.
	MaxBackups int
}

type TypeOption

type TypeOption func(*TypeOptions)

func WithTypeDelay

func WithTypeDelay(d time.Duration) TypeOption

type TypeOptions

type TypeOptions struct {
	Delay time.Duration
}

type UnsupportedComboError

type UnsupportedComboError struct {
	Browser  Browser
	Protocol Protocol
}

func (UnsupportedComboError) Error

func (e UnsupportedComboError) Error() string

type Viewport

type Viewport struct {
	Width  int
	Height int
}

type WaitTask

type WaitTask interface {
	Timeout(timeout time.Duration) WaitTask
	Run(ctx context.Context) error
}

WaitTask represents a deferred waiter check. Call Timeout to override the duration (0 means "owner default"), then Run.

type WindowBounds

type WindowBounds struct {
	Left   int
	Top    int
	Width  int
	Height int
	State  WindowState
}

type WindowManager

type WindowManager interface {
	// Context convention:
	//   - methods that call CDP / block / do IO take context.Context
	//   - pure in-memory snapshots do not take context.Context
	Bounds(ctx context.Context) (WindowBounds, error)
	SetBounds(ctx context.Context, bounds WindowBounds) error
	SetSize(ctx context.Context, width int, height int) error
	SetPosition(ctx context.Context, left int, top int) error
	Maximize(ctx context.Context) error
	Minimize(ctx context.Context) error
	Fullscreen(ctx context.Context) error
	Normal(ctx context.Context) error
	Close(ctx context.Context) error
}

type WindowState

type WindowState string
const (
	WindowStateNormal     WindowState = "normal"
	WindowStateMinimized  WindowState = "minimized"
	WindowStateMaximized  WindowState = "maximized"
	WindowStateFullscreen WindowState = "fullscreen"
)

Source Files

Jump to

Keyboard shortcuts

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