Skip to content

CDP coverage ​

Pyro speaks the Chrome DevTools Protocol over WebSocket. It implements the subset that Playwright's Chromium driver and Puppeteer send, over its own engine (JavaScriptCore, a Rust DOM and Blitz layout). This page lists every method the dispatcher handles, by domain, and the events it emits.

Every method not listed here returns an explicit error. Nothing is faked as a success (see Unknown and unsupported methods). For Pyro's own domains, see Pyro CDP domain (prepared pages, browser level) and LP.run wire format (LP.*, page level).

Status key

StatusMeaning
implementedBacked by the engine. Notes list the limits that differ from Chrome.
partialWorks for the common case. Some parameters or modes return errors or are ignored (see notes).
acceptedReturns {}, but nothing in the engine observes it. The success is still truthful, because the thing it would control does not exist (for example, there are no breakpoints to skip).

Connecting ​

Start a server with lightningpanda serve (default 127.0.0.1:9222). It serves:

EndpointResponse
GET /json/version{"Browser": "Chrome/124.0.6367.29", "Protocol-Version": "1.3", "User-Agent": "…", "V8-Version": "", "WebKit-Version": "", "webSocketDebuggerUrl": "ws://HOST:PORT/"}. HOST is --advertise-host, else --host.
GET /json, GET /json/list[]. A fresh connection has no pages to list.
WebSocket upgrade on any pathA CDP connection. In fork mode, the query ?profile=N asks for a fork of profile N's snapshot (details).

PUT is accepted like GET. Other paths return 404. Other methods return 405.

Security checks on every request:

  • The Host header must be an IP literal or localhost (with an optional port). Anything else gets 403, a guard against DNS rebinding. Connect by IP when the server is remote.
  • WebSocket upgrades that carry an Origin header get 403, so web pages in a normal browser cannot drive the server.

Each WebSocket connection is a separate browser: its own engine thread, browser contexts and targets. Every context is disposed when the connection closes. The number of connections and the message sizes are capped by --cdp-max-connections and --cdp-max-message-size.

ts
// Playwright (stock): connect over CDP
import { chromium } from 'playwright';
const browser = await chromium.connectOverCDP('http://127.0.0.1:9222');

// Puppeteer
import puppeteer from 'puppeteer-core';
const browser2 = await puppeteer.connect({ browserWSEndpoint: 'ws://127.0.0.1:9222/' });

The Playwright drop-in (@povio/lightning-panda/playwright, see Coming from Playwright) and the SDK connect for you. For Puppeteer details, see Puppeteer and raw CDP.

Sessions use flat mode only. Target.attachToTarget and Target.setAutoAttach without flatten: true fail with Only flatten mode is supported. Per-connection budgets: 256 browser contexts, 256 targets, 512 sessions.

Unknown and unsupported methods ​

