Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Scan for outdated or missing drivers - takes under a minute3Repair Windows errors before they cause bigger problemsSome links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
First decide what your app must capture. This tutorial captures an element inside a page you control: html2canvas reconstructs that DOM element as a canvas, then JavaScript exports the canvas as a PNG download. It does not capture the browser’s actual pixels or the current tab. For a browser extension that captures the visible tab, use the browser’s native extension API instead.
Choose the right capture method
| Requirement | Recommended approach | What to expect |
|---|---|---|
| Capture an element in your own page | html2canvas | DOM and styles are reconstructed into a canvas; rendering can differ from the browser’s pixels. |
| Capture the currently visible browser tab | Native extension capture API | Use APIs such as chrome.tabs.captureVisibleTab(); this is generally more reliable for extensions than DOM reconstruction. |
html2canvas documents its reconstruction model and limitations in its documentation. It runs in the browser, not in Node.js.
Build the page
1. Create a small project
mkdir screenshot-downloader
cd screenshot-downloader
npm init -y
npm install @html2canvas/html2canvas
The package name is @html2canvas/html2canvas. Add an HTML page containing the content to capture and a button that starts the download.
Free tools Windows power users keep installed
One-click scans. No signup required.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Screenshot downloader</title>
<style>
body { font-family: system-ui, sans-serif; margin: 2rem; }
#capture { max-width: 720px; padding: 2rem; color: #172033; background: #eef3ff; border-radius: 16px; }
button { margin-top: 1rem; padding: .7rem 1rem; cursor: pointer; }
</style>
</head>
<body>
<section id="capture">
<h1>A downloadable card</h1>
<p>This element is rendered to a PNG by html2canvas.</p>
</section>
<button id="download" type="button">Save as image</button>
<script type="module" src="./app.js"></script>
</body>
</html>
2. Render the element and download PNG
Call html2canvas(element, options), wait for its Promise, convert the returned canvas with toDataURL('image/png'), and click a temporary anchor whose download attribute supplies the filename. This follows the project’s getting-started and example flow.
#1 Best Overall
import html2canvas from '@html2canvas/html2canvas';
const button = document.querySelector('#download');
const target = document.querySelector('#capture');
button.addEventListener('click', async () => {
button.disabled = true;
try {
const canvas = await html2canvas(target, {
backgroundColor: null,
scale: window.devicePixelRatio
});
const png = canvas.toDataURL('image/png');
const link = document.createElement('a');
link.href = png;
link.download = 'capture.png';
link.click();
} catch (error) {
console.error('Screenshot failed', error);
alert('The image could not be exported. Check cross-origin resources and canvas size.');
} finally {
button.disabled = false;
}
});
Serve the project through your normal development server so the module import resolves; opening an arbitrary file URL can trigger browser module restrictions.
Capture a region or clean up the output
Crop to coordinates
Pass x, y, width, and height to capture a region rather than the whole target. Measure coordinates relative to the element you are rendering and test them against your layout.
const canvas = await html2canvas(target, {
x: 20,
y: 10,
width: 640,
height: 360
});
Increase pixel density
scale: window.devicePixelRatio can produce a higher-density image on a retina display. Larger scales also increase memory use, so test the actual devices and content sizes you support.
Rank #2
Exclude controls
Add data-html2canvas-ignore to an element that should not appear in the output, such as the download button:
<button id="download" data-html2canvas-ignore>Save as image</button>
These options are documented in the project examples; they are controls to test, not guarantees of identical rendering in every browser.
Handle limitations before shipping
It is not a pixel screenshot
html2canvas traverses available DOM and style information. Unsupported or incomplete CSS, fonts, filters, pseudo-elements, and browser-specific behavior can make the image differ from what users see. If pixel fidelity is essential, use a native browser capture path instead.
Cross-origin images and iframes
Images from another origin can taint the canvas and prevent reading or exporting its pixels. You may try useCORS: true, but the remote server must permit the request; the option cannot override its policy.
const canvas = await html2canvas(target, {
useCORS: true
});
Cross-origin iframes cannot be read by html2canvas because of browser security boundaries. Proxy assets through an origin you control or omit them from the capture.
Very large pages
Browser and platform canvas limits vary. Oversized canvases can become blank or partial without a useful error. Start with realistic dimensions, check that canvas.width and canvas.height are non-zero, and offer smaller regions or multiple captures when necessary.
Rank #4
Wait for content
Capture only after images, fonts, and client-rendered content are ready. In your application, disable the button while loading and provide a visible failure message rather than silently downloading an empty file.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.When you need a browser extension
An extension that captures the visible tab solves a different problem. The html2canvas FAQ recommends native screenshot APIs for extensions, including chrome.tabs.captureVisibleTab() for Chrome, Edge, and Opera; verify the current API and manifest requirements in the target browser’s official documentation.
If the extension saves the returned image through Chrome’s downloads API, declare the downloads permission in the manifest. Permissions can produce user warnings, so request only what the feature needs. See Chrome’s downloads API and permissions list.
Best Value
{
"manifest_version": 3,
"name": "Visible tab saver",
"version": "1.0.0",
"permissions": ["activeTab", "downloads"],
"action": { "default_popup": "popup.html" }
}
Use the native capture route when the requirement is “what is visible in the tab.” Use html2canvas when the requirement is “render this app-owned DOM element.”
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. One request returns a PNG, JPEG, WebP, or PDF, so you do not have to maintain browser automation for a URL.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo API documentation for parameters and response handling. Before capture it accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Sign up for the free ScreenshotNeo plan to try it without a card.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

