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.
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.
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:
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
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.
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 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);
});
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
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 are language wrapper around the chrome devtool protocol
Node:
Php:
C++ library:
More:
Higher level library based on the Protocol Driver Library