CaseError
Domain or method the engine does not implement{"code": -32000, "message": "<Method> is not supported by lightningpanda"}
Page method sent on the browser session (no sessionId), for example Page.navigatesame -32000 … is not supported by lightningpanda. Attach to the target first.
Unknown Lightningpanda.* method, or a method name without a .{"code": -32601, "message": "'<Method>' wasn't found"}
Unknown sessionId{"code": -32001, "message": "Session with given id not found."}
Bad params-32602 with the parse or validation message (Chrome's text where Chrome has one)

Known unsupported methods that Playwright 1.59 may send: Browser.cancelDownload, Browser.getWindowBounds, Browser.setDockTile, Emulation.setScriptExecutionDisabled, HeapProfiler.collectGarbage, Network.loadNetworkResource, Page.setFontFamilies, Page.startScreencast, Tracing.start, Tracing.end. Runtime.queryObjects also fails explicitly, because JavaScriptCore's API has no heap iteration.

Browser-level methods ​

These are sent without a sessionId, or on a browser session from Target.attachToBrowserTarget.

Target ​

MethodStatusNotes
Target.setDiscoverTargetsimplementedPage and tab filters honored.
Target.setAutoAttachimplementedFlat mode only. Attaches pages (Playwright) or tab targets (Puppeteer) as the filter asks. Popups start paused (waitingForDebugger) until Runtime.runIfWaitingForDebugger. Not available on browser sessions from attachToBrowserTarget.
Target.getTargetsimplemented
Target.getTargetInfoimplemented
Target.getBrowserContextsimplementedThe default context is not listed, as in Chrome.
Target.createBrowserContextimplementedSeveral contexts per connection, each with its own network client, cookies and storage. proxyServer takes one HTTP proxy (CONNECT for https, absolute-form for http; direct:// for none), and proxyBypassList takes Chrome's syntax (<local>, <-loopback>, CIDR, wildcards). SOCKS, https:// proxies and per-scheme lists are refused.
Target.disposeBrowserContextimplementedThe default context cannot be disposed.
Target.createTargetimplementedPage targets only. Page-opened popups (target=_blank, named targets, window.open) become targets in the opener's context with openerId. There is no cross-page WindowProxy: window.open returns a minimal object (closed, close(), focus(), blur(), location).
Target.closeTargetimplemented
Target.attachToTargetimplementedFlat mode only.
Target.detachFromTargetimplementedBy sessionId or targetId.
Target.activateTargetimplementedValidates the target. There is nothing to bring forward.
Target.attachToBrowserTargetimplementedFlat browser sessions with explicit page attachment. Nested browser sessions and per-session auto-attach or discovery are unsupported.

Browser, Storage, Security ​

MethodStatusNotes
Browser.getVersionimplementedproduct Chrome/124.0.6367.29, protocolVersion 1.3, Chrome-like userAgent. revision and jsVersion are empty.
Browser.setDownloadBehaviorimplementedPer browser context. deny, default, allow, allowAndName. The allow modes need downloadPath. <a download> to blob:, data: or same-origin URLs, and navigations answered with Content-Disposition: attachment, are written to disk. Browser.downloadWillBegin and Browser.downloadProgress are emitted when eventsEnabled is set.
Browser.grantPermissionsimplementedPer context (the default context without browserContextId). Drives navigator.permissions.query, live PermissionStatus change events and the context clipboard. Chrome's messages for unknown types.
Browser.resetPermissionsimplementedBack to Chrome's defaults (clipboard-write granted, the rest prompt).
Browser.setPermissionimplementedOne permission for one origin, or for every origin.
Storage.getCookies / setCookies / clearCookiesimplementedThe context's real cookie jar (HTTP cookies included). Negative expires means a session cookie. Invalid batches are rejected before anything changes. Partitioned and SameParty cookies, non-default priority and source overrides are refused.
Security.enable / disableacceptedNo security state events.
Security.setIgnoreCertificateErrorsimplementedOn the browser session (Puppeteer acceptInsecureCerts), it covers every context, later ones included. On a page session, it covers that page's context. Handshake signatures are still verified. Otherwise an untrusted certificate fails with net::ERR_CERT_AUTHORITY_INVALID.
Runtime.runIfWaitingForDebuggeracceptedOn a browser session.

Pyro ​

Lightningpanda.capabilities, registerPreparedPage, acquirePreparedPage, preparedPages, unregisterPreparedPage, adoptPreparedPage, preparedProfiles. See Pyro CDP domain.

Page-session methods ​

These are sent with the sessionId of an attached page.

Page ​

MethodStatusNotes
Page.enable / disableimplemented
Page.navigateimplementedabout:blank, data: and HTTP(S) documents. frameId can target child frames. A download response fails the navigation with net::ERR_ABORTED.
Page.reloadimplementedSame limits as navigate.
Page.getFrameTreeimplementedNested frames with loader ids and security origins.
Page.setLifecycleEventsEnabledimplementedPer-frame lifecycle events. Milestones already reached are replayed.
Page.addScriptToEvaluateOnNewDocument / removeScriptToEvaluateOnNewDocumentimplemented
Page.createIsolatedWorldimplementedNamed isolated worlds per frame.
Page.getNavigationHistoryimplementedMain-frame history. Only the current entry has a title. transitionType is always other.
Page.navigateToHistoryEntryimplementedSame-document entries fire popstate. Others re-fetch (no bfcache).
Page.getLayoutMetricsimplementedCSS px from Pyro's layout. No pinch zoom: the visual viewport equals the layout viewport.
Page.captureScreenshotimplementedRendered on the CPU by the Blitz renderer. png and jpeg (quality), clip with scale, captureBeyondViewport. webp, fromSurface: false and optimizeForSpeed are ignored or refused. Pixels differ from Chromium's. See Rendering.
Page.printToPDFimplementedPaper size, landscape, margins, scale (0.1–2), printBackground, pageRanges, generateTaggedPDF, links, transferMode: ReturnAsStream. Paged by .pz-page boxes (Paprize) or by cutting the document at Chrome-like break points. displayHeaderFooter and its templates, preferCSSPageSize and generateDocumentOutline are accepted and ignored. The page prints with its emulated media (screen unless set to print), not Chrome's print media. See Rendering.
Page.handleJavaScriptDialogimplementedalert, confirm, prompt and beforeunload block while a session has Page enabled. During LP.* driver commands dialogs are dismissed instead, unless LP.dialogs {block: true} is set.
Page.setInterceptFileChooserDialogimplementedEmits Page.fileChooserOpened.
Page.setDocumentContentimplementeddocument.open, write, close on the current document. URL and contexts stay. No frameNavigated.
Page.closeimplementedFires beforeunload. A cancelling handler opens a dialog.
Page.setBypassCSPacceptedThere is no CSP enforcement.
Page.bringToFrontacceptedEach page is always in the foreground.

Runtime ​

MethodStatusNotes
Runtime.enable / disableimplementedExecution context, console and exception events.
Runtime.evaluateimplementedreturnByValue, awaitPromise, generatePreview (V8's ObjectPreview shape), objectGroup. A JavaScriptCore Proxy is previewed as its target.
Runtime.callFunctionOnimplemented
Runtime.getPropertiesimplementedownProperties, accessorPropertiesOnly, nonIndexedPropertiesOnly, generatePreview, and the internal properties JavaScriptCore exposes. No [[Target]]/[[Handler]] for a Proxy, no [[Scopes]], no [[FunctionLocation]].
Runtime.releaseObject / releaseObjectGroupimplemented
Runtime.addBinding / removeBindingimplementedSurvives navigation. Emits Runtime.bindingCalled (Playwright exposeFunction).
Runtime.runIfWaitingForDebuggerimplementedStarts a paused popup's navigation.
Runtime.terminateExecutionimplementedStops a running script. It answers "Execution was terminated".
Runtime.setAsyncCallStackDepthacceptedNo async stacks are recorded.
Runtime.queryObjectsunsupportedExplicit error.

DOM ​

MethodStatusNotes
DOM.enable / disableimplementedOnly DOM.documentUpdated. No frontend mirror or mutation events.
DOM.describeNodepartialBackend node ids, depth 0–32, at most 1024 nodes. No frontend nodeIds, no depth -1, no pierce.
DOM.resolveNodeimplementedInto any world of the node's frame.
DOM.getBoxModel / getContentQuadsimplementedFrom Blitz layout, with transforms. Inline boxes report one quad per line.
DOM.scrollIntoViewIfNeededimplementedReveals through iframes. Honors rect.
DOM.focusimplemented
DOM.getFrameOwnerimplemented
DOM.setFileInputFilesimplementedPaths read from disk (64 MiB each). Fires trusted input and change.

DOM.getDocument, DOM.querySelector*, DOM.getOuterHTML and the rest of the frontend DOM domain are unsupported. Use Runtime.evaluate or LP.* locators.

Input ​

MethodStatusNotes
Input.dispatchMouseEventimplementedHit testing through iframes. Trusted mouse and pointer events, boundary events, wheel scrolling. No pen and no custom pressure.
Input.dispatchKeyEventimplementedTrusted keyboard events with default actions. The macOS editing commands are advisory: the key's own default action runs (arrows, Home/End, Backspace, Delete, Meta+A). Clipboard, undo and word movement do nothing.
Input.insertTextimplementedCancelable beforeinput and input.
Input.dispatchTouchEventimplementedChrome's pointer, touch and compat-mouse sequence. A tap clicks. Touch never scrolls the page.
Input.dispatchDragEventpartialNative drag sessions as in Blink. Drags carrying files and child-frame targets are unsupported.
Input.setInterceptDragsimplementedEmits Input.dragIntercepted (Playwright drag-and-drop).

Emulation ​

MethodStatusNotes
Emulation.setDeviceMetricsOverride / clearDeviceMetricsOverridepartialWidth, height, DPR, screen size and resize events. mobile: true is accepted, but <meta name=viewport> has no effect. Transforms and non-trivial screenOrientation are refused.
Emulation.setEmulatedMediaimplementedprint/screen, prefers-color-scheme and prefers-reduced-motion reach matchMedia, CSS, layout and rendering. Other features are accepted and not evaluated.
Emulation.setUserAgentOverrideimplementedPer page. userAgentMetadata drives navigator.userAgentData and the low-entropy Sec-CH-UA* headers.
Emulation.setLocaleOverridepartialnavigator.language(s) and Accept-Language only. Intl and Date keep the process locale.
Emulation.setTimezoneOverridepartialPer connection (Date, Intl, Temporal). Two pages on one connection cannot hold different zones ("Cannot set timezone").
Emulation.setGeolocationOverride / clearGeolocationOverrideimplementedPer browser context. Needs the geolocation permission.
Emulation.setTouchEmulationEnabledimplementednavigator.maxTouchPoints (1–16), (pointer: coarse), (hover: none).
Emulation.setDefaultBackgroundColorOverrideimplementedScreenshot background. a: 0 gives transparent PNGs.
Emulation.setVirtualTimePolicypartialFreezes Date and performance.now() and holds timers. advance and pauseIfNetworkFetchesPending with budget (emits Emulation.virtualTimeBudgetExpired). Thread-wide and owned by one page. Cannot be turned off.
Emulation.setFocusEmulationEnabledacceptedHeadless pages always behave as focused.

Network ​

MethodStatusNotes
Network.enable / disableimplementedRequest, response, data, finish and failure events, plus WebSocket events. Bounded buffers: on overflow the connection closes instead of dropping events. Per-session buffer options are refused.
Network.getResponseBodyimplementedText or base64. 64 MiB process budget, 8 MiB per body. Evicted bodies get an explicit error.
Network.getRequestPostDataimplementedUp to 1 MiB per body, 8 MiB per page.
Network.setExtraHTTPHeadersimplementedPer page. Applied while Network is enabled.
Network.setUserAgentOverrideimplementedSame as the Emulation method.
Network.setCacheDisabledimplementedPer page, while Network is enabled.
Network.clearBrowserCacheimplementedThe context's HTTP cache, and the shared asset cache when it is on.
Network.setBypassServiceWorkerimplementedPer session.
Network.emulateNetworkConditionspartialoffline only (per context). Latency and throughput are ignored.
Network.getCookies / setCookie / setCookies / deleteCookies / clearBrowserCookiesimplementedThe page's context jar.

Fetch ​

MethodStatusNotes
Fetch.enable / disableimplementedRequest and response stages. Only one session per page can intercept. Synchronous XHR is not offered for interception.
Fetch.continueRequestimplementedRequest overrides. interceptResponse: true pauses the request again at the response stage.
Fetch.fulfillRequestimplementedText or binary headers. Custom status phrases are refused.
Fetch.failRequestimplemented
Fetch.continueResponseimplementedResponse stage.
Fetch.getResponseBodyimplementedResponse stage only.
Fetch.continueWithAuthimplementedServer and proxy Basic challenges (Fetch.authRequired). Other schemes are unsupported.

Accessibility ​

MethodStatusNotes
Accessibility.enable / disableacceptedTrees are computed per call.
Accessibility.getFullAXTreeimplementeddepth, frameId. Chrome's node shape, compared 1:1 on fixtures. No InlineTextBox nodes, no synthesized nodes, shadow and frame contents not inlined. At most 16384 nodes.
Accessibility.getPartialAXTreepartialbackendNodeId/objectId and fetchRelatives. No frontend nodeId.
Accessibility.queryAXTreeimplementedExact accessibleName and role match.

Coverage: Profiler, Debugger, CSS ​

MethodStatusNotes
Profiler.enableacceptedCoverage starts with startPreciseCoverage.
Profiler.disableimplementedStops precise coverage.
Profiler.startPreciseCoverage / stopPreciseCoverage / takePreciseCoverageimplementedJavaScriptCore's control-flow profiler in V8's block-coverage shape (for c8 and v8-to-istanbul). Playwright page.coverage JS.
Debugger.enable / disableimplementedEmits Debugger.scriptParsed while precise coverage is on. No breakpoints.
Debugger.getScriptSourceimplemented
Debugger.resume, setSkipAllPauses, setAsyncCallStackDepth, setBreakpointsActive, setPauseOnExceptions, setBlackboxPatternsacceptedThe engine never pauses.
CSS.enable / disableimplementedCSS.styleSheetAdded for <link> and <style> sheets.
CSS.getStyleSheetTextimplemented
CSS.startRuleUsageTracking / stopRuleUsageTracking / takeCoverageDeltaimplementedRule usage for page.coverage CSS.

Other domains ​

MethodStatusNotes
Browser.getWindowForTargetpartialOne headless window per page. Reports the bounds set with setWindowBounds, else the viewport (default 1280x720).
Browser.setWindowBoundsacceptedStored and reported back. No page API observes it.
Performance.enable / disableacceptedNo timeline events.
Performance.getMetricsimplementedTimestamp, Documents, Frames, Nodes, LayoutCount, RecalcStyleCount, LayoutDuration, RecalcStyleDuration. No JS heap metrics.
IO.read / IO.closeimplementedStreams from printToPDF with ReturnAsStream.
Log.enable / disableacceptedConsole output goes through Runtime.consoleAPICalled.
Audits.enable / disableacceptedNo issues are reported.
Security.*see Browser, Storage, Security
Target.getTargets, Target.getTargetInfo, Target.setAutoAttachimplementedOn a page session, setAutoAttach attaches the page's dedicated workers. Iframes are frames of the page, not separate targets.
LP.run, LP.idle, LP.act, LP.expect, LP.query, LP.dialogsimplementedPyro's native driver. See LP.run wire format.

Worker sessions ​

Dedicated workers attached through Target.setAutoAttach on a page session accept Runtime.enable, disable, evaluate, callFunctionOn, releaseObject, releaseObjectGroup, plus setAsyncCallStackDepth, discardConsoleEntries and terminateExecution (accepted), Target.getTargetInfo, Target.setAutoAttach and Runtime.runIfWaitingForDebugger. Workers never wait for the debugger. Anything else returns the unsupported error.

Tab sessions (Puppeteer) ​

A tab target session (Puppeteer's auto-attach filter) accepts Target.setAutoAttach (attaches its page), Target.getTargetInfo, Target.detachFromTarget and Runtime.runIfWaitingForDebugger.

Events ​

DomainEvents
TargettargetCreated, targetDestroyed, attachedToTarget, detachedFromTarget (no targetInfoChanged)
PageframeAttached, frameDetached, frameNavigated, frameStartedNavigating, frameStartedLoading, frameStoppedLoading, frameRequestedNavigation, frameScheduledNavigation, frameClearedScheduledNavigation, navigatedWithinDocument, lifecycleEvent, domContentEventFired, loadEventFired, javascriptDialogOpening, javascriptDialogClosed, fileChooserOpened
RuntimeexecutionContextCreated, executionContextDestroyed, executionContextsCleared, consoleAPICalled (with object previews and the caller's stack trace), exceptionThrown, bindingCalled
NetworkrequestWillBeSent, responseReceived, dataReceived, loadingFinished, loadingFailed, webSocketCreated, webSocketWillSendHandshakeRequest, webSocketHandshakeResponseReceived, webSocketFrameSent, webSocketFrameReceived, webSocketFrameError, webSocketClosed (no *ExtraInfo events: hasExtraInfo is false)
FetchrequestPaused, authRequired
BrowserdownloadWillBegin, downloadProgress
DOMdocumentUpdated
CSSstyleSheetAdded
DebuggerscriptParsed
InputdragIntercepted
EmulationvirtualTimeBudgetExpired

Differences from Chrome worth knowing ​

  • Contexts: many browser contexts can coexist on one connection. All of them are disposed when the connection closes.
  • No placeholder page: Target.setAutoAttach attaches no startup page.
  • about:blank has a realm: scripts can run in a blank page.
  • Iframes are frames, not targets: there are no out-of-process iframes. Child frames appear through Page.frame* events and frameId parameters.
  • Rendering is CPU-only: screenshots and PDFs come from Blitz (Stylo, Taffy, Parley, vello_cpu), so pixels differ from Chromium's.

For the web APIs inside the page, see Web platform support. For Playwright API coverage, see API coverage.

AGPL-3.0-only. A derivative of Lightpanda. Built by Povio.