Unlock the power of Chrome extensions and elevate your web capture experience! In this step-by-step tutorial, we’ll guide you through the process of building a robust Chrome extension that effortlessly captures full-page screenshots, providing users with a seamless and enhanced browsing experience.
The tutorial will cover creating the necessary files, implementing the content script and popup script, and explaining the key components of the code.
Note : Remember that capturing full-page screenshots of all types of websites can be complex due to variations in web page structures and behaviors. This is a simplified example and might need to be adjusted based on your specific needs

Step 1: Set Up Extension Files
- Create a new folder for your extension.
- Inside the folder, create the following files:
manifest.json
contentScript.js
popup.html
popup.js
background.js
Step 2: Configure manifest.json
{ | |
"manifest_version": 3, | |
"name": "Full Page Screenshot", | |
"version": "1.0", | |
"description": "Capture Full Page Screenshot", | |
"permissions": [ | |
"activeTab", | |
"tabCapture" | |
], | |
"background": { | |
"service_worker": "background.js" | |
}, | |
"action": { | |
"default_popup": "popup.html" | |
}, | |
"content_scripts": [ | |
{ | |
"matches": ["<all_urls>"], | |
"js": ["content.js"] | |
} | |
] | |
} |
Step 3: Create popup.html
<!DOCTYPE html> | |
<html> | |
<head> | |
<style> | |
/* Inline CSS for styling */ | |
body { | |
width: 210px; | |
padding: 20px; | |
text-align: center; | |
} | |
h1 { | |
font-size: 20px; | |
} | |
button { | |
background-color: #0073e6; | |
color: #fff; | |
border: none; | |
padding: 10px 20px; | |
margin: 10px; | |
cursor: pointer; | |
} | |
button:hover { | |
background-color: #005ba4; | |
} | |
</style> | |
</head> | |
<body> | |
<!-- Heading --> | |
<h1>Take Screenshot</h1> | |
<!-- Start Button --> | |
<button id="takeScreenshotBtn">Take Screenshot</button> | |
</body> | |
<script src="popup.js"></script> | |
</html> |
Step 4: Implement content.js
// contentScript.js | |
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { | |
if (message.action === "takeScreenshot") { | |
const { scrollHeight, clientHeight } = document.documentElement; | |
const devicePixelRatio = window.devicePixelRatio || 1; | |
let capturedHeight = 0; | |
let capturedImages = []; | |
const captureAndScroll = () => { | |
const scrollAmount = clientHeight * devicePixelRatio; | |
chrome.runtime.sendMessage({ action: "captureVisibleTab", pixelRatio: devicePixelRatio }, (dataUrl) => { | |
capturedHeight += scrollAmount; | |
if (capturedHeight < scrollHeight * devicePixelRatio) { | |
capturedImages.push(dataUrl); | |
// Scroll to the next part of the page | |
window.scrollTo(0, capturedHeight); | |
setTimeout(captureAndScroll, 2000); // Adjust the delay as needed | |
} else { | |
// All parts captured, send back the complete image | |
sendResponse({ dataUrl: capturedImages }); | |
} | |
}); | |
}; | |
// Start capturing and scrolling | |
captureAndScroll(); | |
return true; | |
} | |
}); |
Step 5: Implement popup.js
document.getElementById("takeScreenshotBtn").addEventListener("click", () => { | |
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => { | |
const activeTab = tabs[0]; | |
chrome.tabs.sendMessage(activeTab.id, { action: "takeScreenshot" }, (response) => { | |
const images = response.dataUrl; | |
if (images.length === 0) { | |
console.error("No images captured."); | |
return; | |
} | |
const canvas = document.createElement("canvas"); | |
const context = canvas.getContext("2d"); | |
// Use the width of the first image to set the canvas width | |
const firstImage = new Image(); | |
firstImage.onload = () => { | |
canvas.width = firstImage.width; | |
canvas.height = images.length * firstImage.height; | |
// Counter to keep track of loaded images | |
let imagesLoaded = 0; | |
// Callback function to draw an image onto the canvas | |
const drawImageOnCanvas = (image, index) => { | |
context.drawImage(image, 0, index * firstImage.height); | |
imagesLoaded++; | |
// Check if all images are loaded | |
if (imagesLoaded === images.length) { | |
// Create a download link for the full-page screenshot | |
const link = document.createElement("a"); | |
link.href = canvas.toDataURL("image/png"); | |
link.download = "fullpage_screenshot.png"; | |
// Append the link to the document, trigger a click, and remove it | |
document.body.appendChild(link); | |
link.click(); | |
document.body.removeChild(link); | |
} | |
}; | |
// Load and draw each image onto the canvas | |
images.forEach((dataUrl, index) => { | |
const image = new Image(); | |
image.onload = () => drawImageOnCanvas(image, index); | |
image.src = dataUrl; | |
}); | |
}; | |
firstImage.src = images[0]; | |
}); | |
}); | |
}); |
Step 6: Implement background.js
// background.js | |
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { | |
if (message.action === "captureVisibleTab") { | |
const { pixelRatio } = message; | |
chrome.tabs.captureVisibleTab({ format: "png", quality: 100 }, (dataUrl) => { | |
sendResponse(dataUrl); | |
}); | |
return true; | |
} | |
}); | |
The source code for this project is available on Github.
High-Level Algorithm:
- Content Script (
contentScript.js
):- Listens for a message from the extension popup to initiate screenshot capture.
- Retrieves the dimensions of the webpage and the device pixel ratio.
- Initializes variables for tracking the captured height and storing captured images.
- Defines a function (
captureAndScroll
) to capture the visible area, scroll to the next part of the page, and repeat until the entire page is captured. - Sends a message to the background script to capture the visible tab and receives the captured image data.
- Checks for duplicate images to avoid capturing the same content multiple times.
- Scrolls to the next part of the page and continues the process until the entire page is captured.
- Sends back the complete array of captured image data to the popup.
- Popup Script (
popup.js
):- Listens for a click on the “Capture Screenshot” button in the popup.
- Queries the active tab to get its ID.
- Sends a message to the content script to initiate the screenshot capture.
- Receives the captured image data from the content script.
- Creates a canvas to stitch together the captured images.
- Sets the canvas width based on the width of the first captured image and the height based on the total height of all captured images.
- Draws each image onto the canvas, adjusting the Y-coordinate based on the index.
- Creates a download link for the full-page screenshot, triggers a click event, and removes the link from the document.
- Background Script (
background.js
):- Listens for a message from the content script with the action “captureVisibleTab.”
- Uses the
chrome.tabs.captureVisibleTab
API to capture the visible area of the tab in PNG format. - Sends the captured image data back to the content script.