I'm trying to take a full screenshot of a webpage and noticed that Chrome has built into their devtools a command to do that. Is there a way to call this command using Javascript in the console or on the webpage?
Edit: to distinguish this question from the referenced, already-answered question on Stack Overflow, I'm asking whether a solution exists to fully capture the webpage without looking at the html and parsing that with javascript. There's apps to do this on the Chrome extension store; however, they rely on the captureVisibleTab API which isn't as fluid as the devtool command that doesn't seem to require scrolling and stitching.
Answer: In the general case, you cannot have simple Javascript in the browser call functions and methods implemented in the devtools library; primarily due to security concerns, your Javascript is sandboxed.
The one exception is if you are making a Chrome extension, where you can specify permissions to the Chrome debugger API. This API allows you to access the Chrome Devtools Protocol, which then allows you to call devtool commands. I found this through a question asking how to access the emulator on devtools. In that post, you can find an example of an extension that accesses the emulator.
As for the full-page screenshot command, I reviewed the source code for the native implementation and puppeteer implementation [1], and found a way to re-implement it for a client-side extension.
{
"name": "",
"version": "0.1.0",
"description": "",
"permissions": [
"tabs",
"debugger"
],
"manifest_version": 2,
"background": {
"scripts": ["background.js"],
"persistent": false
},
"browser_action": {
}
}
'use strict';
const protocolVersion = "1.3"
/**
* @param {!Element} canvas
*/
function saveScreenshot(canvas) {
let fileName = "hello"
const link = document.createElement('a');
link.download = fileName + '.png';
console.log(canvas)
canvas.toBlob(function(blob) {
console.log(blob)
link.href = URL.createObjectURL(blob);
link.click();
});
};
function getPNG(tabId) {
chrome.debugger.attach({
tabId: tabId
}, protocolVersion, function() {
chrome.debugger.sendCommand({
tabId: tabId
}, "Page.getLayoutMetrics", {}, function(object) {
console.log(object)
const {height, width} = object.contentSize
chrome.debugger.sendCommand({
tabId: tabId
}, "Emulation.setDeviceMetricsOverride", {height: height, width: width, deviceScaleFactor: 1, mobile: false}, function() {
console.log("hello world")
chrome.debugger.sendCommand({
tabId: tabId
}, "Page.captureScreenshot", {}, function(screenshot) {
console.log(screenshot)
const pageImage = new Image();
pageImage.src = 'data:image/png;base64,' + screenshot.data;
pageImage.onload = function() {
const canvas = document.createElement('canvas');
canvas.width = pageImage.naturalWidth;
canvas.height= pageImage.naturalHeight;
const ctx = canvas.getContext('2d');
ctx.imageSmoothingEnabled = false;
ctx.drawImage(pageImage, 0, 0);
console.log(canvas, pageImage)
saveScreenshot(canvas);
}
chrome.deugger.detach({
tabId: tabId
})
})
})
})
})
}
chrome.runtime.onInstalled.addListener(function() {
console.log("installed");
});
chrome.browserAction.onClicked.addListener(function() {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
var currTab = tabs[0];
if (currTab) {
getPNG(currTab.id)
}
});
});
[1] Puppeteer is a server-side NodeJS library to control Chromium over devtools protocol. As of the current implementation, you cannot run puppeteer in the browser with something like Webpack.