Connect a CDP Client
icdp exposes a browser-level WebSocket plus a direct WebSocket for every Target. Use the browser endpoint and Chromium's flat-session protocol when one connection must manage multiple Targets. Use a /json/list entry's webSocketDebuggerUrl when the Client expects a traditional sessionless page endpoint.
Use any CDP library or WebSocket implementation that lets you send these standard message envelopes. This complete Node example uses the ws package:
import WebSocket from "ws";
const version = await fetch("http://127.0.0.1:9222/json/version").then((response) =>
response.json(),
);
const socket = new WebSocket(version.webSocketDebuggerUrl);
await new Promise((resolve, reject) => {
socket.once("open", resolve);
socket.once("error", reject);
});
let nextId = 0;
const pending = new Map();
socket.on("message", (raw) => {
const message = JSON.parse(raw.toString());
if (message.id === undefined) {
console.log("event", message.method, message.params);
return;
}
const request = pending.get(message.id);
pending.delete(message.id);
if (!request) return;
if (message.error) request.reject(new Error(message.error.message));
else request.resolve(message.result);
});
function send(method, params = {}, sessionId) {
const id = ++nextId;
socket.send(JSON.stringify({ id, method, params, ...(sessionId ? { sessionId } : {}) }));
return new Promise((resolve, reject) => pending.set(id, { resolve, reject }));
}
const { targetInfos } = await send("Target.getTargets");
const target = targetInfos[0];
if (!target) throw new Error("No Targets are available");
const { sessionId } = await send("Target.attachToTarget", {
targetId: target.targetId,
flatten: true,
});
await send("Runtime.enable", {}, sessionId);
const { result } = await send(
"Runtime.evaluate",
{ expression: "document.title", returnByValue: true },
sessionId,
);
console.log(result.value);
socket.close();The wire sequence is the same regardless of Client implementation:
- Read
/json/versionand open itswebSocketDebuggerUrl. - Send
Target.getTargets. - Send
Target.attachToTargetwithflatten: true. - Put the returned
sessionIdon every command for that Target. - Treat messages with
methodand noidas events for theirsessionId.
For a direct Target connection, fetch /json/list, select an entry, and open its webSocketDebuggerUrl. Send Target commands on that socket without a sessionId; results and implicit-Session events omit it as well.
Domain state is Session-local. Enable Runtime, Page, Network, Accessibility, or another event-producing domain separately on every attachment that needs it. Detach with Target.detachFromTarget; closing the browser WebSocket also tears down all of that Client's Sessions.
icdp implements the methods listed in the CDP support matrix. Unsupported methods return the standard -32601 method-not-found error. Do not infer support from the Client's API surface.