browserlaunch

package
v0.1.5 Latest Latest
Warning

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

Go to latest
Published: Aug 9, 2026 License: MIT Imports: 17 Imported by: 0

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

View Source
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

func (h *Handle) Close() error

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

func (h *Handle) ExitErr() error

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.

Jump to

Keyboard shortcuts

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