sema-cdp
0.1.0Chrome DevTools Protocol client: launch, connect, send commands, wait for events
sema-cdp
Chrome DevTools Protocol client: launch, connect, send commands, wait for events.
This is the raw protocol layer. It knows nothing about selectors or clicking —
for a high-level API (auto-waiting actions, screenshots, accessibility
snapshots) use sema-browser, which
is built on this package. Use sema-cdp directly when you need protocol
domains the high-level layer doesn't wrap: network interception, tracing,
emulation, coverage, or any of the CDP domains.
Works against anything that speaks CDP: Chrome, Chromium, Edge, Brave,
chrome-headless-shell, or an already-running browser started with
--remote-debugging-port.
Install
sema pkg add sema-cdp
Quick start
(import "sema-cdp")
(define b (cdp/launch)) ; headless Chrome
(define sess (cdp/attach! b (cdp/new-target! b "about:blank")))
(cdp/send sess "Page.enable")
(cdp/send sess "Page.navigate" {:url "https://sema-lang.com"})
(cdp/wait-event sess "Page.loadEventFired")
(define r (cdp/send sess "Runtime.evaluate"
{:expression "document.title" :returnByValue #t}))
(println (:value (:result r))) ; => Sema
(cdp/close! b)
API
| Function | Description |
|---|---|
cdp/find-chrome |
Locate a Chrome-compatible binary, or nil |
cdp/browser-candidates |
The paths find-chrome probes, in priority order |
cdp/launch |
Launch a browser with remote debugging, return a connection |
cdp/connect |
Attach to an already-running browser |
cdp/close! |
Shut the browser down and release its process |
cdp/send |
Send a command, return its result map |
cdp/targets |
List browser targets |
cdp/new-target! |
Create a page target, return its id |
cdp/attach! |
Attach to a target, return a session |
cdp/detach! |
Detach a session |
cdp/on! |
Register an event handler (returns an id) |
cdp/off! |
Remove a handler by id |
cdp/pump |
Receive events while otherwise idle |
cdp/wait-event |
Wait for (and consume) an event |
cdp/events |
Buffered events |
cdp/clear-events! |
Drop buffered events |
cdp/version |
Browser version info |
(cdp/find-chrome) / (cdp/browser-candidates)
cdp/find-chrome returns the path of a Chrome-compatible browser binary, or
nil if none is found. It checks the SEMA_CHROME env var first, then
well-known install locations on macOS, Linux, and Windows — Chrome, Chromium,
Brave, and Edge, in that order. On Windows the per-machine and per-user roots
come from PROGRAMFILES, PROGRAMFILES(X86), and LOCALAPPDATA.
cdp/browser-candidates returns the probed paths for this machine, in
priority order (most will not exist) — useful for diagnosing why no browser
was found.
(cdp/launch) / (cdp/launch opts)
Launch a browser with remote debugging and return a connection. Options:
:headless— default#t:chrome— binary path (default:cdp/find-chrome):args— list of extra CLI arguments:user-data-dir— profile dir (default: a fresh dir under the system temp dir)
Errors if no browser binary can be found, naming the ways to provide one.
(cdp/connect url)
Connect to an already-running browser. Accepts a ws:// debugger URL, or an
http:// devtools address (e.g. "http://localhost:9222") whose
/json/version endpoint is used to discover it.
(define b (cdp/connect "http://localhost:9222"))
(cdp/close! conn)
Ask the browser to shut down (Browser.close), close the websocket, and kill
the spawned process when this connection launched it.
(cdp/send target method) / (cdp/send target method params) / (cdp/send target method params opts)
Send a CDP command and return its result map (keyword keys). target is a
connection or a session from cdp/attach! — a session routes the command to
its target. opts supports :timeout in ms (default 30000). A CDP error
response raises, including the method, code, and message.
(cdp/send sess "Emulation.setDeviceMetricsOverride"
{:width 390 :height 844 :deviceScaleFactor 3 :mobile #t})
(cdp/targets conn)
List the browser's targets (pages, workers, extensions) as maps with
:targetId, :type, :url, :title.
(cdp/new-target! conn url)
Create a new page target navigated to url and return its target id.
(cdp/attach! conn target-id)
Attach to a target (flat protocol) and return a session map. Pass the session
to cdp/send / cdp/wait-event to address that target.
(cdp/detach! session)
Detach a session created by cdp/attach!.
(cdp/on! target method handler) / (cdp/off! target handler-id)
cdp/on! registers a handler called with each matching event map as it
arrives, and returns a handler id; cdp/off! removes it. Scoped to the session
when target is one, otherwise connection-wide. Events are only received while
a cdp/send, cdp/wait-event, or cdp/pump is pumping the connection — there
is no background thread. Handlers may call cdp/send themselves (responses are
routed by id, so reentrant sends are safe).
(cdp/pump target duration-ms)
Receive and dispatch events for up to duration-ms without sending anything —
use it to let cdp/on! handlers run while otherwise idle.
(cdp/version conn)
Return browser version info: :product, :revision, :userAgent,
:jsVersion, :protocolVersion.
(cdp/wait-event target method) / (cdp/wait-event target method opts)
Wait for an event, consume it from the buffer, and return the event map.
Already-buffered events match first, so an event that fired during a previous
command is not missed. Options: :timeout ms (default 30000), :pred — a
predicate on the event map.
(cdp/wait-event sess "Network.responseReceived"
{:pred (fn (ev) (string/contains?
(get-in ev [:params :response :url]) "/api/"))})
(cdp/events target) / (cdp/clear-events! target) / (cdp/clear-events! target method)
Inspect or drop the buffered events (oldest first, capped at 500). Scoped to
the session when target is one.
Testing
sema tests.sema
The live tests launch a headless browser and are skipped when none is
installed (cdp/find-chrome returns nil).
License
MIT
| Version | Size | Published |
|---|---|---|
| 0.1.0 | 9 KB | 2026-08-25 14:26:50 |