Table of Contents

Chrome DevTool protocol (CDP)

About

The Chrome DevTool protocol (CDP) is a API that permits to call browsers implementing the CDP api (chrome of course but also any other browser implementation 1)) via json RPC.

The protocol is used to communicate with Chrome and drive the headless browser instance.

Usage

This is a low level api. The webdriver API or puppeteer like API are higher level API based on this protocol that are easier to use to control a browser.

API

The API is divided into a number of domains (DOM, Debugger, Network etc.). Chrome DevTools protocol has APIs to interact with many different parts of the browser. These parts are called Targets such as:

where:

Start Sequence

Enabling the DevTools protocol

To enable the DevTools protocol, you need to start chrome with the –remote-debugging-port flag

google-chrome-stable --headless --remote-debugging-port=9222 &

# With the UI
google-chrome --remote-debugging-port=9222

If the port is 0, the CDP server prints its WebSocket URL to stdout and the client need to parses it to get the port.

Example:

DevTools listening on ws://127.0.0.1:36775/devtools/browser/a292f96c-7332-4ce8-82a9-7411f3bd280a

Test that it's up

Since you don't have browser UI to see the page, you can navigate to http://localhost:9222 in another browser to check that everything is working.

You should see a list of inspectable pages where you can click through and see what Headless is rendering.

Client Connection and request

Example

Directly via Websocket

Create a websocket and issue CDP commands. 2)

const ws = new WebSocket(browser.wsEndpoint(), {perMessageDeflate: false});
await new Promise(resolve => ws.once('open', resolve));
console.log('connected!');

ws.on('message', msg => console.log(msg));

console.log('Sending Target.setDiscoverTargets');
ws.send(JSON.stringify({
    id: 1,
    method: 'Target.setDiscoverTargets',
    params: {
      discover: true
    },
}));

With a CDP driver library

With the chrome-remote-interface CDP driver 3)

const execFile = require('child_process').execFile;
function launchHeadlessChrome(url, callback) {
  // Assuming MacOSx.
  const CHROME = '/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome';
  execFile(CHROME, ['--headless', '--disable-gpu', '--remote-debugging-port=9222', url], callback);
}

launchHeadlessChrome('https://www.chromestatus.com', (err, stdout, stderr) => {
  ...
});
const CDP = require('chrome-remote-interface');
CDP((client) => {
  // Extract used DevTools domains.
  const {Page, Runtime} = client;

  // Enable events on domains we are interested in.
  Promise.all([
    Page.enable()
  ]).then(() => {
    return Page.navigate({url: 'https://example.com'});
  });

  // Evaluate outerHTML after page has loaded.
  Page.loadEventFired(() => {
    Runtime.evaluate({expression: 'document.body.outerHTML'}).then((result) => {
      console.log(result.result.value);
      client.close();
    });
  });
}).on('error', (err) => {
  console.error('Cannot connect to browser:', err);
});

Tools

Cli / Repl

The chrome-remote-interface has a client 4) that permits to run as a client.

yarn global add chrome-remote-interface
# or
npm install -g chrome-remote-interface

It is possible to perform command execution (repl) and event binding, using the chrome-remote-interface inspect inspect subcommand

Protocol Monitor

To see all CDP command that performs the chrome browser, you can use the protocol-monitor. It provides a way to view all the CDP requests and responses made by DevTools.

Library

Protocol Driver Library

Library are language wrapper around the chrome devtool protocol

Node:

Php:

C++ library:

More:

Higher Library

Higher level library based on the Protocol Driver Library