📋 Table of Contents
Setting Up Manifest V3
Chrome extensions in 2026 must use Manifest V3. To capture screenshots, your extension needs the
activeTab permission (for capturing the current tab) and optionally tabs for
broader access.
// manifest.json
{
"manifest_version": 3,
"name": "My Screenshot Extension",
"version": "1.0",
"description": "Capture screenshots of any webpage",
"permissions": [
"activeTab"
],
"action": {
"default_popup": "popup.html",
"default_icon": "icon.png"
},
"background": {
"service_worker": "background.js"
}
}
Capturing the Visible Tab
The simplest way to capture a screenshot in a Chrome extension is using the
chrome.tabs.captureVisibleTab() API. This captures exactly what the user sees in their browser
viewport as a base64-encoded PNG or JPEG data URL.
// background.js (service worker)
chrome.action.onClicked.addListener(async (tab) => {
try {
const dataUrl = await chrome.tabs.captureVisibleTab(
tab.windowId,
{ format: 'png', quality: 100 }
);
// Open the screenshot in a new tab
chrome.tabs.create({ url: dataUrl });
// Or download it directly
chrome.downloads.download({
url: dataUrl,
filename: `screenshot-${Date.now()}.png`
});
} catch (error) {
console.error('Screenshot failed:', error);
}
});
Limitations: This method only captures the visible portion of the page (the viewport). It
cannot capture content below the fold, and it doesn't work on chrome:// pages, the Chrome Web
Store, or other restricted URLs.
Full-Page Screenshots: The Hard Part
Capturing the entire scrollable page from a Chrome extension is significantly more complex. There is no
built-in captureFullPage() API. The common workaround involves:
- Injecting a content script into the page
- Programmatically scrolling the page section by section
- Capturing each viewport with
captureVisibleTab() - Stitching the resulting images together on an offscreen canvas
// content-script.js — Scroll-and-stitch approach (simplified)
async function captureFullPage() {
const totalHeight = document.body.scrollHeight;
const viewportHeight = window.innerHeight;
const captures = [];
for (let y = 0; y < totalHeight; y += viewportHeight) {
window.scrollTo(0, y);
// Wait for rendering to settle
await new Promise(r => setTimeout(r, 300));
// Request the background script to capture this viewport
const dataUrl = await chrome.runtime.sendMessage({ action: 'capture' });
captures.push({ dataUrl, y });
}
// Scroll back to the top
window.scrollTo(0, 0);
return captures; // Stitch these in an offscreen canvas
}
This approach is fragile. Sticky headers, position-fixed elements, and CSS animations can cause visual artifacts like duplicated navbars or misaligned sections between stitched segments.
Using a Screenshot API for Advanced Captures
For reliable full-page captures, element-specific captures, or dark-mode screenshots, the cleanest solution is to call a Screenshot API from your extension's background service worker. This avoids all the scrolling/stitching complexity.
// background.js — Using SnapAPI for full-page captures
chrome.action.onClicked.addListener(async (tab) => {
const apiUrl = new URL('https://snapapi.alterra-solutions.com/v1/screenshot');
apiUrl.searchParams.append('url', tab.url);
apiUrl.searchParams.append('full_page', 'true');
apiUrl.searchParams.append('format', 'png');
apiUrl.searchParams.append('api_key', 'YOUR_API_KEY');
try {
const response = await fetch(apiUrl.toString());
const blob = await response.blob();
const dataUrl = await blobToDataUrl(blob);
// Download the full-page screenshot
chrome.downloads.download({
url: dataUrl,
filename: `fullpage-${Date.now()}.png`
});
} catch (error) {
console.error('API screenshot failed:', error);
}
});
function blobToDataUrl(blob) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onloadend = () => resolve(reader.result);
reader.onerror = reject;
reader.readAsDataURL(blob);
});
}
This approach gives you pixel-perfect full-page screenshots without any scrolling hacks, works on sites with
complex sticky headers, and even lets you add parameters like dark_mode=true or
device=mobile for advanced captures.
Power Your Chrome Extension with SnapAPI
100 free screenshots per month. Add full-page capture to your extension in minutes.
Get Started Free →