Documentation
¶
Overview ¶
Package browserlaunch launches a system-installed Chromium-based browser (Chrome / Edge / Brave / Chromium) with a CDP remote-debugging endpoint and exposes the resulting websocket URL so a driver — the Python browser-use sidecar, or chromedp elsewhere — can attach to the very same browser instead of each driver spawning its own.
The design borrows the CDP launch engineering from agent-browser (vercel-labs) and OpenWork's eval host launcher, adapted to Go:
- The PORT is allocated by the Go host via net.Listen("127.0.0.1:0") and handed to Chrome as --remote-debugging-port. This avoids the TOCTOU race in OpenWork's fixed-list probing ([9223..9227] may all be free at probe time but taken by bind time).
- A spawn-integrity check asserts the port Chrome actually bound (read from its DevToolsActivePort file) matches the one we asked for, so a collision never silently attaches to the wrong instance.
- Readiness is a three-way race: CDP /json/list responds vs. the process exits vs. the process is no longer alive — a browser that crashes before CDP is ready never hangs the caller.
Unlike builtin browser_open (which owns the chromedp allocator internally), this package launches the browser as a raw subprocess and exposes only the wsURL. It does NOT drive the browser itself; that is the sidecar's job.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrNoBrowser = errors.New("no Chromium-based browser found")
ErrNoBrowser is returned when no Chromium-based browser can be found.
Functions ¶
This section is empty.
Types ¶
type CDPVersionInfo ¶
type CDPVersionInfo struct {
Browser string `json:"Browser"`
WebKitVersion string `json:"WebKit-Version"`
UserAgent string `json:"User-Agent"`
V8Version string `json:"V8-Version"`
WebSocketDebuggerURL string `json:"webSocketDebuggerUrl"`
}
CDPVersionInfo is the JSON returned by /json/version. We only need the webSocketDebuggerUrl to derive the browser-level ws endpoint, but the rest is useful for diagnostics.
type Handle ¶
type Handle struct {
// CDPURL is the base HTTP endpoint, e.g. "http://127.0.0.1:54321". Drivers
// that speak raw HTTP discovery (/json/version, /json/list) use this.
CDPURL string
// WSURL is the browser-level websocket debugger URL, e.g.
// "ws://127.0.0.1:54321/devtools/browser/...". Drivers using
// connect_over_cdp / chromedp.NewRemoteAllocator use this.
WSURL string
// BrowserName is the display name ("Chrome" / "Edge" / …) of what was driven.
BrowserName string
// Port is the bound remote-debugging port.
Port int
// contains filtered or unexported fields
}
Handle is a launched browser process plus its CDP endpoint. Close must be called to release the process and temp profile.
func Launch ¶
func Launch(ctx context.Context, opts LaunchOptions) (*Handle, error)
Launch detects and starts a Chromium-based browser with a CDP endpoint and returns a Handle once CDP is reachable. The caller owns the Handle and must Close it.
If ExecutablePath is empty and no Chromium browser can be found, Launch returns an error wrapping ErrNoBrowser with install guidance — it never spawns a non-Chromium binary.
func (*Handle) Close ¶
Close terminates the browser, then (if Launch created a temp profile) removes it. It is safe to call multiple times.
When the caller supplied a PERSISTENT --user-data-dir (LoginOpts.UserDataDir), Close asks Chrome to exit gracefully and waits briefly so it can flush cookies/localStorage to disk before the process is killed — otherwise a persistent login session can be lost on a hard kill (a real issue agent-browser guards against with its wait_or_kill). The temp profile is only deleted when Launch created it (ownTempDir); a user-supplied persistent dir is left intact.
func (*Handle) Done ¶
func (h *Handle) Done() <-chan struct{}
Done returns a channel closed when the browser process exits. Useful for the screencast/keepalive loops to detect that the browser died under them.
func (*Handle) ExitErr ¶
ExitErr returns the process exit error after Done is closed (nil for a clean exit). Before Done is closed the result is meaningless.
func (*Handle) VersionInfo ¶
func (h *Handle) VersionInfo(ctx context.Context) (*CDPVersionInfo, error)
VersionInfo fetches /json/version from the running browser. Useful for diagnostics and confirming the browser is a real Chromium.
type LaunchOptions ¶
type LaunchOptions struct {
// ExecutablePath overrides browser auto-detection. Empty = auto-detect
// (Chrome → Edge → Brave → Chromium). This mirrors builtin's CHROME_PATH /
// [cowork] browser_path.
ExecutablePath string
// UserDataDir is the --user-data-dir. Empty = a fresh temp dir per launch
// (zero pollution, zero conflict with the user's real profile).
UserDataDir string
// Headless launches with --headless=new. When the in-app screencast panel
// is the primary view, headless avoids a second visible window stealing
// focus; for local debugging set false to watch the real window.
Headless bool
// Proxy is the --proxy-server value (e.g. "http://127.0.0.1:7890"). Empty =
// no proxy (direct). The driven browser should reach the network the same way
// fairpeer's other traffic does, so this mirrors the chromedp browser_* tools
// (see boot.go resolveBrowserProxyURL). Authenticated proxies (user:pass@)
// are NOT supported by --proxy-server; the caller must strip credentials.
Proxy string
// ExtraArgs are appended to the Chrome command line after the defaults.
ExtraArgs []string
// StartURL, if non-empty, is opened as the initial page.
StartURL string
}
LaunchOptions controls how a browser is launched.