Frontend Development 15 min read

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.

政采云技术
政采云技术
政采云技术
Understanding the Chrome DevTools Protocol (CDP) for Remote Debugging

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=./test

Puppeteer

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

JavaScriptWebSocketProtocolremote-debuggingChrome DevToolsCDP
政采云技术
Written by

政采云技术

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.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.