Documentation
¶
Index ¶
- Constants
- Variables
- func AcquireContext(b *rod.Browser, name string) (*rod.Browser, error)
- func AcquireSession(name string, opts SessionSpawnOpts) (string, error)
- func AddExtractionBoxes(page *rod.Page, result *ExtractionResult)
- func AddInitScript(srcPath string) (string, error)
- func AnnotateScreenshot(page *rod.Page, snapshot *PageSnapshot, screenshotPNG []byte) ([]byte, error)
- func ApplyColorScheme(page *rod.Page, scheme string) error
- func ApplyDefaultPageProfile(page *rod.Page) error
- func ApplyDevice(page *rod.Page, d Device) error
- func ApplyEmulationState(page *rod.Page, s EmulationState) error
- func ApplyInitScriptFiles(page *rod.Page, paths []string) error
- func ApplyInitScripts(page *rod.Page) error
- func ApplyLocale(page *rod.Page, locale string) error
- func ApplyProxyAuth(page *rod.Page, proxyURL string) error
- func ApplyServiceWorkersMode(page *rod.Page, mode string) error
- func ApplyStealth(page *rod.Page) error
- func ApplyTimezone(page *rod.Page, tz string) error
- func ApplyUserAgent(page *rod.Page, ua string) error
- func ApplyUserAgentLocale(page *rod.Page, ua string, locale string) error
- func BuildHTTPClient(opts HTTPClientOpts) (*http.Client, error)
- func CleanupFailedLauncher(l *launcher.Launcher, removeProfile bool)
- func CleanupLauncher(l *launcher.Launcher, removeProfile bool)
- func ClickElement(page *rod.Page, el *rod.Element) error
- func ClickElementWithButton(page *rod.Page, el *rod.Element, button proto.InputMouseButton) error
- func ClickRef(page *rod.Page, ref string, snapshot *PageSnapshot) error
- func ClipboardRead(page *rod.Page) (string, error)
- func ClipboardWrite(page *rod.Page, text string) error
- func CloseContext(b *rod.Browser, name string) error
- func CloseTab(browser *rod.Browser, index int) (proto.TargetTargetID, error)
- func CountSelector(page *rod.Page, selector string) int
- func DblClickRef(page *rod.Page, ref string, snapshot *PageSnapshot) error
- func DblClickRefWithButton(page *rod.Page, ref string, snapshot *PageSnapshot, ...) error
- func DecryptCookiesInPlace(cookiesPath string) (total, decrypted, failed int, err error)
- func DefaultExtensionPaths() ([]string, error)
- func DefaultExtensionsDir() (string, error)
- func DefaultSession() (string, bool)
- func DetachSysProcAttr() *syscall.SysProcAttr
- func DetectAgent() bool
- func DiscoverCDP(ports []int, timeout time.Duration) (string, error)
- func DiscoverCDPChannel(channel string, ports []int, timeout time.Duration) (string, error)
- func DismissCookieBanner(page *rod.Page) bool
- func DragDrop(page *rod.Page, fromRef, toRef string, snapshot *PageSnapshot, steps int) error
- func DragDropCoords(page *rod.Page, sx, sy, dx, dy float64, steps int) error
- func DropElement(el *rod.Element, payload dropPayload) error
- func DropTarget(page *rod.Page, target string, paths []string, data []DropData, ...) error
- func EvadeRuntimeEnable() bool
- func EvalJS(page *rod.Page, expr string, elementRef string, snapshot *PageSnapshot) (string, error)
- func EvalJSTimeout(page *rod.Page, expr string, elementRef string, snapshot *PageSnapshot, ...) (string, error)
- func ExtractNextData(html string) []byte
- func FindSystemChromeBinary() string
- func FormatCollect(r *CollectResult) string
- func FormatDiff(d SnapshotDiff) string
- func FormatErrors(errors []ErrorEntry) string
- func FormatMultiCollect(r *MultiCollectResult) string
- func FormatPlaywrightSnapshot(result *ExtractionResult) string
- func FormatPreview(r *PreviewResult) string
- func FormatPreviewProfile(r *PreviewResult, p RenderProfile) string
- func FormatText(result *ExtractionResult) string
- func FormatTextProfile(result *ExtractionResult, p RenderProfile) string
- func GetResponseBodyByRequestID(page *rod.Page, requestID string) (string, bool, error)
- func GhostchromeDataDirs() []string
- func GrantPlaywrightPermissions(browser *rod.Browser, names []string) error
- func HasSelector(page *rod.Page, selector string) bool
- func HideHighlights(page *rod.Page, target string, snapshot *PageSnapshot) error
- func HighlightTarget(page *rod.Page, target, style string, snapshot *PageSnapshot) error
- func HoverElement(page *rod.Page, el *rod.Element) error
- func HoverRef(page *rod.Page, ref string, snapshot *PageSnapshot) error
- func HumanMode() bool
- func InitScriptsDir() (string, error)
- func InjectCookies(page *rod.Page, cookies []CookieRecord) (int, error)
- func InternalRef(ref string) string
- func IsStaticNetworkEntry(resourceType, mimeType string) bool
- func KillAllSessions() (int, error)
- func KillProcess(pid int) error
- func LauncherOwnsRodTempProfile(l *launcher.Launcher, userDataDir string, launchArgs []string) bool
- func ListInitScripts() ([]string, error)
- func LoadFulfillBody(value string) ([]byte, error)
- func LoadRules(rulesPath, baseDir string) ([]compiledRule, error)
- func LoadStorageState(browser *rod.Browser, page *rod.Page, state *StorageState) error
- func MapPlaywrightPermissions(names []string) (mapped []proto.BrowserPermissionType, unsupported []string)
- func MatchRule(rules []compiledRule, url, method string) (*compiledRule, bool)
- func MustReadResponseBody(resp *http.Response) ([]byte, error)
- func NewLauncher(opts LauncherOpts) *launcher.Launcher
- func NewTab(browser *rod.Browser, url string) (*rod.Page, error)
- func ParseBlockList(s string) []string
- func ParseMouseButton(name string) (proto.InputMouseButton, error)
- func ParseProxyList(s string) []string
- func PlaywrightRef(ref string) string
- func PressKey(page *rod.Page, key string, ref string, snapshot *PageSnapshot) error
- func PrewarmDomains(page *rod.Page)
- func ProfileUsesSystemChrome(userDataDir string) bool
- func PruneSessions() (int, error)
- func ReactSuspense(page *rod.Page) ([]map[string]any, error)
- func RecoverBotChallenge(ctx RecoveryContext) (bool, error)
- func RecoverDialogAccept(ctx RecoveryContext) (bool, error)
- func RecoverNetworkSettle(ctx RecoveryContext) (bool, error)
- func RecoverStaleRef(ctx RecoveryContext) (bool, error)
- func RecoveryChain(ctx RecoveryContext, hooks []RecoveryHook) (retry bool, err error)
- func RemoveInitScript(name string) error
- func RemoveProfile(name string) error
- func RenderTraceHTML(entries []TraceEntry, sourcePath string) string
- func ResetEmulation(page *rod.Page) error
- func ResolveByLocator(page *rod.Page, loc Locator) (*rod.Element, error)
- func ResolveCDPEndpoint(raw string, timeout time.Duration) (string, error)
- func ResolveProfileDir(name string) (string, error)
- func ResolveRef(page *rod.Page, ref string, snapshot *PageSnapshot) (*rod.Element, error)
- func ResolveTarget(page *rod.Page, target string, snapshot *PageSnapshot) (*rod.Element, error)
- func RunVideoRuntime(ctx context.Context, opts VideoRuntimeOpts) (err error)
- func SaveCookiesJSON(profileDir string, cookies []CookieRecord) error
- func ScrollBy(page *rod.Page, dy int) (int, error)
- func ScrollToRef(page *rod.Page, ref string, snapshot *PageSnapshot) error
- func ScrollToY(page *rod.Page, y int, bottomSentinel bool) (int, error)
- func SelectOption(page *rod.Page, ref string, values []string, snapshot *PageSnapshot) error
- func SetCheckedRef(page *rod.Page, ref string, checked bool, snapshot *PageSnapshot) error
- func SetEvadeRuntimeEnable(on bool)
- func SetHumanMode(enabled bool)
- func SetStealthTimezone(tz string)
- func SetViewport(page *rod.Page, width, height int) error
- func StopSession(name string) error
- func SubmitOnElement(page *rod.Page, el *rod.Element) error
- func SwitchTab(browser *rod.Browser, index int) (*rod.Page, error)
- func TakeScreenshot(page *rod.Page, fullPage bool, elementRef string, quality int, ...) ([]byte, error)
- func TakeScreenshotFormat(page *rod.Page, fullPage bool, elementRef string, format string, quality int, ...) ([]byte, error)
- func TakeScreenshotScaled(page *rod.Page, fullPage bool, elementRef string, quality int, scale float64, ...) ([]byte, error)
- func TruncateURL(u string, maxLen int) string
- func TypeElement(page *rod.Page, el *rod.Element, text string) error
- func TypeFocused(page *rod.Page, text string) error
- func TypeRef(page *rod.Page, ref string, text string, snapshot *PageSnapshot) error
- func UploadRef(page *rod.Page, ref string, selector string, files []string, ...) error
- func ValidateExtractLevel(level ExtractLevel) error
- func VideoRuntimeStatusPath(framesDir string) string
- func VideoRuntimeStopPath(statusPath string) string
- func WaitForBotChallenge(page *rod.Page, timeout time.Duration) bool
- func WaitForLocator(page *rod.Page, loc Locator, state ElementState, timeout time.Duration) (*rod.Element, error)
- func WaitForPage(page *rod.Page, waitStrategy string) error
- func WaitForRef(page *rod.Page, ref string, snapshot *PageSnapshot, state ElementState, ...) (*rod.Element, error)
- func WaitForSelector(page *rod.Page, selector string, timeoutSec int) error
- func WaitForTarget(page *rod.Page, target string, snapshot *PageSnapshot, state ElementState, ...) (*rod.Element, error)
- func WriteHAR(h *HAR, path string) error
- type APIRequest
- type APIResponse
- type AlgoliaOpts
- type Browser
- func (b *Browser) Alive(d time.Duration) bool
- func (b *Browser) AppendConsoleLog(events []ObserverEvent) error
- func (b *Browser) AppendNetworkLog(entries []*CapturedEntry) error
- func (b *Browser) BrowserTraceState() BrowserTraceState
- func (b *Browser) CachedExtract(page *rod.Page) *ExtractionResult
- func (b *Browser) ClearConsoleLog() error
- func (b *Browser) ClearEmulationState() error
- func (b *Browser) ClearNetworkLog() error
- func (b *Browser) Close()
- func (b *Browser) ConnectURL() string
- func (b *Browser) Connected() bool
- func (b *Browser) ConsoleLog() []ObserverEvent
- func (b *Browser) CurrentTargetID() string
- func (b *Browser) DeleteSnapshot(targetID proto.TargetTargetID) error
- func (b *Browser) EmulationState() EmulationState
- func (b *Browser) NetworkLog() []*CapturedEntry
- func (b *Browser) Page() (*rod.Page, error)
- func (b *Browser) RodBrowser() *rod.Browser
- func (b *Browser) SaveSnapshot(page *rod.Page, result *ExtractionResult) error
- func (b *Browser) SetBrowserTraceState(state BrowserTraceState) error
- func (b *Browser) SetCurrentPage(page *rod.Page) error
- func (b *Browser) SetEmulationState(state EmulationState) error
- func (b *Browser) SetVideoState(state VideoState) error
- func (b *Browser) Snapshot(page *rod.Page) *PageSnapshot
- func (b *Browser) StartBackgroundObserver(page *rod.Page)
- func (b *Browser) VideoState() VideoState
- type BrowserOpts
- type BrowserTraceState
- type CaptureSession
- type CaptureSpec
- type CapturedEntry
- type CollectResult
- type CollectedItem
- type ContextEntry
- type ContextRegistryEntry
- type CookieRecord
- type Device
- type DialogResult
- type DiffEntry
- type DiffNode
- type DiffStats
- type DropData
- type ElementBox
- type ElementState
- type EmulationState
- type ErrorCollector
- type ErrorEntry
- type ExtractLevel
- type ExtractedNode
- type ExtractionResult
- func Extract(page *rod.Page, level ExtractLevel, selector string, includeSSR bool) (*ExtractionResult, error)
- func ExtractWithTimeout(page *rod.Page, level ExtractLevel, selector string, timeout time.Duration, ...) (*ExtractionResult, error)
- func ExtractionForRef(result *ExtractionResult, ref string) (*ExtractionResult, bool)
- func LimitExtractionDepth(result *ExtractionResult, maxDepth int) *ExtractionResult
- type ExtractionStats
- type FastFetchOpts
- type FastResult
- type HAR
- type HARContent
- type HARCreator
- type HAREntry
- type HARLog
- type HARPage
- type HARRequest
- type HARResponse
- type HARTimings
- type HTTPClientOpts
- type ImageDiffResult
- type InterceptSession
- type InterceptSpec
- type InterceptStats
- type LauncherOpts
- type Locator
- type LocatorMatchCountError
- type MultiCollectResult
- type NetworkEntry
- type Observation
- type Observer
- func (o *Observer) Drain(afterMs int64) []ObserverEvent
- func (o *Observer) Events() <-chan ObserverEvent
- func (o *Observer) Start(ctx context.Context) error
- func (o *Observer) Stats() ObserverStats
- func (o *Observer) Stop() error
- func (o *Observer) WriteNDJSON(ctx context.Context, w io.Writer) error
- type ObserverEvent
- type ObserverFilters
- type ObserverKind
- type ObserverOpts
- type ObserverStats
- type PageInfo
- type PageSnapshot
- type PersistentSessionObserver
- type PlaywrightLogState
- type PreviewResult
- type PreviewSummary
- type ProfileGCCandidate
- type ProfileInfo
- type ProxyPool
- type ReactComponent
- type Recorder
- type RecorderOp
- type RecorderOpts
- type RecoveryContext
- type RecoveryHook
- type RefSnapshot
- type RenderProfile
- type RuleMatchType
- type RuleSpec
- type RulesFile
- type SSRPayload
- type SSRSource
- type ScreenRecorder
- type ScreenRecorderOpts
- type SessionEntry
- type SessionRegistryEntry
- type SessionSpawnOpts
- type SiteResult
- type SnapshotDiff
- type StorageCookie
- type StorageKeyValue
- type StorageOrigin
- type StorageState
- type TabInfo
- type TraceEntry
- type VideoChapter
- type VideoRuntimeOpts
- type VideoRuntimeStatus
- type VideoState
Constants ¶
const ( ContentBoundaryOpen = "⟦page⟧" ContentBoundaryClose = "⟦/page⟧" )
ContentBoundaryOpen and ContentBoundaryClose are the sentinel markers used to fence untrusted page-derived text when ContentBoundary is enabled. They use Unicode brackets (U+27E6 / U+27E7) that are unlikely to appear in real page content and are visually distinct from tool output.
⟦page⟧ <untrusted text here> ⟦/page⟧
const CookiesJSONFilename = ".ghostchrome-cookies.json"
CookiesJSONFilename is the filename written by import-profile inside the ghostchrome profile dir. openPage() reads this on startup and replays the cookies into Chrome via CDP Network.setCookies.
const DefaultSessionName = "default"
const MobileViewportThreshold = 768
MobileViewportThreshold is the width below which SetViewport switches Chrome to mobile emulation. Callers persisting the resulting profile must use the same threshold or the replayed viewport would differ from the applied one.
const ( // VideoRuntimeStaleAfter bounds how long a persisted recording state can // block a new recording when its detached runtime disappeared without // publishing a terminal status. VideoRuntimeStaleAfter = 5 * time.Second )
Variables ¶
var ActivePolicy *policy.Policy
ActivePolicy is the session-wide policy enforced on navigation and actions. Set by the CLI or MCP server at startup. Nil means no restrictions.
var AntiBotPatterns = []string{
"*://js.datadome.co/*",
"*://*.datado.me/*",
"*://api-js.datadome.co/*",
"*://geo.captcha-delivery.com/*",
"*://*.perimeterx.net/*",
"*://client.perimeterx.net/*",
"*://collector-pxk*.px-cloud.net/*",
"*://*.imperva.com/v2/*",
"*://*.incapsula.com/_Incapsula_Resource*",
"*://*.akamaihd.net/akam/*",
"*://googletagservices.com/tag/js/gpt.js*",
"*://*.googletagservices.com/*",
"*://securepubads.g.doubleclick.net/*",
"*://*.googlesyndication.com/*",
"*://cdn.taboola.com/libtrc/*",
"*://cdn.outbrain.com/outbrain-loader.js*",
"*://static.criteo.net/js/*",
}
AntiBotPatterns is the curated list of glob URL patterns for scripts whose only purpose is detection/fingerprinting/heavy tracking. Blocking them at the network layer prevents the main thread from being monopolised by fingerprinting bursts that hang Runtime.evaluate calls.
Conservative list — only includes well-known anti-bot vendors and the heaviest analytics. Does NOT block CMP frameworks (OneTrust, Cookiebot, ...) because some sites' page rendering is gated on consent state.
var DefaultDiscoverPorts = []int{9222, 9223, 9224, 9225, 9226, 9227, 9228, 9229}
DefaultDiscoverPorts is the list of common Chrome remote debugging ports scanned by DiscoverCDP when no explicit port is supplied.
var DefaultExtensionNames = []string{"ublock", "icdc", "force-bg"}
DefaultExtensionNames lists the bundled extension slugs ghostchrome looks for under ~/.ghostchrome/extensions/<name>/ when --default-extensions is set. Mirrors browser-use's defaults.
var ErrSessionNotFound = errors.New("session not found in registry")
var ErrStaleRef = errors.New("stale ref: snapshot is missing or no longer matches the page")
ErrStaleRef indicates that a ref no longer maps to a live element.
Functions ¶
func AcquireContext ¶
AcquireContext returns a *rod.Browser view scoped to the named isolated context. It reuses an existing context if the registry entry is still alive in Chrome, otherwise creates a new one and persists it.
The caller must have already connected b to Chrome before calling this.
func AcquireSession ¶
func AcquireSession(name string, opts SessionSpawnOpts) (string, error)
AcquireSession resolves a named session to a browser WebSocket URL. If the session is already running it is reused; otherwise a detached `serve` process is spawned, bound to the disk profile of the same name, and probed until its CDP endpoint is ready.
func AddExtractionBoxes ¶ added in v0.6.0
func AddExtractionBoxes(page *rod.Page, result *ExtractionResult)
AddExtractionBoxes enriches interactive nodes with viewport-relative CSS pixel rectangles. Missing or detached nodes are skipped because pages may mutate while their boxes are being collected.
func AddInitScript ¶
AddInitScript copies a JS file into the init-scripts directory.
func AnnotateScreenshot ¶
func AnnotateScreenshot(page *rod.Page, snapshot *PageSnapshot, screenshotPNG []byte) ([]byte, error)
AnnotateScreenshot overlays numbered borders on each interactive element identified by the snapshot's refs. Input must be PNG; output is always PNG.
func ApplyColorScheme ¶
ApplyColorScheme emulates prefers-color-scheme. Accepts "dark", "light", "no-preference" (case-insensitive).
func ApplyDefaultPageProfile ¶
ApplyDefaultPageProfile installs the baseline browser profile used by normal pages. Stealth mode can still layer stronger anti-detection overrides later.
Caller responsibility: do NOT call this on a page belonging to a connected (foreign) Chrome unless the user explicitly opted in via --apply-profile. Mutating an existing user tab's UA / viewport breaks the runtime policy stated in CLAUDE.md.
func ApplyDevice ¶
ApplyDevice applies viewport metrics, UA, and touch emulation from a preset.
func ApplyEmulationState ¶
func ApplyEmulationState(page *rod.Page, s EmulationState) error
ApplyEmulationState replays a persisted emulation profile on a page. It is the exact counterpart of what ApplyDevice / SetViewport / ApplyUserAgent installed in the session that saved the profile.
func ApplyInitScriptFiles ¶
ApplyInitScriptFiles registers JavaScript files to run before future page scripts. This mirrors Playwright's addInitScript-style behavior for config supplied init scripts.
func ApplyInitScripts ¶
ApplyInitScripts loads and evaluates all init scripts on the page.
func ApplyLocale ¶
ApplyLocale emulates Playwright's browser.contextOptions.locale for a page. Without a User-Agent override, CDP has no standalone AcceptLanguage command, so this applies the HTTP header plus navigator.language(s) for new documents.
func ApplyProxyAuth ¶
ApplyProxyAuth wires CDP Fetch interception on the page so that basic-auth challenges issued by an upstream proxy (e.g. Bright Data, Smartproxy) are answered automatically with the credentials embedded in proxyURL.
Chromium ignores user:password embedded in --proxy-server URLs and instead surfaces a blocking basic-auth dialog. The work-around is to enable Fetch.enable{handleAuthRequests:true} and respond to Fetch.authRequired via Fetch.continueWithAuth.
If proxyURL is empty or carries no credentials, this is a silent no-op.
func ApplyServiceWorkersMode ¶
ApplyServiceWorkersMode applies the subset of Playwright's contextOptions.serviceWorkers that CDP can honor directly.
func ApplyStealth ¶
ApplyStealth applies anti-detection patches to a page via CDP. Targets DataDome, Akamai, and similar bot-detection systems.
func ApplyTimezone ¶
ApplyTimezone overrides the JavaScript Date/Intl timezone.
func ApplyUserAgent ¶
ApplyUserAgent overrides navigator.userAgent and the HTTP User-Agent header.
func ApplyUserAgentLocale ¶
ApplyUserAgentLocale overrides the User-Agent and optionally the browser Accept-Language value using the same CDP call Playwright-backed contexts use.
func BuildHTTPClient ¶
func BuildHTTPClient(opts HTTPClientOpts) (*http.Client, error)
BuildHTTPClient returns an http.Client honoring the supplied proxy URL. Supports http://, https:// (HTTP CONNECT) and socks5:// schemes. http(s) proxies may carry user:pass; socks5 auth is taken from URL too.
func CleanupFailedLauncher ¶
CleanupFailedLauncher releases resources after Launcher.Launch returned an error. A non-zero PID means Chrome did start, so wait for Rod's exit channel before deleting. With PID zero no process can still write the generated dir.
func CleanupLauncher ¶
CleanupLauncher synchronously terminates a successfully launched Chrome and optionally removes its Rod-owned temporary profile. Kill must precede Cleanup: Rod's Cleanup waits on the launcher exit channel and has no context or cancellation mechanism of its own.
func ClickElement ¶
ClickElement performs a click on an already-resolved element (used by the locator path so the same scroll+click+wait logic is shared).
func ClickElementWithButton ¶
ClickElementWithButton performs a click with an explicit mouse button.
func ClickRef ¶
func ClickRef(page *rod.Page, ref string, snapshot *PageSnapshot) error
ClickRef clicks the element at the given ref.
func ClipboardRead ¶
ClipboardRead returns the current clipboard text content.
func ClipboardWrite ¶
ClipboardWrite sets the clipboard text content.
func CloseContext ¶
CloseContext disposes the named context in Chrome (if alive) and removes it from the registry.
func CountSelector ¶
CountSelector returns the number of elements matching selector. Errors are swallowed and reported as 0 so the polling caller can distinguish "not-yet-rendered" from "match count below threshold".
func DblClickRef ¶
func DblClickRef(page *rod.Page, ref string, snapshot *PageSnapshot) error
DblClickRef double-clicks the element at the given ref.
func DblClickRefWithButton ¶
func DblClickRefWithButton(page *rod.Page, ref string, snapshot *PageSnapshot, button proto.InputMouseButton) error
DblClickRefWithButton double-clicks an element with an explicit mouse button.
func DecryptCookiesInPlace ¶
DecryptCookiesInPlace opens the SQLite Cookies database at path, decrypts every v10-tagged encrypted_value using the macOS Keychain Chrome key, and rewrites the row with the plaintext in `value` (encrypted_value cleared). Kept for backward compat with profiles imported before the JSON export scheme. Returns counts: total, decrypted, failed.
func DefaultExtensionPaths ¶
DefaultExtensionPaths returns absolute paths to the bundled extensions (uBlock Origin Lite, "I still don't care about cookies", Force Background Tab) that exist on disk. Missing entries are silently skipped. When none are found a hint is printed to stderr.
func DefaultExtensionsDir ¶
DefaultExtensionsDir returns the absolute path to the per-user extensions directory: ~/.ghostchrome/extensions.
func DefaultSession ¶
DefaultSession returns the default attached/session WS URL when it exists and is alive. It does not spawn a new browser.
func DetachSysProcAttr ¶
func DetachSysProcAttr() *syscall.SysProcAttr
DetachSysProcAttr returns platform-specific process attributes for a child that should survive the parent CLI process.
func DetectAgent ¶
func DetectAgent() bool
DetectAgent reports whether the current process runs inside an LLM agent. Detection order:
- GHOSTCHROME_PROFILE=agent|human (explicit override).
- GHOSTCHROME_AGENT=1|true (explicit opt-in).
- Known agent environment variables set by Claude Code, Cursor, Aider, Devin, Gemini CLI, and similar tools.
func DiscoverCDP ¶
DiscoverCDP probes 127.0.0.1 on the given ports for a running Chrome exposing /json/version, and returns the first webSocketDebuggerUrl found. When ports is nil/empty, DefaultDiscoverPorts is used. Returns an error when no endpoint responds within timeout.
func DiscoverCDPChannel ¶
DiscoverCDPChannel probes local Chrome remote-debugging ports for a browser matching a playwright-cli channel name. It attaches only to already running browsers with remote debugging enabled.
func DismissCookieBanner ¶
DismissCookieBanner attempts to find and click a cookie accept button. Returns true if a banner was found and dismissed.
func DragDropCoords ¶
DragDropCoords drags from one coordinate to another.
func DropElement ¶ added in v0.6.0
func DropTarget ¶ added in v0.6.0
func DropTarget(page *rod.Page, target string, paths []string, data []DropData, snapshot *PageSnapshot) error
DropTarget dispatches browser drag events on an arbitrary element. Unlike UploadRef, it does not require an <input type=file>: supplied files become File objects in event.dataTransfer and --data values become DataTransfer string entries.
func EvadeRuntimeEnable ¶
func EvadeRuntimeEnable() bool
EvadeRuntimeEnable reports whether Runtime.* subscriptions must be skipped.
func EvalJS ¶
EvalJS evaluates JavaScript on the page or in an element context. If elementRef is non-empty, the JS runs with `this` bound to that element.
func EvalJSTimeout ¶
func EvalJSTimeout(page *rod.Page, expr string, elementRef string, snapshot *PageSnapshot, d time.Duration) (string, error)
EvalJSTimeout runs EvalJS with a per-call deadline. When the page's main thread is busy (anti-bot fingerprinting, infinite analytics loop, ...), the underlying CDP Runtime.evaluate call hangs until the deadline fires instead of blocking the server-wide timeout. Returns a typed timeout error the caller can surface clearly to the LLM.
func ExtractNextData ¶
ExtractNextData scans for the canonical Next.js SSR data island in arbitrary HTML and returns the raw JSON payload. Returns nil when the marker is absent. Exported so callers that obtain HTML through a different path (e.g. Chrome page.HTML()) can reuse the same parser.
func FindSystemChromeBinary ¶
func FindSystemChromeBinary() string
FindSystemChromeBinary returns the absolute path to a real, installed Google Chrome / Chromium binary, or "" if none is found. Preferring the system Chrome over rod's bundled Chromium matters for anti-bot: the bundled build can lag many versions behind, and an outdated Chrome version is itself a signal Cloudflare-style challenges score against.
func FormatCollect ¶
func FormatCollect(r *CollectResult) string
FormatCollect renders a compact text table from collected items.
func FormatDiff ¶
func FormatDiff(d SnapshotDiff) string
FormatDiff renders a SnapshotDiff as compact text.
func FormatErrors ¶
func FormatErrors(errors []ErrorEntry) string
FormatErrors formats errors as compact text lines.
func FormatMultiCollect ¶
func FormatMultiCollect(r *MultiCollectResult) string
FormatMultiCollect renders a compact text report for multi-URL results.
func FormatPlaywrightSnapshot ¶
func FormatPlaywrightSnapshot(result *ExtractionResult) string
FormatPlaywrightSnapshot renders an accessibility tree in the documented playwright-cli snapshot style:
- heading "Title" [level=1]
- textbox "Search" [ref=e2]
- listitem:
- text: "Item"
func FormatPreview ¶
func FormatPreview(r *PreviewResult) string
FormatPreview renders a compact text report (human profile).
func FormatPreviewProfile ¶
func FormatPreviewProfile(r *PreviewResult, p RenderProfile) string
FormatPreviewProfile renders the preview using the given profile. In agent mode, empty sections and zero-stat headers are dropped, failed requests are grouped by status code and the DOM dump uses one-letter role tags.
func FormatText ¶
func FormatText(result *ExtractionResult) string
FormatText renders the extraction result as compact text (human profile).
func FormatTextProfile ¶
func FormatTextProfile(result *ExtractionResult, p RenderProfile) string
FormatTextProfile renders the extraction result using the given profile. The agent profile uses one-letter role tags, truncates long labels and shortens hrefs (see TruncateURL).
func GetResponseBodyByRequestID ¶
GetResponseBodyByRequestID fetches a response body from the current CDP session.
func GhostchromeDataDirs ¶
func GhostchromeDataDirs() []string
GhostchromeDataDirs returns the data directories a full uninstall removes: ~/.ghostchrome (profiles, contexts, sessions registry) and the ~/.cache/ghostchrome session-snapshot cache. Missing dirs are omitted.
func GrantPlaywrightPermissions ¶
GrantPlaywrightPermissions grants context-wide permissions using CDP. The origin is intentionally omitted to match Playwright config semantics.
func HasSelector ¶
HasSelector reports whether at least one element matches selector. It is a non-throwing alternative to page.Element used by polling loops.
func HideHighlights ¶ added in v0.6.0
func HideHighlights(page *rod.Page, target string, snapshot *PageSnapshot) error
HideHighlights removes an overlay for target. When target is empty it removes every ghostchrome highlight in the current document.
func HighlightTarget ¶ added in v0.6.0
func HighlightTarget(page *rod.Page, target, style string, snapshot *PageSnapshot) error
HighlightTarget draws a persistent, pointer-transparent overlay around a target. The overlay belongs to the document, so it remains visible when a later CLI invocation reconnects to the same page.
func HoverElement ¶
HoverElement hovers on an already-resolved element.
func HoverRef ¶
func HoverRef(page *rod.Page, ref string, snapshot *PageSnapshot) error
HoverRef hovers over the element at the given ref.
func InitScriptsDir ¶
InitScriptsDir returns the directory for user init scripts.
func InjectCookies ¶
func InjectCookies(page *rod.Page, cookies []CookieRecord) (int, error)
InjectCookies sets the given cookies on the browser via CDP, one at a time. A bad cookie (binary garbage from a misdecoded entry, mismatched domain, etc.) doesn't poison the rest of the batch. Returns the number of successful injections.
func InternalRef ¶
InternalRef maps playwright-cli eN refs back to ghostchrome's internal @N refs.
func IsStaticNetworkEntry ¶
IsStaticNetworkEntry reports whether a request is usually noise for Playwright CLI-style network inspection.
func KillAllSessions ¶
KillAllSessions stops every registered session.
func KillProcess ¶
KillProcess signals a managed background process.
func LauncherOwnsRodTempProfile ¶
LauncherOwnsRodTempProfile reports whether the launcher's final user data directory is the ephemeral direct child generated by Rod. Explicit profile inputs are never owned, even when they happen to live under Rod's prefix.
func ListInitScripts ¶
ListInitScripts returns the names of installed init scripts.
func LoadFulfillBody ¶
LoadFulfillBody returns raw bytes from a @path literal or the string otherwise. Useful so CLI flags can take `"@mock.json"` or an inline payload.
func LoadRules ¶
LoadRules parses path, validates each rule, loads bodyFile contents, and compiles match patterns. baseDir is used to resolve relative bodyFile paths.
func LoadStorageState ¶
LoadStorageState restores cookies browser-wide and localStorage per origin. For each origin referenced, the current page is navigated there briefly so the localStorage write lands in the right context.
func MapPlaywrightPermissions ¶
func MapPlaywrightPermissions(names []string) (mapped []proto.BrowserPermissionType, unsupported []string)
MapPlaywrightPermissions converts Playwright permission names to CDP Browser.grantPermissions values. Unknown permissions are returned so callers can report them instead of silently overclaiming parity.
func MatchRule ¶
MatchRule returns the first compiledRule whose pattern and method match url+method. method may be empty to skip method filtering.
func MustReadResponseBody ¶
MustReadResponseBody is exposed so callers building atypical clients can reuse the gzip handling. We keep readResponseBody (lowercase) for the internal call sites in FastFetch.
func NewLauncher ¶
func NewLauncher(opts LauncherOpts) *launcher.Launcher
NewLauncher returns a configured launcher with the shared anti-detection flags used by both auto-launch (NewBrowser) and the `serve` command. --no-sandbox is auto-enabled when running inside a CI runner (env GITHUB_ACTIONS / CI) or as root, because those environments disable the Chrome sandbox.
func NewTab ¶
NewTab opens a new tab, optionally navigating to url (blank when empty), activates it, and returns the page.
func ParseBlockList ¶
ParseBlockList splits a comma-separated glob list, trimming spaces and dropping empty entries.
func ParseMouseButton ¶
func ParseMouseButton(name string) (proto.InputMouseButton, error)
ParseMouseButton validates Playwright-compatible mouse buttons and returns the corresponding Rod protocol enum.
func ParseProxyList ¶
ParseProxyList splits a proxy list on commas, newlines and spaces, trims each entry and drops empties. Accepts the value of --proxy-list or the GHOSTCHROME_PROXY_LIST env (or the contents of a file passed to either).
func PlaywrightRef ¶
PlaywrightRef maps ghostchrome's internal @N refs to playwright-cli's eN refs.
func PressKey ¶
PressKey sends a keyboard key press. If ref is non-empty, focuses the element first.
func PrewarmDomains ¶
PrewarmDomains enables the CDP domains the engine will need lazily on its first call (Accessibility, DOM, Page lifecycle events). Each enable is idempotent and cheap, so calling this at session start removes the per-domain round-trip from the first extract / navigate / screenshot.
Best-effort: failures are silently ignored — every consumer re-enables the domain it needs anyway.
func ProfileUsesSystemChrome ¶
ProfileUsesSystemChrome returns true when the profile dir was created by `ghostchrome import-profile` and is bound to the system Chrome binary. We keep this for backward compatibility but with the cookie decryption path it's no longer required — the bundled Chromium can now read the imported cookies because they were rewritten as plaintext.
func PruneSessions ¶
PruneSessions removes registry entries whose Chrome is no longer reachable, killing any lingering serve process and its log. Returns the count pruned.
func ReactSuspense ¶
ReactSuspense returns the current Suspense boundary states.
func RecoverBotChallenge ¶
func RecoverBotChallenge(ctx RecoveryContext) (bool, error)
RecoverBotChallenge handles DataDome 403 / Cloudflare 503 bot-challenge pages. It waits up to 10s for the challenge to resolve, then signals retry.
func RecoverDialogAccept ¶
func RecoverDialogAccept(ctx RecoveryContext) (bool, error)
RecoverDialogAccept handles the case where a JS dialog is blocking the page. It accepts the dialog and signals retry=true so the op can be retried.
func RecoverNetworkSettle ¶
func RecoverNetworkSettle(ctx RecoveryContext) (bool, error)
RecoverNetworkSettle handles transient network timeouts by waiting 2s for the network to become idle, then signalling retry.
func RecoverStaleRef ¶
func RecoverStaleRef(ctx RecoveryContext) (bool, error)
RecoverStaleRef handles ErrStaleRef. Per the spec: it must NEVER silently remap refs. Instead it returns retry=false with an informative error so the agent can decide to run an explicit re-extract op.
func RecoveryChain ¶
func RecoveryChain(ctx RecoveryContext, hooks []RecoveryHook) (retry bool, err error)
RecoveryChain runs hooks in order until one returns retry=true or all are exhausted. Returns (true, nil) if a hook signalled recovery, (false, nil) if no hook could help, or (false, err) if a hook returned an error.
func RemoveInitScript ¶
RemoveInitScript removes a script by name from the init-scripts directory.
func RemoveProfile ¶
RemoveProfile deletes a profile directory. The name is validated and the resolved path is confirmed to live under the profiles dir before any removal, so it can never escape via traversal.
func RenderTraceHTML ¶
func RenderTraceHTML(entries []TraceEntry, sourcePath string) string
RenderTraceHTML produces a self-contained HTML viewer of a trace. No external deps; opens directly in a browser.
func ResetEmulation ¶
ResetEmulation drops every emulation override on the page and restores the browser's own User-Agent. Device metrics fall back to the real window size, which is what an un-emulated tab looks like.
func ResolveByLocator ¶
ResolveByLocator returns the single visible element matching the locator. Matching strategy:
- If Text is set: XPath text contains (case-insensitive). Matches <button>, <a>, <label>, generic text containers.
- Else: extract the a11y tree at skeleton level and filter by (role, name|label).
Zero or multiple visible matches are errors. This strictness is shared by action --by-* flags and generated Playwright locator strings so an ambiguous agent instruction can never silently act on the first element in tree order.
func ResolveCDPEndpoint ¶
ResolveCDPEndpoint returns a browser WebSocket debugger URL for a CDP endpoint. ws:// and wss:// inputs are already resolved; http(s) inputs are probed via /json/version.
func ResolveProfileDir ¶
ResolveProfileDir converts a short profile name into the canonical persistent Chrome user_data_dir path under ~/.ghostchrome/profiles/<name>. The directory is created with 0700 perms if missing.
func ResolveRef ¶
ResolveRef finds an element by its ref (@1, @2, etc.) using a persisted snapshot.
func ResolveTarget ¶ added in v0.6.0
ResolveTarget resolves one interaction target. Targets may be snapshot refs (@N or playwright-cli eN), a strict CSS selector, or the small Playwright locator subset emitted by generate-locator: getByRole, getByText, and getByLabel (with an optional { name: "..." } for getByRole).
CSS selectors must match exactly one element. This deliberately avoids the accidental-first-match behavior that is especially unsafe for agent input.
func RunVideoRuntime ¶ added in v0.6.0
func RunVideoRuntime(ctx context.Context, opts VideoRuntimeOpts) (err error)
RunVideoRuntime continuously records the requested target until a stop file is requested. A file control channel is portable and survives independent CLI processes without trusting a reused PID.
func SaveCookiesJSON ¶
func SaveCookiesJSON(profileDir string, cookies []CookieRecord) error
SaveCookiesJSON writes a portable cookie snapshot inside the profile dir.
func ScrollToRef ¶
func ScrollToRef(page *rod.Page, ref string, snapshot *PageSnapshot) error
ScrollToRef scrolls the element at the given ref into view without performing any other interaction.
func ScrollToY ¶
ScrollToY scrolls the page to an absolute Y pixel position. When bottomSentinel is true, the page is scrolled to document.body.scrollHeight regardless of the y argument — use this for "scroll-to bottom". Returns the final window.scrollY as observed after the scroll.
func SelectOption ¶
SelectOption selects option(s) in a <select> element by visible text.
func SetCheckedRef ¶
SetCheckedRef brings a checkbox/radio to the desired checked state. It is idempotent: if the element is already in the target state it does nothing, so "check" never accidentally toggles a box that was already ticked.
func SetEvadeRuntimeEnable ¶
func SetEvadeRuntimeEnable(on bool)
SetEvadeRuntimeEnable toggles Runtime.enable evasion process-wide. Wired from the root `--evade-runtime` flag / GHOSTCHROME_EVADE_RUNTIME env.
func SetHumanMode ¶
func SetHumanMode(enabled bool)
SetHumanMode toggles the human-input simulation globally. When false the engine uses the original Rod fast path; when true ClickElement / TypeElement / HoverElement dispatch human-shaped events.
func SetStealthTimezone ¶
func SetStealthTimezone(tz string)
SetStealthTimezone sets the explicit --timezone override applied by ApplyStealth. An empty value falls back to a locale-derived default.
func SetViewport ¶
SetViewport overrides the page viewport dimensions.
func StopSession ¶
StopSession terminates the named session's process and removes it from the registry (best-effort: the process may already be gone).
func SubmitOnElement ¶
SubmitOnElement focuses el and presses Enter on it. TypeElement blurs the field after writing (so change/validation handlers fire), which means a follow-up Enter would otherwise land on document.body — re-focus first so the keydown reaches the input and submits its form.
func TakeScreenshot ¶
func TakeScreenshot(page *rod.Page, fullPage bool, elementRef string, quality int, snapshot *PageSnapshot) ([]byte, error)
TakeScreenshot captures the page or a specific element. If elementRef is non-empty, captures only that element. If fullPage is true, captures the full scrollable page. quality controls JPEG/WebP quality (1-100); PNG is used if quality <= 0.
func TakeScreenshotFormat ¶
func TakeScreenshotFormat(page *rod.Page, fullPage bool, elementRef string, format string, quality int, snapshot *PageSnapshot) ([]byte, error)
TakeScreenshotFormat is the explicit-format variant. format is "png", "jpeg", "webp", or "" to default (webp when quality > 0, png otherwise). WebP at q=60 is typically 30-50% smaller than JPEG at the same visual quality — preferred when the consumer is an LLM agent that pays per byte.
func TakeScreenshotScaled ¶
func TakeScreenshotScaled(page *rod.Page, fullPage bool, elementRef string, quality int, scale float64, snapshot *PageSnapshot) ([]byte, error)
TakeScreenshotScaled is like TakeScreenshot but accepts a device scale factor. scale <= 0 or == 1 means native resolution. scale = 0.5 halves both dimensions (quartering pixel count and file size).
func TruncateURL ¶
TruncateURL strips common scheme/www prefixes and shortens the URL to maxLen. Used by formatted output from preview and collect.
func TypeElement ¶
TypeElement writes text into an already-resolved element.
func TypeFocused ¶
TypeFocused writes text into the currently focused element without changing focus or clearing existing content.
func TypeRef ¶
TypeRef types text into the element at the given ref. Uses focus + select all + keyboard typing to work with React/Vue/Angular.
func UploadRef ¶
func UploadRef(page *rod.Page, ref string, selector string, files []string, snapshot *PageSnapshot) error
UploadRef sets the files on a file-input element.
The target can be identified either by:
- ref: a @N reference from the current snapshot (works when the input is a native, visible <input type=file>).
- selector: a CSS selector (use this when the visible widget is a styled button wrapping a hidden input — common pattern).
Exactly one of ref or selector must be non-empty.
func ValidateExtractLevel ¶
func ValidateExtractLevel(level ExtractLevel) error
ValidateExtractLevel ensures the extraction level is supported.
func VideoRuntimeStatusPath ¶ added in v0.6.0
func VideoRuntimeStopPath ¶ added in v0.6.0
func WaitForBotChallenge ¶
WaitForBotChallenge detects bot-challenge pages (DataDome, Cloudflare, etc.) and waits for the challenge to clear.
Two behaviours make it materially more reliable than a plain poll loop:
- Reload of a wedged challenge. Cloudflare hands out an independent challenge token per navigation; an instance that hasn't cleared in ~20s almost never un-sticks on its own, but a fresh reload usually gets a solvable one. We reload up to 3 times within the budget.
- A one-off pointer nudge. A few Cloudflare variants only progress once the page has observed a genuine input event.
Returns true if a challenge was detected and ultimately cleared.
func WaitForLocator ¶
func WaitForLocator(page *rod.Page, loc Locator, state ElementState, timeout time.Duration) (*rod.Element, error)
WaitForLocator resolves a Locator with retry-until-found-or-stable logic.
It polls every 100 ms with exponential backoff up to 500 ms per interval. Deadline is set by timeout (0 = no wait, resolve once and return).
Returns the resolved element or a timeout/context error.
func WaitForPage ¶
WaitForPage applies a supported page wait strategy.
Strategies (ordered fastest → slowest typically):
- "domcontentloaded": fires when HTML parsed, before sub-resources. ~200-500ms faster than "load" on real-world pages with images/iframes/3P scripts.
- "load": "load" event — DOM + sub-resources fetched.
- "stable": DOM mutations have settled for 500ms.
- "idle": network has been idle for 500ms.
- "none": return immediately.
Defaults to "domcontentloaded" for empty input — that's the right trade-off for an LLM agent: parsing is done, refs are extractable, but we don't pay for late-loading ads/analytics.
func WaitForRef ¶
func WaitForRef(page *rod.Page, ref string, snapshot *PageSnapshot, state ElementState, timeout time.Duration) (*rod.Element, error)
WaitForRef waits until the element identified by ref in snapshot reaches the desired state.
IMPORTANT: This function PRESERVES the original ref → backendNodeID mapping. It never re-extracts or remaps refs — if the element is stale it returns ErrStaleRef so the caller can decide to re-extract.
Returns the resolved element once it satisfies state, or an error.
func WaitForSelector ¶
WaitForSelector waits for a CSS selector to appear in the DOM.
func WaitForTarget ¶ added in v0.6.0
func WaitForTarget(page *rod.Page, target string, snapshot *PageSnapshot, state ElementState, timeout time.Duration) (*rod.Element, error)
WaitForTarget waits for a ref, strict CSS selector, or supported Playwright locator string. Refs retain their persisted snapshot mapping; CSS selectors and locator strings are resolved afresh while polling.
Types ¶
type APIRequest ¶
type APIRequest struct {
Method string // GET, POST, PUT, DELETE, … (default GET)
URL string // absolute, with query string
Headers map[string]string // any custom headers
Body []byte // request body, plain bytes
Timeout time.Duration // per-request deadline (default 8s)
Proxy string // optional http(s):// or socks5:// proxy URL
}
APIRequest is the cross-method, JSON-aware request shape used by FastFetchAPI. Headers and Body are sent as-is; the helper only owns transport-level details (gzip handling, timeout, JSON detection).
type APIResponse ¶
type APIResponse struct {
Status int `json:"status"`
URL string `json:"url"`
Headers http.Header `json:"headers,omitempty"`
Body []byte `json:"-"`
BodyText string `json:"body_text,omitempty"`
JSON json.RawMessage `json:"json,omitempty"`
IsJSON bool `json:"is_json"`
Elapsed time.Duration `json:"-"`
ElapsedMs int64 `json:"elapsed_ms"`
ContentLength int64 `json:"content_length"`
}
APIResponse is what FastFetchAPI returns. Body is the decoded payload (gzip handled). JSON is non-nil when Body parses cleanly as JSON, regardless of the response Content-Type — many APIs lie about the type.
func AlgoliaQuery ¶
func AlgoliaQuery(ctx context.Context, opts AlgoliaOpts) (*APIResponse, error)
AlgoliaQuery is a small convenience wrapper around FastFetchAPI for the common Algolia search shape used by capcar / starterre / aramis-style recipes:
POST https://<appId>-dsn.algolia.net/1/indexes/<index>/query
X-Algolia-Application-Id: <appId>
X-Algolia-API-Key: <apiKey>
{"params":"<urlencoded form>"}
We construct the params payload from the supplied params map and let FastFetchAPI do the actual HTTP work. Returns the parsed Algolia response (typically `{ hits: [...], nbHits: N, nbPages: P }`).
func FastFetchAPI ¶
func FastFetchAPI(ctx context.Context, req APIRequest) (*APIResponse, error)
FastFetchAPI is the JSON-API counterpart to FastFetch. Use it to replay XHR endpoints captured via `ghostchrome --observe` or to hit a known API directly (Algolia, vendor JSON APIs, public REST). It does not attempt anti-bot detection — APIs that need cookies/tokens fail with a clean status code that the caller acts on.
Differences from FastFetch:
- generic method (GET/POST/PUT/…)
- no SSR / __NEXT_DATA__ scanning
- tries to JSON-parse the body opportunistically; falls back to text
type AlgoliaOpts ¶
type AlgoliaOpts struct {
AppID string
APIKey string
Index string
Endpoint string
Params map[string]string // raw params, joined with `=&`; alternative to ParamsForm
ParamsForm string // pre-built `query=&hitsPerPage=20&page=0` string
ExtraHeaders map[string]string
Timeout time.Duration
Proxy string
}
AlgoliaOpts groups the Algolia-specific knobs. AppID/APIKey/Index are required; Endpoint can be overridden if the site uses a custom DSN.
type Browser ¶
type Browser struct {
// contains filtered or unexported fields
}
Browser wraps a Rod browser with connect/launch logic.
func NewBrowser ¶
NewBrowser creates a browser instance. If connectURL is set, connects to an existing Chrome via CDP. Otherwise, auto-launches a new Chrome process.
func NewBrowserWith ¶
func NewBrowserWith(opts BrowserOpts) (*Browser, error)
NewBrowserWith creates a browser instance with full options. Persistent user_data_dir and upstream proxy only apply in auto-launch mode (i.e., when opts.ConnectURL is empty).
func (*Browser) Alive ¶
Alive reports whether the underlying Chrome still answers CDP within d. A crashed or killed Chrome leaves the rod handle poisoned — every call on it fails with a context error — so callers holding a long-lived Browser use this cheap probe (one Browser.getVersion round-trip, ~1ms on a live process, instant failure on a dead one) before trusting it.
func (*Browser) AppendConsoleLog ¶
func (b *Browser) AppendConsoleLog(events []ObserverEvent) error
AppendConsoleLog appends console events to the persistent session log.
func (*Browser) AppendNetworkLog ¶
func (b *Browser) AppendNetworkLog(entries []*CapturedEntry) error
AppendNetworkLog appends network entries to the persistent session log.
func (*Browser) BrowserTraceState ¶
func (b *Browser) BrowserTraceState() BrowserTraceState
BrowserTraceState returns the persisted CDP tracing state for this session.
func (*Browser) CachedExtract ¶
func (b *Browser) CachedExtract(page *rod.Page) *ExtractionResult
CachedExtract returns the cached ExtractionResult for the current page if the URL has not changed since the last extraction. Returns nil when no cache exists or the page has navigated. This avoids the expensive CDP AccessibilityGetFullAXTree call when the page content is unchanged.
The URL check uses a lightweight JS eval instead of page.Info() to minimize CDP round-trips.
func (*Browser) ClearConsoleLog ¶
ClearConsoleLog removes the persistent console log for this session.
func (*Browser) ClearEmulationState ¶
ClearEmulationState forgets the persisted emulation profile.
func (*Browser) ClearNetworkLog ¶
ClearNetworkLog removes the persistent network log for this session.
func (*Browser) ConnectURL ¶ added in v0.6.0
ConnectURL returns the resolved CDP endpoint used by this browser. Managed sessions and --connect=auto resolve their endpoint before Browser creation, so detached helpers must use this value instead of the original CLI flag.
func (*Browser) Connected ¶
Connected returns true if connected to external Chrome (not launched by us).
func (*Browser) ConsoleLog ¶
func (b *Browser) ConsoleLog() []ObserverEvent
ConsoleLog returns a copy of the persistent console log.
func (*Browser) CurrentTargetID ¶
CurrentTargetID returns the persisted current tab target, if any.
func (*Browser) DeleteSnapshot ¶
func (b *Browser) DeleteSnapshot(targetID proto.TargetTargetID) error
DeleteSnapshot removes stored ref state for a closed page target.
func (*Browser) EmulationState ¶
func (b *Browser) EmulationState() EmulationState
EmulationState returns the emulation profile persisted for this session.
func (*Browser) NetworkLog ¶
func (b *Browser) NetworkLog() []*CapturedEntry
NetworkLog returns a copy of the persistent network log.
func (*Browser) Page ¶
Page returns the active page or creates a new one. When connected to an existing Chrome, it prefers the persisted active tab.
func (*Browser) RodBrowser ¶
RodBrowser returns the underlying rod.Browser for advanced operations.
func (*Browser) SaveSnapshot ¶
func (b *Browser) SaveSnapshot(page *rod.Page, result *ExtractionResult) error
SaveSnapshot persists the latest ref snapshot for the page.
SSRPayloads are stripped from the persisted copy before caching (see stripSSRForCache) — the caller's result, used for the immediate command response, is left untouched; only the copy written to disk is stripped, so a later non-SSR command reading this cache via CachedExtract can never leak SSR data it didn't ask for.
func (*Browser) SetBrowserTraceState ¶
func (b *Browser) SetBrowserTraceState(state BrowserTraceState) error
SetBrowserTraceState stores the CDP tracing state for this session.
func (*Browser) SetCurrentPage ¶
SetCurrentPage marks the provided page as the current tab for the session.
func (*Browser) SetEmulationState ¶
func (b *Browser) SetEmulationState(state EmulationState) error
SetEmulationState persists the emulation profile so the next invocation can replay it. It is a no-op outside managed sessions (one-shot launches keep their overrides for the whole process; foreign Chromes must not be mutated).
func (*Browser) SetVideoState ¶
func (b *Browser) SetVideoState(state VideoState) error
SetVideoState stores video metadata for this session.
func (*Browser) Snapshot ¶
func (b *Browser) Snapshot(page *rod.Page) *PageSnapshot
Snapshot returns the last persisted snapshot for the current page.
func (*Browser) StartBackgroundObserver ¶
Close cleans up the browser resources. External Chrome keeps running; the CLI process owns the websocket lifetime.
func (*Browser) VideoState ¶
func (b *Browser) VideoState() VideoState
VideoState returns the persisted video metadata for this session.
type BrowserOpts ¶
type BrowserOpts struct {
ConnectURL string
Headless bool
Invisible bool
TimeoutSec int
CDPHeaders map[string]string
CDPTimeoutMS int
UserDataDir string // absolute path; ignored when ConnectURL is set
Proxy string // upstream proxy URL; ignored when ConnectURL is set
ProxyBypass string // Chromium proxy bypass list; ignored when ConnectURL is set
ExecutablePath string // Chrome/Chromium binary path; ignored when ConnectURL is set
LaunchArgs []string // extra Chromium switches; ignored when ConnectURL is set
Extensions []string // absolute paths to unpacked extensions; ignored when ConnectURL is set
SystemChrome bool // force /Applications/Google Chrome.app binary; ignored when ConnectURL is set
// AttachFresh is set when ConnectURL points at a Chrome we don't own
// (the user's personal browser, discovered via DiscoverCDP). In that
// case we must NOT reuse any existing tab — every command works in a
// freshly created background target so the user's foreground tab is
// left untouched. Ignored in auto-launch mode.
AttachFresh bool
// ContextName, when non-empty, routes all page operations through a
// named isolated BrowserContext (incognito). The name→contextID mapping
// is persisted in ~/.ghostchrome/contexts.json across CLI invocations.
// Only meaningful in connected mode (ConnectURL != ""). In auto-launch
// mode each process already gets its own profile; the flag is ignored.
ContextName string
// TargetTabIndex selects an explicit tab index in connected mode.
// Nil means "use persisted state or auto-select when unambiguous".
TargetTabIndex *int
// ApplyProfile, when true, installs ghostchrome's default UA / viewport
// profile on whichever page Page() resolves to. In auto-launch mode it
// is on by default (the page is ours). In connected mode it must be
// explicit — mutating a foreign Chrome tab violates the runtime policy
// stated in CLAUDE.md.
ApplyProfile bool
// ManagedSession is set when ConnectURL points at a Chrome ghostchrome
// itself spawned and owns (the transparent daemon or an explicit
// `-s <name>` session). Only those sessions replay the persisted
// emulation profile across invocations: doing it on a foreign Chrome
// would mutate a user tab, which the runtime policy forbids.
ManagedSession bool
// ProviderFunc, when set, replaces the local launcher for Chrome
// provisioning. Returns a WS URL and a cleanup function. Ignored
// when ConnectURL is set (direct connection takes precedence).
ProviderFunc func(ctx context.Context) (wsURL string, cleanup func(), err error)
}
BrowserOpts configures NewBrowserWith. It supersedes the positional parameters of NewBrowser and adds persistent profile + upstream proxy support for auto-launch.
type BrowserTraceState ¶
type BrowserTraceState struct {
Active bool `json:"active,omitempty"`
StartedAt string `json:"started_at,omitempty"`
Output string `json:"output,omitempty"`
}
BrowserTraceState tracks whether CDP browser tracing is currently active for a persistent session.
type CaptureSession ¶
type CaptureSession struct {
// contains filtered or unexported fields
}
CaptureSession owns the goroutine that listens to Network events.
func StartCapture ¶
func StartCapture(page *rod.Page, spec CaptureSpec) (*CaptureSession, error)
StartCapture enables the Network domain and begins listening.
func (*CaptureSession) Entries ¶
func (s *CaptureSession) Entries() []*CapturedEntry
Entries returns a snapshot of collected entries.
func (*CaptureSession) ReachedMax ¶
func (s *CaptureSession) ReachedMax() <-chan struct{}
ReachedMax fires once Max matches have been collected.
func (*CaptureSession) Stop ¶
func (s *CaptureSession) Stop() ([]*CapturedEntry, error)
Stop detaches listeners, closes the output file, and returns any write errors.
type CaptureSpec ¶
type CaptureSpec struct {
// URLMatch is a regex applied to the full request URL. Empty = match all.
URLMatch string
// MimeMatch is a regex applied to the response MIME type. Empty = match all.
MimeMatch string
// Max is the number of MATCHING entries to collect before ReachedMax fires.
// 0 = unlimited.
Max int
// IncludeBody, when true, fetches the response body via
// Network.getResponseBody for every matching entry.
IncludeBody bool
// ExcludeStatic drops script, stylesheet, font, image, and media requests from
// matching entries. It is intended for Playwright CLI-compatible network
// output; raw capture keeps static resources by default.
ExcludeStatic bool
// OutputPath, if set, streams each entry as it is captured (NDJSON).
OutputPath string
}
CaptureSpec configures a passive network capture session. Generic DevTools-Network-tab style recorder: no request modification, no auth bypass — just observation of what the page already requested.
type CapturedEntry ¶
type CapturedEntry struct {
RequestID string `json:"request_id"`
Method string `json:"method"`
URL string `json:"url"`
ResourceType string `json:"resource_type"`
Status int `json:"status"`
StatusText string `json:"status_text,omitempty"`
MimeType string `json:"mime_type,omitempty"`
ReqHeaders map[string]string `json:"request_headers,omitempty"`
ResHeaders map[string]string `json:"response_headers,omitempty"`
PostData string `json:"post_data,omitempty"`
Body string `json:"body,omitempty"`
BodyBase64 bool `json:"body_base64,omitempty"`
BodyError string `json:"body_error,omitempty"`
StartedAt string `json:"started_at"`
}
CapturedEntry is one fully-hydrated request/response pair.
type CollectResult ¶
type CollectResult struct {
PageURL string `json:"page_url"`
ItemCount int `json:"item_count"`
Items []CollectedItem `json:"items"`
}
CollectResult holds all collected items from a listing page.
func Collect ¶
func Collect(page *rod.Page, limit int) (*CollectResult, error)
Collect auto-detects repeated listing cards on a page and extracts structured data. It finds elements containing price patterns (€, $, £), groups them by common ancestor, and extracts title, price, URL, and metadata from each card.
type CollectedItem ¶
type CollectedItem struct {
Title string `json:"title"`
Price string `json:"price,omitempty"`
URL string `json:"url,omitempty"`
Fields map[string]string `json:"fields,omitempty"`
}
CollectedItem is a single listing item extracted from a page.
type ContextEntry ¶
type ContextEntry struct {
ID string `json:"id"`
}
ContextEntry maps a user-supplied name to a CDP BrowserContextID.
type ContextRegistryEntry ¶
type ContextRegistryEntry struct {
Name string `json:"name"`
ID string `json:"id"`
Alive bool `json:"alive"`
Unknown bool `json:"unknown,omitempty"` // true when Chrome is unreachable
}
ContextRegistryEntry is the public-facing representation used by the CLI.
func ListContexts ¶
func ListContexts(b *rod.Browser) ([]ContextRegistryEntry, error)
ListContexts returns all registry entries annotated with liveness. b may be nil — in that case all entries are reported as unknown/false.
func (ContextRegistryEntry) AliveStr ¶
func (e ContextRegistryEntry) AliveStr() string
AliveStr returns "yes", "no", or "?" depending on liveness state.
type CookieRecord ¶
type CookieRecord struct {
Name string `json:"name"`
Value string `json:"value"`
Domain string `json:"domain"`
Path string `json:"path"`
Expires float64 `json:"expires"` // CDP unix seconds, 0 = session
Secure bool `json:"secure"`
HTTPOnly bool `json:"httpOnly"`
SameSite string `json:"sameSite,omitempty"` // "Strict"|"Lax"|"None"|""
}
CookieRecord holds the subset of fields ghostchrome injects via CDP at session start. Mirrors the relevant columns of Chrome's Cookies SQLite schema, plus the decrypted plaintext value.
func ExportDecryptedCookies ¶
func ExportDecryptedCookies(cookiesPath string) ([]CookieRecord, error)
ExportDecryptedCookies opens the SQLite Cookies db at path, decrypts every v10-tagged encrypted_value via macOS Keychain, and returns the list as portable CookieRecord values. Source file is not modified.
func LoadCookiesJSON ¶
func LoadCookiesJSON(profileDir string) ([]CookieRecord, error)
LoadCookiesJSON reads the snapshot if present. Returns nil, nil when the file is absent (no import done on this profile).
type Device ¶
type Device struct {
Name string
Width int
Height int
DPR float64
UserAgent string
Mobile bool
Touch bool
}
Device describes a hardware profile used by the emulate command. Dimensions are CSS pixels; DPR is devicePixelRatio.
func DeviceByName ¶
DeviceByName looks up a Device preset by its canonical name.
func ListDevices ¶
func ListDevices() []Device
ListDevices returns a copy of the registered device presets.
type DialogResult ¶
type DialogResult struct {
Handled bool `json:"handled"`
Action string `json:"action"`
Type string `json:"type,omitempty"`
Message string `json:"message,omitempty"`
URL string `json:"url,omitempty"`
DefaultPrompt string `json:"default_prompt,omitempty"`
TimedOut bool `json:"timed_out,omitempty"`
}
DialogResult describes how a JS dialog handler completed.
func HandleNextDialog ¶
func HandleNextDialog(page *rod.Page, accept bool, promptText string, timeout time.Duration) (*DialogResult, error)
HandleNextDialog waits for the next JavaScript dialog and handles it. The timeout is propagated via context so wait() unblocks cleanly on timeout and no goroutine is leaked.
type DiffNode ¶
type DiffNode struct {
Ref string `json:"ref"`
Role string `json:"role"`
Name string `json:"name,omitempty"`
Href string `json:"href,omitempty"`
Value string `json:"value,omitempty"`
}
DiffNode is the minimal payload we return for added nodes.
type DiffStats ¶
type DiffStats struct {
AddedCount int `json:"added"`
RemovedCount int `json:"removed"`
ChangedCount int `json:"changed"`
KeptCount int `json:"kept"`
}
DiffStats summarises a diff for agent consumption.
type DropData ¶ added in v0.6.0
DropData is one text entry placed in a DataTransfer object. MIME is the DataTransfer format, for example text/plain or application/json.
type ElementBox ¶ added in v0.6.0
type ElementBox struct {
X int `json:"x"`
Y int `json:"y"`
Width int `json:"width"`
Height int `json:"height"`
}
ElementBox is a viewport-relative element rectangle in CSS pixels. It is populated only when snapshot --boxes is explicitly requested.
type ElementState ¶
type ElementState string
ElementState describes the desired element state for WaitForLocator.
const ( // StateAttached waits until the element is present in the DOM. StateAttached ElementState = "attached" // StateVisible waits until the element is visible (not display:none, not hidden). StateVisible ElementState = "visible" // StateHidden waits until the element is hidden or removed. StateHidden ElementState = "hidden" // StateEnabled waits until the element is not disabled. StateEnabled ElementState = "enabled" // StateStable waits until the element's bounding box stops moving for 100ms. StateStable ElementState = "stable" )
func ParseElementState ¶
func ParseElementState(s string) (ElementState, error)
ParseElementState validates and normalises the string form of a state. Empty string defaults to StateAttached.
type EmulationState ¶
type EmulationState struct {
Device string `json:"device,omitempty"`
Width int `json:"width,omitempty"`
Height int `json:"height,omitempty"`
DPR float64 `json:"dpr,omitempty"`
Mobile bool `json:"mobile,omitempty"`
Touch bool `json:"touch,omitempty"`
UserAgent string `json:"user_agent,omitempty"`
ColorScheme string `json:"color_scheme,omitempty"`
Timezone string `json:"timezone,omitempty"`
}
EmulationState is the emulation profile of a managed session.
CDP emulation overrides (device metrics, touch, UA, color-scheme, timezone) live in the DevTools session, not in the page: Chrome drops them the moment the client detaches. With the transparent daemon, every CLI invocation is a new short-lived session against a long-lived Chrome, so a viewport set by one command was gone by the next one and the page snapped back to the real window size. Persisting the profile here lets the next command replay it on attach.
func EmulationFromDevice ¶
func EmulationFromDevice(d Device) EmulationState
EmulationFromDevice converts a preset into the persistable profile that ApplyDevice just installed on the page.
func (EmulationState) Empty ¶
func (s EmulationState) Empty() bool
Empty reports whether the profile carries nothing to replay.
func (EmulationState) Summary ¶
func (s EmulationState) Summary() string
Summary renders the profile as a single compact line for CLI feedback.
type ErrorCollector ¶
type ErrorCollector struct {
// contains filtered or unexported fields
}
ErrorCollector collects console-side errors from a page via CDP events.
func NewErrorCollector ¶
func NewErrorCollector(page *rod.Page) *ErrorCollector
NewErrorCollector creates a collector and starts listening on the page. It hooks into RuntimeConsoleAPICalled, RuntimeExceptionThrown, and LogEntryAdded. The Log domain carries browser-side messages (CORS, mixed content, CSP violations, deprecation, network ERR_*, cookie warnings) that the Runtime domain does NOT surface — they show up in DevTools Console but go through a different CDP channel. The caller must call Close() to detach the listeners.
func (*ErrorCollector) Close ¶
func (c *ErrorCollector) Close()
Close detaches the error listeners and waits for the dispatch goroutine to drain any in-flight events before returning, so callers that snapshot just before Close see a consistent view.
func (*ErrorCollector) Errors ¶
func (c *ErrorCollector) Errors() []ErrorEntry
Errors returns all collected errors (snapshot).
type ErrorEntry ¶
type ErrorEntry struct {
Type string `json:"type"` // "console" or "network"
Level string `json:"level"` // "error", "warning", "4xx", "5xx"
Message string `json:"message"` // error message or URL
Source string `json:"source"` // file:line for console, URL for network
Status int `json:"status,omitempty"` // HTTP status for network errors
Method string `json:"method,omitempty"` // HTTP method for network
TimeMs int64 `json:"time_ms"` // timestamp relative to collector start
}
ErrorEntry represents a single console or network error.
type ExtractLevel ¶
type ExtractLevel string
ExtractLevel controls how much of the accessibility tree is returned.
const ( LevelSkeleton ExtractLevel = "skeleton" LevelContent ExtractLevel = "content" LevelFull ExtractLevel = "full" )
type ExtractedNode ¶
type ExtractedNode struct {
Ref string `json:"ref,omitempty"`
Role string `json:"role"`
Name string `json:"name,omitempty"`
Value string `json:"value,omitempty"`
Level int `json:"level,omitempty"`
Href string `json:"href,omitempty"`
Type string `json:"type,omitempty"`
Checked *bool `json:"checked,omitempty"`
Disabled bool `json:"disabled,omitempty"`
Box *ElementBox `json:"box,omitempty"`
BackendNodeID proto.DOMBackendNodeID `json:"-"`
Children []ExtractedNode `json:"children,omitempty"`
}
ExtractedNode represents a filtered accessibility node.
type ExtractionResult ¶
type ExtractionResult struct {
Nodes []ExtractedNode `json:"nodes"`
Refs map[string]ExtractedNode `json:"refs"`
Stats ExtractionStats `json:"stats"`
// SSRPayloads is populated as a fallback when the accessibility tree
// comes back empty or fails to load — e.g. an SSR/hydration-driven page
// (Next.js, Nuxt, ...) still mid-hydration behind an unresolved bot
// challenge. See ssrFallbackPayloads. Only populated when the caller
// opts in (includeSSR) — these payloads (__NEXT_DATA__, __APOLLO_STATE__,
// RSC chunks, ...) can carry tokens/PII on an authenticated page, so they
// must not be exposed to the LLM by default.
SSRPayloads []SSRPayload `json:"ssr_payloads,omitempty"`
}
ExtractionResult holds the extraction output.
func Extract ¶
func Extract(page *rod.Page, level ExtractLevel, selector string, includeSSR bool) (*ExtractionResult, error)
Extract retrieves the accessibility tree from the page and filters it. The CDP call uses its own 30 s timeout so a slow navigation doesn't eat into the extraction budget. includeSSR controls whether the SSR-fallback payloads (see ExtractionResult.SSRPayloads) are returned; pass false unless the caller explicitly wants them exposed.
func ExtractWithTimeout ¶
func ExtractWithTimeout(page *rod.Page, level ExtractLevel, selector string, timeout time.Duration, includeSSR bool) (*ExtractionResult, error)
ExtractWithTimeout is like Extract but accepts an explicit timeout for the CDP AccessibilityGetFullAXTree call. Use 0 to inherit the page's context deadline (previous behavior).
func ExtractionForRef ¶
func ExtractionForRef(result *ExtractionResult, ref string) (*ExtractionResult, bool)
ExtractionForRef returns a single-root extraction result for ref.
func LimitExtractionDepth ¶
func LimitExtractionDepth(result *ExtractionResult, maxDepth int) *ExtractionResult
LimitExtractionDepth returns a copy of result whose node children are cut after maxDepth. A negative maxDepth returns result unchanged; 0 keeps only root nodes.
func (ExtractionResult) MarshalJSON ¶
func (r ExtractionResult) MarshalJSON() ([]byte, error)
MarshalJSON serializes the extraction result for the wire: the JSONL `agent` protocol (what the TS/Python SDKs speak), `extract --json`, and the MCP surface. In memory every entry in Refs carries the interactive node's full Children subtree — ExtractionForRef relies on it to scope output to a single ref — but that subtree is already present in Nodes, so serializing it again for every interactive element duplicated a large slice of the payload the agent/SDK receives (the SDK's lightweight RefEntry type never modeled those children). Strip Children from Refs on the wire only; the in-memory struct is left untouched, so ExtractionForRef and other internal readers still see the subtree. Every interactive node already has its own top-level key in Refs, so dropping the nested subtree loses no ref.
type ExtractionStats ¶
type ExtractionStats struct {
TotalNodes int `json:"total_nodes"`
FilteredNodes int `json:"filtered_nodes"`
InteractiveCount int `json:"interactive_count"`
}
ExtractionStats provides extraction metrics.
type FastFetchOpts ¶
type FastFetchOpts struct {
UserAgent string // "" → derived from runtime.GOOS like ApplyDefaultPageProfile
AcceptLanguage string // default "fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7"
Timeout time.Duration // default 8s
ExtraHeaders map[string]string
Proxy string // optional http(s):// or socks5:// proxy URL
}
FastFetchOpts tunes the no-browser HTTP path.
type FastResult ¶
type FastResult struct {
Status int
URL string // final URL after redirects
HTML string
NextData []byte // raw JSON from <script id="__NEXT_DATA__">; nil if absent
SSRPayloads []SSRPayload
Blocked bool // anti-bot challenge detected
Reason string // human-readable explanation when Blocked or no payload extracted
Elapsed time.Duration
}
FastResult is what FastFetch returns. Blocked means "this page is gated by an anti-bot challenge — do NOT trust the body, fall back to a real browser".
NextData is the raw __NEXT_DATA__ JSON when present; SSRPayloads holds the full set of structured data islands found in the body (Next, Nuxt, Apollo, Initial-State, JSON-LD…). Modern recipes pick the first match they understand; legacy callers can keep using NextData.
func FastFetch ¶
func FastFetch(ctx context.Context, url string, opts FastFetchOpts) (*FastResult, error)
FastFetch performs a single GET with realistic browser headers and inspects the response for SSR data and anti-bot markers. It's a best-effort fast path: callers must check (Blocked || NextData == nil) and decide whether to fall back to a Chrome-driven recipe.
type HAR ¶
type HAR struct {
Log HARLog `json:"log"`
}
HAR follows the HAR 1.2 specification (W3C Web Performance Working Group). It's intentionally minimal: we only populate what NetworkEntry knows about, leaving the optional fields (headers, cookies, content text) empty so parsers treat them as "not captured" rather than "empty".
func BuildHAR ¶
func BuildHAR(entries []NetworkEntry, pageURL, pageTitle, creatorVersion string) *HAR
BuildHAR constructs a HAR from the passive NetworkEntry slice collected by requestTracker. pageURL and pageTitle name the top-level page.
type HARContent ¶
HARContent carries the payload summary (size, MIME).
type HARCreator ¶
HARCreator identifies the tool that recorded the trace.
type HAREntry ¶
type HAREntry struct {
PageRef string `json:"pageref,omitempty"`
StartedDateTime string `json:"startedDateTime"`
Time int64 `json:"time"`
Request HARRequest `json:"request"`
Response HARResponse `json:"response"`
Cache struct{} `json:"cache"`
Timings HARTimings `json:"timings"`
}
HAREntry is one network request + response.
type HARLog ¶
type HARLog struct {
Version string `json:"version"`
Creator HARCreator `json:"creator"`
Pages []HARPage `json:"pages"`
Entries []HAREntry `json:"entries"`
}
HARLog is the top-level container.
type HARPage ¶
type HARPage struct {
StartedDateTime string `json:"startedDateTime"`
ID string `json:"id"`
Title string `json:"title"`
}
HARPage groups entries by the top-level navigation that produced them.
type HARRequest ¶
type HARRequest struct {
Method string `json:"method"`
URL string `json:"url"`
HTTPVersion string `json:"httpVersion"`
Headers []string `json:"headers"`
QueryString []string `json:"queryString"`
HeadersSize int `json:"headersSize"`
BodySize int `json:"bodySize"`
}
HARRequest describes the outgoing request.
type HARResponse ¶
type HARResponse struct {
Status int `json:"status"`
StatusText string `json:"statusText"`
HTTPVersion string `json:"httpVersion"`
Headers []string `json:"headers"`
Cookies []string `json:"cookies"`
Content HARContent `json:"content"`
RedirectURL string `json:"redirectURL"`
HeadersSize int `json:"headersSize"`
BodySize int `json:"bodySize"`
}
HARResponse describes the incoming response.
type HARTimings ¶
type HARTimings struct {
Send int `json:"send"`
Wait int64 `json:"wait"`
Receive int `json:"receive"`
}
HARTimings models per-phase durations. We only know the total so we put it on "wait".
type HTTPClientOpts ¶
HTTPClientOpts configures the proxy-aware http.Client used by the no-browser commands (fastfetch, fetchapi). Empty Proxy means direct.
type ImageDiffResult ¶
type ImageDiffResult struct {
Width int `json:"width"`
Height int `json:"height"`
PixelsTotal int `json:"pixels_total"`
PixelsChanged int `json:"pixels_changed"`
DiffRatio float64 `json:"diff_ratio"`
DiffPath string `json:"diff_path,omitempty"`
Skipped bool `json:"skipped,omitempty"`
SkipReason string `json:"skip_reason,omitempty"`
}
ImageDiffResult summarises a pixel-by-pixel comparison.
func DiffImages ¶
func DiffImages(baselinePNG, currentPNG []byte, tolerance int, diffPath string) (*ImageDiffResult, error)
DiffImages compares two images pixel by pixel. When dimensions differ, the result is flagged Skipped so the caller can decide (usually: fail or use the new image as the new baseline).
If diffPath is non-empty, a PNG is written there highlighting every pixel where delta >= tolerance in red (original otherwise).
type InterceptSession ¶
type InterceptSession struct {
// contains filtered or unexported fields
}
InterceptSession owns the router lifetime. Stop() must be called to release resources.
func StartAntiBotBlocker ¶
func StartAntiBotBlocker(browser *rod.Browser, extraPatterns ...string) (*InterceptSession, error)
StartAntiBotBlocker installs a request blocker for AntiBotPatterns on the given browser. Returns the InterceptSession so the caller can Stop() it and read the Stats() to know how many requests were blocked.
extraPatterns lets callers extend the curated list (e.g. site-specific trackers known to cause issues).
func StartIntercept ¶
func StartIntercept(browser *rod.Browser, spec InterceptSpec) (*InterceptSession, error)
StartIntercept enables Fetch interception on the browser and returns an InterceptSession. The caller is responsible for Stop().
func (*InterceptSession) Stats ¶
func (s *InterceptSession) Stats() *InterceptStats
Stats returns the live counters.
func (*InterceptSession) Stop ¶
func (s *InterceptSession) Stop() error
Stop disables interception and waits for the background goroutine.
type InterceptSpec ¶
type InterceptSpec struct {
// BlockPatterns list glob URL patterns to block with
// NetworkErrorReasonBlockedByClient.
BlockPatterns []string
// FulfillPattern optionally matches requests to be answered with the
// FulfillBody payload and FulfillStatus response code. Only set one pattern.
FulfillPattern string
FulfillBody []byte
FulfillStatus int
FulfillContentType string
FulfillHeaders map[string]string
RemoveRequestHeaders []string
// Rules are pre-compiled rule-file entries. When non-empty, each incoming
// request is matched against them before falling through to FulfillPattern /
// BlockPatterns. Populated by LoadRules; callers should not build this slice
// manually.
Rules []compiledRule
}
InterceptSpec configures a request interception router.
type InterceptStats ¶
type InterceptStats struct {
Blocked int
Fulfilled int
Passed int
// contains filtered or unexported fields
}
InterceptStats are cumulative counters updated by the router goroutine.
func (*InterceptStats) Snapshot ¶
func (s *InterceptStats) Snapshot() (blocked, fulfilled, passed int)
Snapshot returns a concurrent-safe copy of the counters.
type LauncherOpts ¶
type LauncherOpts struct {
Headless bool
RemotePort int // 0 = random
// Invisible forces headful Chrome (real rendering pipeline, harder to
// fingerprint as a bot) but positions the window far off-screen so it
// stays out of sight. Overrides Headless when set.
Invisible bool
// UserDataDir is the absolute Chrome --user-data-dir path. Empty means
// ephemeral. Use ResolveProfileDir to convert a short profile name into
// the canonical path under ~/.ghostchrome/profiles/<name>.
UserDataDir string
// Proxy is the upstream proxy URL passed to Chrome via --proxy-server.
// Examples: "http://user:pass@host:port", "socks5://host:1080".
// Empty means no proxy.
Proxy string
// ProxyBypass is passed to Chrome as --proxy-bypass-list when Proxy is set.
// It uses Chromium's bypass list syntax, matching Playwright's proxy.bypass.
ProxyBypass string
// ExecutablePath forces a specific Chrome/Chromium binary. It maps
// Playwright's browser.launchOptions.executablePath and overrides
// ghostchrome's system-Chrome preference.
ExecutablePath string
// Args are extra Chromium command-line switches, normalized as --flag or
// --flag=value. They map Playwright's browser.launchOptions.args.
Args []string
// Extensions is a list of absolute paths to unpacked Chrome extensions
// (each path must contain a manifest.json at its root). When non-empty,
// Chrome is launched with --load-extension and --disable-extensions-except
// so only the listed extensions are active. Note: requires HeadlessNew
// (the modern headless mode); old --headless ignores extensions.
Extensions []string
// SystemChrome forces the launcher to use the system's Google Chrome
// binary (com.google.Chrome bundle) instead of rod's bundled Chromium.
// Required when reusing a profile imported from the user's real Chrome
// — only com.google.Chrome can decrypt cookies sealed by macOS Keychain
// "Chrome Safe Storage". Auto-detected via the .ghostchrome-system-chrome
// marker file in the profile dir.
SystemChrome bool
}
LauncherOpts configures a stealth-flavored Chrome launcher.
type Locator ¶
type Locator struct {
// Role matches the ARIA role (see engine.interactiveRoles, engine.skeletonRoles).
// Accepts canonical role strings or their one-letter agent abbreviation
// ("b"=button, "a"=link, "t"=textbox, etc.).
Role string
// Name matches the accessible name. Comparison is case-insensitive and uses
// substring matching, so "Sign in" matches "Sign in now".
Name string
// Label matches the accessible label derived from <label for=...> or
// aria-labelledby. In Chromium's a11y tree, that's exposed as the name of
// a textbox / combobox — so this is equivalent to Name for inputs.
// Included as a separate field for ergonomic CLI flags (--by-label).
Label string
// Text matches via page-wide text search — like Playwright's getByText.
// When set, Role is ignored.
Text string
}
Locator describes a semantic element match. At least one field must be set. When multiple fields are set, the match is conjunctive (all must hold).
type LocatorMatchCountError ¶ added in v0.6.0
LocatorMatchCountError identifies a strict semantic-locator cardinality failure. Waiters retry zero matches, but reject ambiguity immediately.
func (*LocatorMatchCountError) Error ¶ added in v0.6.0
func (e *LocatorMatchCountError) Error() string
type MultiCollectResult ¶
type MultiCollectResult struct {
TotalItems int `json:"total_items"`
TotalTimeMs int64 `json:"total_time_ms"`
Sites []SiteResult `json:"sites"`
}
MultiCollectResult holds results from parallel multi-URL collection.
func MultiCollect ¶
func MultiCollect(browser *rod.Browser, urls []string, limit int, stealth bool, maxParallel int) *MultiCollectResult
MultiCollect scrapes multiple URLs in parallel using separate browser tabs. Each URL gets its own tab, navigates, collects, and closes. maxParallel caps the number of concurrent tabs; <= 0 falls back to 5.
type NetworkEntry ¶
type NetworkEntry struct {
Method string `json:"method,omitempty"`
URL string `json:"url"`
Status int `json:"status"`
Size int `json:"size_bytes"`
TimeMs int64 `json:"time_ms"`
MimeType string `json:"mime_type,omitempty"`
Error string `json:"error,omitempty"`
}
NetworkEntry represents a captured network request.
type Observation ¶
type Observation struct {
// ConsoleErrors holds runtime errors or uncaught exceptions observed during
// the op (kind=error from the Observer).
ConsoleErrors []ObserverEvent `json:"console_errors,omitempty"`
// NetworkFailed holds network requests that failed (4xx/5xx or transport
// error) during the op.
NetworkFailed []ObserverEvent `json:"network_failed,omitempty"`
// A11yDiff is the compact text diff of the a11y tree between before and
// after the op (FormatDiff output). Empty when there is no change.
A11yDiff string `json:"a11y_diff,omitempty"`
// Dialog is the text of a pending JS dialog detected on the page ("alert
// open: <message>"). Empty when no dialog is open.
Dialog string `json:"dialog,omitempty"`
// CaptchaHint is set when a bot-challenge page is detected
// ("datadome", "cloudflare", or a generic "captcha").
CaptchaHint string `json:"captcha_hint,omitempty"`
// URL is the current page URL at the time the observation was built.
URL string `json:"url,omitempty"`
}
Observation is the structured feedback packet returned after each agent op. All fields are omitempty so an empty observation serialises to `{}`.
func BuildObservation ¶
func BuildObservation(page *rod.Page, before, after *PageSnapshot, events []ObserverEvent) Observation
BuildObservation constructs an Observation from the observer events that occurred during a single op, the a11y snapshots taken before and after, and the current page state.
before may be nil (first op, no prior snapshot). after may be nil if the op failed before extraction. events is the slice from Observer.Drain().
type Observer ¶
type Observer struct {
// contains filtered or unexported fields
}
Observer multiplexes CDP Network + Runtime + Page events into a unified channel.
func NewObserver ¶
func NewObserver(page *rod.Page, opts ObserverOpts) *Observer
NewObserver creates an Observer for page. Call Start to begin listening.
func (*Observer) Drain ¶
func (o *Observer) Drain(afterMs int64) []ObserverEvent
Drain returns all events whose TS >= afterMs without removing them.
func (*Observer) Events ¶
func (o *Observer) Events() <-chan ObserverEvent
Events returns the read-only event channel.
func (*Observer) Stats ¶
func (o *Observer) Stats() ObserverStats
Stats returns a snapshot of event counters.
type ObserverEvent ¶
type ObserverEvent struct {
TS int64 `json:"ts"` // unix ms
Kind ObserverKind `json:"kind"`
Method string `json:"method,omitempty"`
URL string `json:"url,omitempty"`
Status int `json:"status,omitempty"`
MimeType string `json:"mime_type,omitempty"`
Type string `json:"type,omitempty"`
RequestID string `json:"request_id,omitempty"`
Body string `json:"body,omitempty"`
BodyBase64 bool `json:"body_base64,omitempty"`
BodyError string `json:"body_error,omitempty"`
Size int64 `json:"size,omitempty"`
DurationMs int64 `json:"duration_ms,omitempty"`
Failed string `json:"failed,omitempty"`
Level string `json:"level,omitempty"`
Text string `json:"text,omitempty"`
Source string `json:"source,omitempty"`
Event string `json:"event,omitempty"`
Frame string `json:"frame,omitempty"`
ReqHeaders map[string]string `json:"request_headers,omitempty"`
ResHeaders map[string]string `json:"response_headers,omitempty"`
PostData string `json:"post_data,omitempty"`
}
ObserverEvent is one emitted CDP event in a unified format.
type ObserverFilters ¶
type ObserverFilters struct {
// NetTypes filters by network resource type (e.g. "xhr", "fetch", "document").
// Empty means accept all.
NetTypes []string
// NetURLRegex filters net events by URL. Nil means accept all.
NetURLRegex *regexp.Regexp
// ConsoleLevels filters console events (e.g. "error", "warning", "info").
// Empty means accept all.
ConsoleLevels []string
// Kinds limits event kinds emitted. Empty means accept all.
Kinds []ObserverKind
}
ObserverFilters selectively narrows which events are emitted.
type ObserverKind ¶
type ObserverKind string
ObserverKind classifies an ObserverEvent.
const ( KindNet ObserverKind = "net" KindConsole ObserverKind = "console" KindError ObserverKind = "error" KindPage ObserverKind = "page" )
type ObserverOpts ¶
type ObserverOpts struct {
Filters ObserverFilters
MaxEvents int // 0 = unlimited
Duration time.Duration // 0 = unlimited
BufferSize int // channel buffer; default 256
}
ObserverOpts configures an Observer.
type ObserverStats ¶
type ObserverStats struct {
Net int
Console int
Error int
Page int
Total int
Dropped int // events discarded due to MaxEvents or channel full
}
ObserverStats holds counters for each kind.
type PageInfo ¶
type PageInfo struct {
URL string `json:"url"`
Title string `json:"title"`
Status int `json:"status"`
TimeMs int64 `json:"time_ms"`
}
PageInfo holds the result of a navigation.
type PageSnapshot ¶
type PageSnapshot struct {
TargetID string `json:"target_id"`
URL string `json:"url,omitempty"`
Title string `json:"title,omitempty"`
Refs map[string]RefSnapshot `json:"refs,omitempty"`
// CachedExtraction is the last ExtractionResult for this page, persisted so
// subsequent commands can skip the expensive CDP AccessibilityGetFullAXTree
// call when the URL has not changed.
CachedExtraction *ExtractionResult `json:"cached_extraction,omitempty"`
}
PageSnapshot stores the last known interactive refs for a page target.
func BuildSnapshot ¶
func BuildSnapshot(page *rod.Page, result *ExtractionResult) (*PageSnapshot, error)
BuildSnapshot creates an in-memory ref snapshot from an extraction result.
type PersistentSessionObserver ¶ added in v0.6.0
type PersistentSessionObserver struct {
// contains filtered or unexported fields
}
PersistentSessionObserver keeps CDP observation alive in the transparent daemon, including the idle time between short CLI processes.
func StartPersistentSessionObserver ¶ added in v0.6.0
func StartPersistentSessionObserver(connectURL string) (*PersistentSessionObserver, error)
StartPersistentSessionObserver connects a second CDP client to the daemon Chrome and appends bounded network/console events to its session log.
func (*PersistentSessionObserver) Stop ¶ added in v0.6.0
func (p *PersistentSessionObserver) Stop()
Stop detaches observers. Chrome itself remains owned by serve and is not closed through this secondary CDP connection.
type PlaywrightLogState ¶
type PlaywrightLogState struct {
Console []ObserverEvent `json:"console,omitempty"`
Network []CapturedEntry `json:"network,omitempty"`
}
PlaywrightLogState stores bounded command-observation buffers for Playwright CLI-compatible console/network inspection.
type PreviewResult ¶
type PreviewResult struct {
PageInfo *PageInfo `json:"page"`
Errors []ErrorEntry `json:"errors"`
Network []NetworkEntry `json:"network"`
DOM *ExtractionResult `json:"dom"`
Summary PreviewSummary `json:"summary"`
}
PreviewResult is the all-in-one dev report for a page.
type PreviewSummary ¶
type PreviewSummary struct {
TotalRequests int `json:"total_requests"`
FailedRequests int `json:"failed_requests"`
ErrorCount int `json:"error_count"`
WarningCount int `json:"warning_count"`
InteractiveCount int `json:"interactive_count"`
}
PreviewSummary provides quick stats.
type ProfileGCCandidate ¶
type ProfileGCCandidate struct {
Name string `json:"name"`
Bytes int64 `json:"bytes"`
Modified time.Time `json:"modified"`
}
ProfileGCCandidate is an orphan profile eligible for reclamation.
func GCProfiles ¶
func GCProfiles(ttl time.Duration, dryRun bool) ([]ProfileGCCandidate, error)
GCProfiles finds — and, unless dryRun, deletes — orphan profile directories that are safe to reclaim: never the implicit "default" daemon profile, never a profile backing a currently-live session, and only those idle for at least ttl (no file modified within the window). The idle gate protects persistent login profiles that are still in active rotation even when no session is up right now. Callers should surface the returned candidates before deleting (the CLI defaults to a dry run) so a login profile is never removed silently.
type ProfileInfo ¶
type ProfileInfo struct {
Name string `json:"name"`
Path string `json:"path"`
Bytes int64 `json:"bytes"`
}
ProfileInfo describes a persistent Chrome profile on disk (~/.ghostchrome/profiles/<name>).
func ListProfiles ¶
func ListProfiles() ([]ProfileInfo, error)
ListProfiles returns every persistent profile with its on-disk size.
type ProxyPool ¶
type ProxyPool struct {
// contains filtered or unexported fields
}
ProxyPool hands out proxy URLs round-robin across sessions. Residential / mobile proxies are usually sold as a pool; rotating the egress IP is the #1 lever against IP-reputation anti-bot layers (DataDome & co.), which a single static --proxy cannot provide. Thread-safe.
func NewProxyPool ¶
NewProxyPool builds a pool from already-parsed entries. A nil/empty list yields an empty pool whose Next() returns "".
type ReactComponent ¶
type ReactComponent struct {
Name string `json:"name"`
Type string `json:"type"`
Key string `json:"key,omitempty"`
Props json.RawMessage `json:"props,omitempty"`
State json.RawMessage `json:"state,omitempty"`
Children []ReactComponent `json:"children,omitempty"`
}
ReactComponent represents a React component in the fiber tree.
type Recorder ¶
type Recorder struct {
// contains filtered or unexported fields
}
Recorder injects a JS listener into the page, coalesces typing, and emits JSONL ops to w. It uses Runtime.addBinding so the JS → Go channel is clean (no console-log pollution).
Call Start() once then either Wait() (blocks until done) or Stop().
func NewRecorder ¶
NewRecorder creates a recorder but does not start it.
func (*Recorder) Done ¶
func (r *Recorder) Done() <-chan struct{}
Done returns a channel closed when the recorder stops.
type RecorderOp ¶
RecorderOp is a single user-action op, ready to be written as JSONL. The schema matches the agentRequest format consumed by `ghostchrome agent`.
type RecorderOpts ¶
RecorderOpts configures a Recorder session.
type RecoveryContext ¶
type RecoveryContext struct {
// Page is the active Rod page.
Page *rod.Page
// Err is the error returned by the original op.
Err error
// OpName is the JSONL op name for logging (e.g. "click", "navigate").
OpName string
}
RecoveryContext carries the inputs available to a RecoveryHook.
type RecoveryHook ¶
type RecoveryHook func(ctx RecoveryContext) (retry bool, err error)
RecoveryHook is a function that inspects the failure context and optionally performs a repair action.
Return values:
- retry=true: the hook resolved the issue; the caller should retry the op.
- retry=false, err=nil: the hook ran but did not fix anything; try next hook.
- retry=false, err=non-nil: the hook itself failed with a new error; abort.
func DefaultRecoveryHooks ¶
func DefaultRecoveryHooks() []RecoveryHook
DefaultRecoveryHooks returns the standard set of hooks in priority order:
- RecoverDialogAccept — dialogs block everything
- RecoverBotChallenge — captcha/CF interstitial
- RecoverNetworkSettle — transient timeout
- RecoverStaleRef — stale ref is last (never silently remaps)
type RefSnapshot ¶
type RefSnapshot struct {
BackendNodeID proto.DOMBackendNodeID `json:"backend_node_id"`
Role string `json:"role,omitempty"`
Name string `json:"name,omitempty"`
}
RefSnapshot stores a stable backend node mapping for a single ref.
type RenderProfile ¶
type RenderProfile struct {
// Agent is true when the output is being consumed by an LLM agent runner
// (Claude Code, Cursor, Aider, etc.) rather than a human terminal.
Agent bool
// Format is "text" or "json".
Format string
// MaxLabelLen truncates node names / values to this length in agent mode.
// 0 means no truncation.
MaxLabelLen int
// AbbrevRoles uses 1-2 character role abbreviations (b/a/t/c/s/r/m/x/h).
AbbrevRoles bool
// DropEmptyStats omits "[errors] 0 ..." / "[network] ... 0 failed" headers
// when counts are zero.
DropEmptyStats bool
// ContentBoundary wraps page-derived text (node names / values) with sentinel
// markers so an LLM consuming the snapshot can distinguish tool output from
// untrusted page content (prompt-injection defense). Default false = opt-in only.
// Markers used: ⟦page⟧ … ⟦/page⟧
ContentBoundary bool
}
RenderProfile controls how output is rendered for the calling environment. It is resolved once per CLI invocation (see ResolveProfile) and then threaded into formatters.
func ProfileAgent ¶
func ProfileAgent(format string) RenderProfile
ProfileAgent returns the compact agent-optimised profile.
func ProfileHuman ¶
func ProfileHuman(format string) RenderProfile
ProfileHuman returns the default human-friendly profile.
func ResolveProfile ¶
func ResolveProfile(explicit, format string) RenderProfile
ResolveProfile picks a RenderProfile from an explicit flag ("auto", "human", "agent") with environment-variable fallback for "auto".
type RuleMatchType ¶
type RuleMatchType string
RuleMatchType controls how the match field is interpreted.
const ( RuleMatchGlob RuleMatchType = "glob" RuleMatchRegex RuleMatchType = "regex" RuleMatchExact RuleMatchType = "exact" )
type RuleSpec ¶
type RuleSpec struct {
Match string `json:"match"`
MatchType RuleMatchType `json:"matchType"`
Method string `json:"method"`
Status int `json:"status"`
ContentType string `json:"contentType"`
Headers map[string]string `json:"headers"`
Body string `json:"body"`
BodyFile string `json:"bodyFile"`
}
RuleSpec is the JSON schema for one entry in the rules file.
type RulesFile ¶
type RulesFile struct {
Rules []RuleSpec `json:"rules"`
}
RulesFile is the top-level JSON structure.
type SSRPayload ¶
type SSRPayload struct {
Source SSRSource `json:"source"`
Data json.RawMessage `json:"data"`
IsJSON bool `json:"is_json"`
// Type is set for JSON-LD payloads to surface schema.org @type
// without forcing the caller to re-parse.
Type string `json:"type,omitempty"`
}
SSRPayload is one structured data island found in HTML. Data is the raw payload as it appeared in the page — JSON for the *Data sources and JSON-LD, plain JS expression for *State / Nuxt 2. IsJSON tells the caller whether they can json.Unmarshal it directly.
func ExtractRSCPayloads ¶
func ExtractRSCPayloads(html string) []SSRPayload
ExtractRSCPayloads decodes Next.js App Router RSC chunks and returns one SSRPayload per logical entry (`<id>:<value>`). Values that parse as JSON (object, array, string) are surfaced with IsJSON=true; module refs and element trees are returned as raw strings (callers that care can run them through V8 — but the JSON ones cover most data needs).
Stream format reference:
0:["$","html",null,{...}] RSC element tree
1:I[123,[...],"Comp"] module / chunk reference
2:[...listings JSON...] plain JSON data island
3:T82a,Lorem ipsum… text token
We keep all of them; downstream extractors filter by id or by "starts with `[` / `{`" depending on what they need.
func ExtractSSRPayloads ¶
func ExtractSSRPayloads(html string) []SSRPayload
ExtractSSRPayloads finds every supported SSR data island in the HTML and returns them in order of appearance. Sites that ship multiple frameworks (e.g. Next + Apollo, or several JSON-LD blocks) get one entry per island.
Always-safe: returns nil on absence rather than an error. Callers decide what to do with the empty list (often: fall back to Chrome).
type SSRSource ¶
type SSRSource string
SSRSource classifies the origin of an SSR data payload found in a page's HTML. Different frameworks expose their state in different shapes; we surface the source so downstream tooling can pick a parser per format.
const ( SourceNextData SSRSource = "next" // <script id="__NEXT_DATA__" type="application/json"> SourceNuxtData SSRSource = "nuxt" // <script id="__NUXT_DATA__" type="application/json"> (Nuxt 3) SourceNuxtJS SSRSource = "nuxt-js" // window.__NUXT__=... (Nuxt 2; raw JS, not JSON) SourceApolloState SSRSource = "apollo" // window.__APOLLO_STATE__=... SourceInitialState SSRSource = "initial-state" // window.__INITIAL_STATE__=... SourcePreloaded SSRSource = "preloaded" // window.__PRELOADED_STATE__=... SourceReduxState SSRSource = "redux" // window.__REDUX_STATE__=... SourceJSONLD SSRSource = "jsonld" // <script type="application/ld+json"> SourceRSC SSRSource = "rsc" // self.__next_f.push([1, "<chunks>"]) (Next.js App Router) )
type ScreenRecorder ¶
type ScreenRecorder struct {
// contains filtered or unexported fields
}
func NewScreenRecorder ¶
func NewScreenRecorder(page *rod.Page, opts ScreenRecorderOpts) *ScreenRecorder
func (*ScreenRecorder) FrameCount ¶
func (r *ScreenRecorder) FrameCount() int64
func (*ScreenRecorder) OutputDir ¶
func (r *ScreenRecorder) OutputDir() string
func (*ScreenRecorder) Start ¶
func (r *ScreenRecorder) Start() error
func (*ScreenRecorder) Stop ¶
func (r *ScreenRecorder) Stop() int64
type ScreenRecorderOpts ¶
type SessionEntry ¶
type SessionEntry struct {
Name string `json:"name"`
Port int `json:"port"`
PID int `json:"pid"`
WSURL string `json:"ws_url"`
Profile string `json:"profile"`
LaunchedAt string `json:"launched_at"`
}
SessionEntry is one named, auto-managed Chrome in the session registry. A session is a long-lived `serve` process bound to a disk profile of the same name (so cookies persist), reused across CLI invocations.
func AttachSession ¶
func AttachSession(name string, wsURL string) (SessionEntry, error)
AttachSession registers an existing CDP endpoint as a named session. It does not spawn or own the browser process; StopSession removes the registry entry but will not terminate an external browser because PID/Port are zero.
type SessionRegistryEntry ¶
type SessionRegistryEntry struct {
Name string `json:"name"`
Port int `json:"port"`
PID int `json:"pid"`
WSURL string `json:"ws_url"`
Profile string `json:"profile"`
LaunchedAt string `json:"launched_at,omitempty"`
Alive bool `json:"alive"`
}
SessionRegistryEntry is the public-facing representation used by the CLI.
func ListSessions ¶
func ListSessions() ([]SessionRegistryEntry, error)
ListSessions returns every registry entry annotated with current liveness.
func ResolveSession ¶
func ResolveSession(name string) (SessionRegistryEntry, error)
ResolveSession returns the live browser WebSocket URL for an existing registered session. It never spawns a new browser.
func (SessionRegistryEntry) AliveStr ¶
func (e SessionRegistryEntry) AliveStr() string
AliveStr returns "yes" or "no".
type SessionSpawnOpts ¶
type SessionSpawnOpts struct {
Headless bool
Stealth bool
Proxy string
ProxyBypass string
ExecutablePath string
ConfigPath string
}
SessionSpawnOpts carries the global flags propagated to a spawned serve.
type SiteResult ¶
type SiteResult struct {
URL string `json:"url"`
Items []CollectedItem `json:"items"`
Count int `json:"count"`
TimeMs int64 `json:"time_ms"`
Error string `json:"error,omitempty"`
}
SiteResult holds the collect result for a single URL in a multi-collect.
type SnapshotDiff ¶
type SnapshotDiff struct {
Unchanged bool `json:"unchanged,omitempty"`
Added []DiffNode `json:"added,omitempty"`
Removed []string `json:"removed,omitempty"`
Changed map[string]DiffEntry `json:"changed,omitempty"`
Stats DiffStats `json:"stats"`
}
SnapshotDiff reports the changes between two ref maps of a page. All fields are optional in JSON output so an unchanged page serialises to `{"unchanged":true}`.
func DiffRefs ¶
func DiffRefs(prev, curr map[string]RefSnapshot) SnapshotDiff
DiffRefs compares two ref maps (typically the persisted PageSnapshot.Refs). Refs are reassigned in document order by the extractor, so a key match indicates the same logical node slot. A role or name change on the same key counts as "changed"; disappearing or new keys count as removed/added.
type StorageCookie ¶
type StorageCookie struct {
Name string `json:"name"`
Value string `json:"value"`
Domain string `json:"domain"`
Path string `json:"path"`
Expires float64 `json:"expires,omitempty"`
HTTPOnly bool `json:"httpOnly,omitempty"`
Secure bool `json:"secure,omitempty"`
SameSite string `json:"sameSite,omitempty"`
}
StorageCookie uses the Playwright-compatible field names (sameSite as string, expires as float64 seconds-since-epoch).
type StorageKeyValue ¶
StorageKeyValue is a single localStorage entry.
type StorageOrigin ¶
type StorageOrigin struct {
Origin string `json:"origin"`
LocalStorage []StorageKeyValue `json:"localStorage"`
}
StorageOrigin groups localStorage entries by origin. sessionStorage is NOT persisted: it's per-tab and generally not replayable.
type StorageState ¶
type StorageState struct {
Cookies []StorageCookie `json:"cookies"`
Origins []StorageOrigin `json:"origins"`
}
StorageState mirrors the Playwright storageState JSON shape so a state file produced by ghostchrome can be loaded by Playwright (and vice versa, within reasonable limits).
func SaveStorageState ¶
SaveStorageState captures cookies (browser-wide) and localStorage for the origin of the current page. Callers can concatenate multiple SaveStorageState runs if they need multiple origins.
type TabInfo ¶
type TabInfo struct {
Index int `json:"index"`
URL string `json:"url"`
Title string `json:"title"`
TargetID string `json:"target_id,omitempty"`
Active bool `json:"active,omitempty"`
}
TabInfo holds metadata about a browser tab.
type TraceEntry ¶
type TraceEntry struct {
TS int64 `json:"ts"`
Op string `json:"op"`
Args map[string]any `json:"args,omitempty"`
OK bool `json:"ok"`
DurationMs int64 `json:"duration_ms"`
Summary string `json:"summary,omitempty"`
Error string `json:"error,omitempty"`
Shot string `json:"shot,omitempty"`
}
TraceEntry is one line of a ghostchrome MCP session trace (JSONL).
type VideoChapter ¶
type VideoChapter struct {
Title string `json:"title"`
Description string `json:"description,omitempty"`
DurationMs int `json:"duration_ms,omitempty"`
AtMs int64 `json:"at_ms"`
CreatedAt string `json:"created_at"`
}
VideoChapter is one requested video chapter marker.
type VideoRuntimeOpts ¶ added in v0.6.0
type VideoRuntimeOpts struct {
ConnectURL string
TargetID string
FramesDir string
StatusPath string
}
VideoRuntimeOpts describes the detached recorder process attached to a long-lived Chrome. The process, rather than the short-lived CLI command, owns the Page.screencast subscription.
type VideoRuntimeStatus ¶ added in v0.6.0
type VideoRuntimeStatus struct {
State string `json:"state"`
Frames int64 `json:"frames_captured"`
StartedAt string `json:"started_at,omitempty"`
UpdatedAt string `json:"updated_at,omitempty"`
StoppedAt string `json:"stopped_at,omitempty"`
Error string `json:"error,omitempty"`
}
VideoRuntimeStatus is written atomically so video-start and video-stop can prove the detached recorder's state across CLI processes.
func ReadVideoRuntimeStatus ¶ added in v0.6.0
func ReadVideoRuntimeStatus(path string) (VideoRuntimeStatus, error)
func RequestVideoRuntimeStop ¶ added in v0.6.0
func RequestVideoRuntimeStop(statusPath string, timeout time.Duration) (VideoRuntimeStatus, error)
RequestVideoRuntimeStop asks the detached recorder to finish its current frame, stop CDP screencast, and publish its final count.
func WaitForVideoRuntime ¶ added in v0.6.0
func WaitForVideoRuntime(path, want string, timeout time.Duration) (VideoRuntimeStatus, error)
type VideoState ¶
type VideoState struct {
Active bool `json:"active,omitempty"`
StartedAt string `json:"started_at,omitempty"`
Filename string `json:"filename,omitempty"`
FramesDir string `json:"frames_dir,omitempty"`
RuntimeStatus string `json:"runtime_status,omitempty"`
Size string `json:"size,omitempty"`
Auto bool `json:"auto,omitempty"`
Source string `json:"source,omitempty"`
Chapters []VideoChapter `json:"chapters,omitempty"`
}
VideoState tracks a durable CDP screencast recording. The artifact is a sequence of JPEG frames, never a WebM file.
Source Files
¶
- annotate.go
- antibot_blocker.go
- browser.go
- capture.go
- clipboard.go
- collector.go
- context_registry.go
- cookies.go
- cookies_decrypt.go
- cookies_inject.go
- discover.go
- drag.go
- drop.go
- emulate.go
- errors.go
- evasion.go
- extractor.go
- extractor_domfallback.go
- fastfetch.go
- fetchapi.go
- format.go
- har.go
- highlight.go
- httpclient.go
- human.go
- imagediff.go
- initscript.go
- interactor.go
- intercept.go
- intercept_rules.go
- locator.go
- locator_wait.go
- mouse.go
- navigator.go
- network_tracker.go
- observation.go
- observer.go
- page_profile.go
- permissions.go
- persistent_observer.go
- persistent_observer_lock_unix.go
- persistent_observer_replace_unix.go
- preview.go
- prewarm.go
- profile.go
- profile_lock.go
- profiles.go
- proxy_auth.go
- proxypool.go
- react.go
- recorder.go
- recovery.go
- rsc_extract.go
- screenrecord.go
- service_workers.go
- session_registry.go
- session_spawn_unix.go
- session_state.go
- snapshot_diff.go
- ssr_extract.go
- stealth.go
- storage.go
- trace.go
- video_runtime.go
- wait.go
Directories
¶
| Path | Synopsis |
|---|---|
|
Package ai implements an autonomous LLM-driven browser agent that drives the existing ghostchrome agent ops.
|
Package ai implements an autonomous LLM-driven browser agent that drives the existing ghostchrome agent ops. |
|
Package dashboard provides a live browser viewport stream over WebSocket.
|
Package dashboard provides a live browser viewport stream over WebSocket. |
|
Package mcp exposes ghostchrome as a Model Context Protocol server so that LLM agents (Claude Code, Codex, Cursor, ...) can drive the browser via stdio JSON-RPC instead of forking the CLI per call.
|
Package mcp exposes ghostchrome as a Model Context Protocol server so that LLM agents (Claude Code, Codex, Cursor, ...) can drive the browser via stdio JSON-RPC instead of forking the CLI per call. |
|
Package provider defines the interface for connecting to a Chrome instance.
|
Package provider defines the interface for connecting to a Chrome instance. |
|
Package sites provides generic, site-agnostic discovery and replay helpers.
|
Package sites provides generic, site-agnostic discovery and replay helpers. |