Understanding the Chrome DevTools Protocol (CDP) for Remote Debugging
This article explains the Chrome DevTools Protocol (CDP), its architecture of frontend, backend, protocol and channels, and provides step‑by‑step instructions with code examples for launching a CDP server, connecting a client, and performing remote debugging of JavaScript, CSS and DOM through WebSocket or other transports.
What is the CDP protocol
CDP (Chrome DevTools Protocol) is a JSON‑RPC protocol over sockets (WebSocket, USB, ADB) used to invoke Chrome's internal methods for debugging JavaScript, CSS, and DOM. The backend implements the protocol (e.g., Chrome, Puppeteer) and the frontend (devtools) acts as a client.
DevTools Debugging System
The complete debugging system consists of four parts: Frontend, Backend, Protocol, and Channels.
Frontend: The debugger front‑end, such as chrome‑devtools‑frontend , a web application that receives CDP events and sends CDP commands to perform DOM, network, and debugger operations.
Backend: Applications that implement the CDP protocol (Chromium, V8, Node.js) and receive commands and emit events.
Protocol: The CDP itself, a JSON‑RPC 2.0 based protocol that defines domains, types, commands, and events.
Channels: The transport mechanisms (Embedder Channel, WebSocket Channel, Chrome Extensions Channel, USB/ADB Channel) used to exchange messages between front‑end and back‑end.
Chrome Remote Debugging
Any application that can consume CDP messages can be debugged with chrome‑devtools‑frontend . Chrome already integrates CDP, so establishing a socket connection to the frontend enables remote debugging. The startup process has three steps:
Start the CDP server (backend).
Start the CDP client (frontend).
Create the connection.
Start CDP Server
Example commands for Chrome and Puppeteer that launch a backend listening on port 9222.
Chrome
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222 --user-data-dir=./testPuppeteer
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({
args: ['--remote-debugging-port=9222', '--remote-debugging-address=0.0.0.0'],
});
const page = await browser.newPage();
console.log(browser.wsEndpoint());
})();Visiting http://0.0.0.0:9222/json returns a list of pages with their WebSocket debugger URLs, confirming the backend is running.
[ {
"description": "",
"devtoolsFrontendUrl": "/devtools/inspector.html?ws=0.0.0.0:9222/devtools/page/...",
"id": "...",
"title": "Welcome to Chrome",
"type": "page",
"url": "chrome://welcome/",
"webSocketDebuggerUrl": "ws://0.0.0.0:9222/devtools/page/..."
}, ... ]Start CDP Client
chrome‑devtools‑frontend is a pure web app that can be served via Koa or accessed directly through Chrome’s built‑in devtools frontend at http://0.0.0.0:9222/devtools/inspector.html .
Create Connection
Pass the webSocketDebuggerUrl to the frontend, e.g. http://0.0.0.0:9222/devtools/inspector.html?ws=${webSocketDebuggerUrl} , or open http://0.0.0.0:9222/ to see the list of tabs and click the desired page.
Opening the Network tab shows the WebSocket traffic where the backend receives CDP commands from the frontend and returns DOM, network, and resource information.
CDP Protocol Structure
cdp protocol groups capabilities by Domain; each domain contains Methods, Events, and Types. (Reference: https://chromedevtools.github.io/devtools-protocol/tot/Debugger/)Methods correspond to request/response, Events to publish/subscribe, and Types to the data structures used in communication.
Example of executing JavaScript remotely: entering the following code in the devtools console triggers three CDP commands – Runtime.compileScript, Runtime.evaluate, and Runtime.compileScript.
pp=function(){ alert(244) }
pp() {
"id": 47,
"method": "Runtime.evaluate",
"params": {
"expression": "pp=function(){alert(244)}",
"includeCommandLineAPI": true,
"generatePreview": true,
"userGesture": false,
"awaitPromise": false,
"throwOnSideEffect": true,
"timeout": 500,
"disableBreaks": true,
"replMode": true,
"uniqueContextId": "-3083772769491583108.6833303176535544523"
}
} {
"id": 178,
"method": "Runtime.compileScript",
"params": {
"expression": "pp=function(){alert(244)}",
"sourceURL": "",
"persistScript": false,
"executionContextId": 7
}
} {
"id": 100,
"method": "Runtime.compileScript",
"params": {
"expression": "pp()",
"sourceURL": "",
"persistScript": false,
"executionContextId": 7
}
}Manual Implementation
H5 Front‑end Calls CDP
var ws = new WebSocket('ws://127.0.0.1:9222/devtools/page/620F91C22D41B614947001C52AC55E53');
window.ppp = function(){
// Call Command
debugger
ws.onmessage = function(event){
console.log(event.data);
// Example data: {"method":"Page.loadEventFired","params":{"timestamp":1402317772.874949}}
};
ws.send('{"id":1,"method":"Page.navigate","params":{"url":"http://www.github.com"}}');
};Remote Debugging
The community provides a basic remote‑debugging solution called devtools‑remote , which offers a WebSocket proxy and a Chrome extension that listens for CDP messages.
devtools‑remote uses the Chrome Extensions API ( chrome.debugger ) with the following methods:
chrome.debugger.getTargets : Retrieves a list of debuggable targets (tab IDs).
chrome.debugger.attach : Attaches the debugger to a target.
chrome.debugger.sendCommand : Sends a CDP command to the target.
chrome.debugger.onEvent.addListener : Listens to all events from the target and forwards them as CDP messages.
Extension workflow:
User clicks the extension, which obtains the current tab ID.
chrome.debugger.attach attaches the debugger.
A WebSocket proxy connects to the remote devtools frontend.
The extension forwards data.request messages as CDP commands and returns data.response with matching IDs.
chrome.debugger.onEvent.addListener captures backend events, formats them as CDP messages, and sends them to the proxy.
The proxy simply forwards data.response and data.event from the extension to the devtools frontend, and forwards data.request from the frontend to the extension.
Other libraries such as chobitsu provide CDP parsing capabilities (Storage, Runtime, Network, DOM, etc.) and can be used to implement remote debugging without relying on the Chrome extension API. Projects like devtools-pro demonstrate this approach and highlight security considerations such as XSS.
React‑devtools follows a similar pattern, injecting a backend script into the inspected page to listen for changes and send CDP commands.
Reference documents:
Chrome DevTools Protocol – https://chromedevtools.github.io/devtools-protocol/tot/Debugger/
chrome‑remote‑interface – https://github.com/cyrus-and/chrome-remote-interface
Deep Dive into Chrome DevTools – https://zhaomenghuan.js.org/blog/chrome-devtools.html
政采云技术
ZCY Technology Team (Zero), based in Hangzhou, is a growth-oriented team passionate about technology and craftsmanship. With around 500 members, we are building comprehensive engineering, project management, and talent development systems. We are committed to innovation and creating a cloud service ecosystem for government and enterprise procurement. We look forward to your joining us.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.