Cropping a Screenshot Captured with a Chrome Extension

Samuel Beaulieu
TarkaLabs TIL
Published in
2 min readApr 20, 2023

There are many reasons why cropping a screenshot is a valuable feature. You may want to remove unwanted screenshot sections or fit them into a specific format. You can get screenshots through the tabs.captureVisibleTab() method available through browser APIs.

If you have experience with Firefox extensions, you might know that you can accomplish this task with the following background script and content script:

//Background script

browser.runtime.onMessage.addListener(function (request, sender, sendResponse) {
if (request.msg === "capture_tab") {
var tabId
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
tabId = tabs[0].id
})

browser.tabs.captureVisibleTab(
tabId,
{ format: "png", quality: 100, rect: request.rect },
function (dataUrl) {
sendResponse({ imgSrc: dataUrl })
}
)
return true
}
})
//Content script
//Define a rect based on the desired left, top, width, and height
const rect = {x: 0, y: 0, width: 100, height: 100};

browser.runtime.sendMessage(
{
msg: "capture_tab"
rect: rect
},
function (response) {
//response.imgSrc is your cropped image as a data URL
}
}
)

However, unlike Firefox, Chrome’s version of the method does not support passing in a rectangle specifying the area to capture. Therefore, a few more steps are required to achieve the desired result.

As always, you need your desired rectangle’s width, height, left coordinate, and top coordinate. These variables will likely be obtained in a content script. Since content scripts cannot call captureVisibleTab(), send a message to the background service worker. This time, there is no point in sending the rectangle dimensions to the background script.

//Background script

chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
if (request.msg === "capture_tab") {
var tabId
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
tabId = tabs[0].id
})

chrome.tabs.captureVisibleTab(
tabId,
{ format: "png", quality: 100 },
function (dataUrl) {
sendResponse({ imgSrc: dataUrl })
}
)
return true
}
})

Once the service worker has captured the screenshot and sent it back to the content script as a data URL, create an Image object and give it said URL as a source. Once the image has loaded, create a canvas, get the canvas context, and use the context method drawImage() to crop the picture with your rectangle’s dimensions and coordinates.

//Content script
//Define and assign left, top, width, and height

chrome.runtime.sendMessage(
{
msg: "capture_tab"
},
function (response) {
const image = new Image()
image.src = response.imgSrc
image.onload = function () {
const canvas = document.createElement("canvas")
const scale = window.devicePixelRatio

canvas.width = width * scale
canvas.height = height * scale
const ctx = canvas.getContext("2d")

ctx.drawImage(
image,
left * scale,
top * scale,
width * scale,
height * scale,
0,
0,
width * scale,
height * scale
)

const croppedImage = canvas.toDataURL()
//Do stuff with your cropped image
}
}
)

Note that scaling is applied based on the device’s pixel ratio. captureVisibleTab() will generate a screenshot multiplied by this ratio, so your cropped image may not match your intentions if you do not account for it.

--

--