Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Call html2canvas(document.body), wait for its Promise, convert the returned canvas with toDataURL('image/png'), and trigger a download from an anchor element. This captures a DOM/CSS reconstruction in the browser—not a native, pixel-perfect browser screenshot—so same-origin or CORS-enabled images, accessible fonts, and supported CSS determine what appears in the file.
Minimal browser implementation
Install the package in a project that has a browser build step:
npm install html2canvas
Then create a function that captures the complete document body and downloads a PNG:
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Clear out junk files and repair common Windows errors3Fix the driver behind crashes, sound loss and screen glitchesimport html2canvas from '@html2canvas/html2canvas';
async function saveBodyAsPng() {
const canvas = await html2canvas(document.body);
const link = document.createElement('a');
link.download = 'body.png';
link.href = canvas.toDataURL('image/png');
link.click();
}
document.querySelector('#save-button').addEventListener('click', saveBodyAsPng);
Add a button such as <button id="save-button">Save page</button>. The call resolves to an HTMLCanvasElement; toDataURL serializes that canvas as a PNG data URL, and the anchor’s download attribute supplies the filename.
#1 Best Overall
Using html2canvas from a script tag
If you are not using npm, load the built library before your own script, using the CDN form documented by the project. The browser then exposes html2canvas globally:
<button id="save-button">Save page</button>
<script src="PATH-TO-THE-HTML2CANVAS-BUILD.js"></script>
<script>
async function saveBodyAsPng() {
const canvas = await html2canvas(document.body);
const link = document.createElement('a');
link.download = 'body.png';
link.href = canvas.toDataURL('image/png');
link.click();
}
document.querySelector('#save-button').addEventListener('click', saveBodyAsPng);
</script>
Replace the script path with the version you have chosen; do not run your code before the library has loaded.
Make the capture match what the user should see
Wait for fonts, images, and application state
Invoke the function only after your page has rendered its final state. In an application, that usually means after data requests finish and the relevant component is visible. For fonts, you can wait for the browser’s font set:
await document.fonts.ready;
const canvas = await html2canvas(document.body);
Lazy images that have not loaded when cloning starts may be absent. Scroll or otherwise trigger your lazy-loading logic first, or wait until the required image elements report completion.
Increase density on high-DPI displays
Pass the device pixel ratio as scale when you want more output pixels on a high-density display:
const canvas = await html2canvas(document.body, {
scale: window.devicePixelRatio
});
A larger scale also creates a larger canvas and data URL. For very long pages, monitor memory use and consider capturing a smaller region or using a server-side workflow.
Rank #2
- HTML CSS Design and Build Web Sites
- Comes with secure packaging
- It can be a gift option
Capture only a rectangle
Use x, y, width, and height to crop the rendered area:
const canvas = await html2canvas(document.body, {
x: 0,
y: 0,
width: document.documentElement.clientWidth,
height: 800
});
The coordinates describe the region html2canvas renders from the document. For a component, selecting that element and passing it as the first argument is usually simpler:
const card = document.querySelector('.invoice-card');
const canvas = await html2canvas(card);
Exclude controls and private UI
Add data-html2canvas-ignore to any element that should not be included:
<button data-html2canvas-ignore>Save page</button>
This is useful for capture buttons, floating help controls, cookie notices, and temporary status messages. The library also documents cloning/configuration hooks for more advanced exclusion rules.
Build a reusable download helper
async function downloadBody(filename = 'body.png') {
try {
await document.fonts.ready;
const canvas = await html2canvas(document.body, {
scale: window.devicePixelRatio,
backgroundColor: '#ffffff'
});
const link = document.createElement('a');
link.download = filename;
link.href = canvas.toDataURL('image/png');
link.click();
} catch (error) {
console.error('Could not capture the body', error);
}
}
Keep the function in a user-initiated click handler where possible. Browsers can apply stricter download behavior when code runs without a user gesture.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Cross-origin images and canvas security
When useCORS works
Set useCORS: true only when the image host sends suitable CORS response headers and the image request is otherwise permitted:
Rank #3
const canvas = await html2canvas(document.body, {
useCORS: true
});
The image server must opt in; adding the option cannot override a server’s policy. Configure the image host to allow the page’s origin (or an appropriate permitted origin) and ensure the image URL is loaded with the expected credentials policy.
When a proxy is required
If an image host cannot provide CORS headers, route the image through a proxy that you control and configure html2canvas to use that proxy according to its configuration reference. A proxy must preserve the image bytes while returning headers that let the browser use them in the canvas. Do not proxy private images without an access-control design.
Why export can fail
A cross-origin image that is drawn without permission can taint the canvas. When that happens, toDataURL may throw a security exception instead of returning a PNG. Check every image, including CSS background images and images inside components, not only the visible <img> tags.
Free tools Windows power users keep installed
One-click scans. No signup required.
Cross-origin iframes
html2canvas cannot render the contents of a cross-origin iframe because browser security prevents access to its contentDocument. You can capture the iframe element’s surrounding box, but not reconstruct the remote document inside it. A same-origin iframe can be handled only when your page has permission to access its document and you deliberately capture that document’s content.
What the resulting image represents
html2canvas reads the DOM and CSS available to the page and paints a representation into a canvas. Its documentation cautions that the result may not be 100% accurate to the real page representation. Unsupported CSS, plugin-rendered content, browser controls, and other details produced outside the accessible DOM can differ. Treat the output as a client-side rendering of page information, not as a guaranteed native browser screenshot.
The library depends on browser APIs and is intended for modern evergreen Firefox, Chromium-based browsers, and Safari. It is not suitable for Node.js by itself. A Node process has no document, layout engine, or canvas-backed browser page for this method to inspect.
Rank #4
- Brand: Wiley
- Set of 2 Volumes
- A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers
PNG, JPEG, and data-URL handling
PNG download
canvas.toDataURL('image/png') is lossless and preserves transparency where the canvas background is transparent. PNG data URLs can become large for full-page captures; the anchor method keeps the conversion entirely in the browser.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
JPEG output
For a smaller photographic image, request JPEG and provide a quality value between zero and one:
const jpegUrl = canvas.toDataURL('image/jpeg', 0.85);
const link = document.createElement('a');
link.download = 'body.jpg';
link.href = jpegUrl;
link.click();
JPEG does not preserve transparency. Choose the format based on whether sharp text/transparency (PNG) or smaller photographic files (JPEG) matters more.
Blob downloads for large captures
For a large page, prefer a Blob rather than keeping a long data URL string:
canvas.toBlob((blob) => {
if (!blob) return;
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.download = 'body.png';
link.href = url;
link.click();
URL.revokeObjectURL(url);
}, 'image/png');
The callback is asynchronous. Revoke the object URL after initiating the download so it does not remain allocated.
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchDiagnose blank or incomplete downloads
The file is blank
- Confirm the call runs after the page content is mounted, not during an earlier loading phase.
- Check that the selected element has nonzero dimensions and is not hidden by CSS.
- Inspect the console for a rejected Promise, resource-loading error, or a tainted-canvas security exception.
- Wait for fonts, application data, and images before calling html2canvas.
Images are missing
- Verify that each image URL is same-origin or served with compatible CORS headers.
- Try
useCORS: trueonly after the image server is configured for CORS. - Use a controlled proxy when the remote server cannot add the required headers.
- Remember that a cross-origin iframe’s internal document cannot be captured.
Text or layout differs
- Check whether the visual depends on CSS or browser features html2canvas does not reconstruct.
- Wait for web fonts and final layout before capture.
- Capture the specific element after its size is stable rather than capturing the entire body during an animation.
- Use
scalefor density, but do not expect it to add information that is absent from the DOM.
The browser refuses the download
Start the capture from a user click, use a normal filename, and test in the target browser. If you need to retain the result inside the application instead, keep the canvas or Blob and upload it through your own authenticated endpoint.
Best Value
When a browser-native or server capture is a better fit
Choose html2canvas when processing must remain in the user’s browser and a DOM-based approximation is acceptable. Choose a real browser screenshot service when you need a repeatable capture outside a user’s session, access to pages that your browser cannot load due to CORS, or a native rendering pipeline. Compare rendering fidelity, cross-origin permissions, browser/runtime requirements, output resolution, handling of fonts and asynchronous content, and where processing and data storage occur. html2canvas’s browser-only DOM reconstruction does not establish performance or quality benchmarks against other tools.
Or skip the browser setup
ScreenshotNeo returns a website screenshot or PDF from one request and handles the browser runtime for you. Before capture it accepts cookie/consent banners like a visitor 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 the response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.
Use the API with the target URL encoded as a query parameter:
cURL
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Python
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
Node.js
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
See the ScreenshotNeo documentation for authentication and options. The service supports full-page lazy-image loading, CSS-selector element capture, dark mode, device presets and custom viewports, retina scale, PDF paper and page controls, custom CSS/JavaScript, clicks, waits, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, TTL caching, signed links, asynchronous signed webhooks, bulk calls for up to 100 URLs, usage data, and an OpenAPI specification. Its parameter names are compatible with those used by other screenshot APIs, which can simplify migration.
Every feature is included on every plan: 1,000 screenshots per month free with no card; Starter is $5 for 3,000, Growth $15 for 15,000, Pro $39 for 60,000, Scale $99 for 250,000, and Business $249 for 1,000,000. Yearly billing provides two months free. Create a free ScreenshotNeo account to start with the 1,000 monthly screenshots and no card.
Practical checklist
- Call
html2canvasonly after the final DOM state is rendered. - Use
scalewhen output density matters and crop coordinates when the full body is unnecessary. - Mark controls with
data-html2canvas-ignore. - Resolve image CORS or proxy requirements before exporting.
- Expect cross-origin iframes and unsupported browser-rendered details to be unavailable.
- Use Blob output for very large files and revoke object URLs.
- Move to a browser screenshot service when you need automated, repeatable captures outside the page.
Frequently Asked Questions
Can html2canvas capture a page before JavaScript finishes loading?
It can capture whatever DOM and styles exist at the moment you call it, so application code must decide when the page has reached the state you want.
Does increasing scale fix missing CSS or images?
No. Scale changes output density; it cannot provide resources that failed to load or CSS that the renderer cannot reconstruct.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Can I use the same function in a Node.js script?
Not directly. html2canvas requires browser APIs and a document; a Node workflow needs a separate browser automation or screenshot service.
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.

