Browser-agnostic automation for AI agents
Project description
browsectl
Browser-agnostic automation for AI agents.
A lightweight CLI that lets AI agents (or humans) drive a real browser session: navigate, screenshot, click, type, extract DOM, and evaluate JavaScript. Designed so that agents can see client-side-rendered pages (like LinkedIn) that aren't curl-friendly.
How it works
You launch your browser with remote debugging enabled. browsectl connects to it and sends commands over the browser's native automation protocol. The agent takes screenshots to "see" the page and decides what to do next. When it hits a CAPTCHA or 2FA wall, it tells you and waits.
The core is browser-agnostic. Concrete browser support is provided by swappable backends (currently: CDP for Chrome/Chromium).
Requirements
- Python 3.14+
- Chrome or Chromium (for the CDP backend)
Installation
git clone <repo-url>
cd browsectl
python -m venv .venv
.venv/bin/pip install poetry
.venv/bin/poetry install
Quick start
1. Launch and connect (one step)
browsectl -s <session> launch
This auto-assigns a free port, starts Chrome with its own profile at ~/.browsectl/profiles/<session>/, waits for CDP readiness, connects, and saves the session. The port is stored in the session file so all subsequent commands find it automatically. Logins persist across runs. Your existing Chrome windows are unaffected.
You can also specify a port explicitly if needed:
browsectl -s <session> launch <port>
If the explicit port is already in use, launch fails immediately with a clear error.
For slow-starting environments, override the CDP readiness timeout (default 15s):
browsectl -s <session> launch --timeout 30
2. Use it
Every command requires -s <session>:
browsectl -s <session> goto "https://example.com"
browsectl -s <session> screenshot # saves screenshot.png
browsectl -s <session> screenshot /tmp/page.png # custom path
browsectl -s <session> info # current URL and title
browsectl -s <session> html "h1" # extract innerHTML
browsectl -s <session> eval "document.title" # run JavaScript
browsectl -s <session> click "#login-button" # click by CSS selector
browsectl -s <session> type "#email" "me@example.com"
browsectl -s <session> scroll 500 # scroll down 500px
browsectl -s <session> scroll -300 # scroll up 300px
browsectl -s <session> wait ".results" 10 # wait for element (10s timeout)
browsectl -s <session> tabs # list open tabs
browsectl -s <session> newtab "https://github.com" # open new tab
browsectl -s <session> switchtab <tab-id> # switch to tab (ID from 'tabs')
browsectl -s <session> clear-cookies # clear all browser cookies
3. Manage sessions
browsectl sessions # list all sessions and their status
browsectl -s <session> stop # kill Chrome and remove the session
browsectl stop-all # stop all sessions at once
browsectl profiles # list profile directories
browsectl profiles --prune # remove orphaned profile directories
sessions shows each session's name, host:port, PID, and whether the process is running, dead, or external (connected manually, no PID tracked).
Connecting to an existing browser
If Chrome is already running with --remote-debugging-port, use connect instead of launch:
browsectl -s <session> connect <host> <port>
Both host and port are required.
Multiple sessions
Run multiple independent browser sessions simultaneously. Each gets its own auto-assigned port:
browsectl -s <session-a> launch
browsectl -s <session-b> launch
browsectl -s <session-a> goto "https://example.com"
browsectl -s <session-b> goto "https://github.com"
Each session gets its own Chrome process, profile directory, cookies, and localStorage. Ports are auto-assigned so agents never clash. Use browsectl sessions to see all active sessions, and browsectl -s <session> stop to shut one down. See docs/multi-session.md for details.
Backend selection
browsectl -s <session> -b cdp goto "https://example.com" # explicit (default)
Available backends: cdp. The architecture supports adding others (WebDriver, Marionette, etc.) without changing the core.
Architecture
Hexagonal / ports-and-adapters. The core never imports a concrete browser adapter.
browsectl/
models.py # domain types (PageInfo, Screenshot, Tab, etc.)
ports.py # function signature contracts, generic over Session
gateway.py # BrowserGateway[S] -- frozen bundle of port functions
core.py # command dispatch, browser-agnostic
main.py # CLI entry point, wiring
adapters/
cdp.py # Chrome DevTools Protocol implementation
Per-site guides
docs/sites/ contains navigation guides for specific websites. Each guide documents working selectors, SPA quirks, authentication patterns, and step-by-step browsectl workflows for that site. Selectors are timestamped since sites change their DOM frequently.
Use docs/sites/_template.md as a starting point for new guides.
Development
.venv/bin/pytest tests/ -v # run tests
.venv/bin/mypy browsectl/ # type check (strict)
.venv/bin/ruff check browsectl/ # lint
License
MIT. See LICENSE.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file browsectl-0.2.1.tar.gz.
File metadata
- Download URL: browsectl-0.2.1.tar.gz
- Upload date:
- Size: 14.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.4.1 CPython/3.14.6 Linux/6.17.0-1020-azure
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ff5ad8d852fd1bf58ab759aa00aab8f22863e7169639f2a2967d778524897d91
|
|
| MD5 |
7f5a45a90121eb77c06ff0cae7ee9889
|
|
| BLAKE2b-256 |
59ac404b7729e9d1804fa6f6fedef2708c2223e3ec3319e385b9c9ea20f44d7a
|
File details
Details for the file browsectl-0.2.1-py3-none-any.whl.
File metadata
- Download URL: browsectl-0.2.1-py3-none-any.whl
- Upload date:
- Size: 16.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.4.1 CPython/3.14.6 Linux/6.17.0-1020-azure
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d1d537f5090eae6b4445924d22f06853656437e0fa2e4541ea20820aade9a102
|
|
| MD5 |
3326b1bb29ca36d6da2f6891ad7e008a
|
|
| BLAKE2b-256 |
f6df33c436e0d85ee3902018d86d5cd185b6d0aa5a37ecb6e74b56991f27ea36
|