The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
html2canvas turns a DOM element into a <canvas> in the browser. Install the package, select an element, await html2canvas(element, options), then display or export the resulting canvas. It reconstructs the page from DOM and CSS; it does not take a native, pixel-for-pixel browser screenshot. That distinction explains most rendering differences, missing images and browser-only limitations.
Install html2canvas and take your first capture
Use the current package name in your application’s package manager:
npm install @html2canvas/html2canvas
# or: yarn add @html2canvas/html2canvas
# or: pnpm add @html2canvas/html2canvas
Then capture an element after it exists in the document:
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errorsimport html2canvas from '@html2canvas/html2canvas';
const element = document.querySelector('#capture');
const canvas = await html2canvas(element);
document.body.appendChild(canvas);
The API is html2canvas(element, options?). It returns a Promise that resolves to a canvas. In a module, put the call inside an async function or use top-level await where your bundler permits it. Check that querySelector did not return null; otherwise the call fails before rendering.
#1 Best Overall
- HTML CSS Design and Build Web Sites
- Comes with secure packaging
- It can be a gift option
A complete button example
<button id="save">Save card</button>
<article id="capture">
<h1>Release notes</h1>
<p>This card will be rendered to an image.</p>
</article>
<script type="module">
import html2canvas from '@html2canvas/html2canvas';
document.querySelector('#save').addEventListener('click', async () => {
const element = document.querySelector('#capture');
const canvas = await html2canvas(element);
document.body.appendChild(canvas);
});
</script>
Save the canvas as a PNG
Call toDataURL('image/png'), create a temporary link and trigger it:
const canvas = await html2canvas(document.querySelector('#capture'));
const link = document.createElement('a');
link.download = 'screenshot.png';
link.href = canvas.toDataURL('image/png');
link.click();
This works only while the canvas is readable. A cross-origin image without appropriate CORS handling can taint the canvas, causing toDataURL to throw a security error even if the image appeared on screen.
JPEG, WebP and a Blob
PNG is lossless and supports transparency. For a smaller photographic file, request JPEG or WebP when supported by the browser:
Recommended Free Tools
const canvas = await html2canvas(document.querySelector('#capture'));
canvas.toBlob(blob => {
if (!blob) return;
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.download = 'screenshot.webp';
link.href = url;
link.click();
URL.revokeObjectURL(url);
}, 'image/webp', 0.9);
Crop a region and control sharpness
Use x, y, width and height to define the render area. Coordinates are relative to the document viewport used for the render. The scale option controls output resolution and defaults to the browser’s device-pixel ratio in the documented options.
const canvas = await html2canvas(document.querySelector('#capture'), {
x: 100,
y: 100,
width: 400,
height: 300,
scale: window.devicePixelRatio,
});
A higher scale produces sharper text but increases memory use and output size. For predictable files across displays, choose an explicit value such as 1 or 2 rather than inheriting each user’s monitor density.
Capture a full page or a long element
Pass the page container (or document.body) for a broad capture. Long documents can exceed browser canvas limits, so provide their scroll dimensions:
Rank #2
- 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
const element = document.querySelector('#article');
const canvas = await html2canvas(element, {
windowWidth: element.scrollWidth,
windowHeight: element.scrollHeight,
});
Evergreen browsers have rough guidance of about 32,767 pixels per dimension for Chrome/Chromium, Firefox and desktop Safari, with separate area limits and device-dependent behavior, especially on iOS Safari. These are not guarantees. A very tall capture may be blank, clipped or partially rendered without an exception. Split the page into sections when it approaches those dimensions.
Outdated 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 matchWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallTransparent backgrounds, cloned pages and excluded controls
Transparent output
Set backgroundColor: null when the image should retain transparency:
const canvas = await html2canvas(element, { backgroundColor: null });
Change only the render copy
onclone receives the cloned document used for rendering. Hide a button, expand a collapsed panel or adjust a style there without changing the live page:
const canvas = await html2canvas(element, {
onclone: clonedDocument => {
clonedDocument.querySelector('.print-only').style.display = 'block';
clonedDocument.querySelector('.share-button').style.display = 'none';
},
});
Ignore elements
Add data-html2canvas-ignore to markup you never want rendered:
<button data-html2canvas-ignore>Edit</button>
Or use a predicate for dynamic rules:
const canvas = await html2canvas(element, {
ignoreElements: node => node.matches('.ad, .cookie-controls'),
});
Why images are missing: CORS and browser security
Images hosted on another origin are the most common cause of missing content or an unusable canvas. Set useCORS: true only helps when the image server sends an appropriate CORS response header. The server, not html2canvas, must permit your page’s origin.
const canvas = await html2canvas(element, {
useCORS: true,
});
If you control the image server, configure it to return an Access-Control-Allow-Origin value that includes your site (or a deliberately appropriate wildcard for non-credentialed assets). If you do not control it, route the image through a same-origin proxy that accepts a ?url= parameter and returns the resource with safe headers. allowTaint permits tainted images to be drawn, but it does not bypass browser content policy; a tainted canvas still cannot be exported.
Rank #3
Cross-origin iframes cannot be read. Same-origin iframes can be traversed recursively. Sandboxed frames without allow-same-origin, Flash and Java applets are not rendered.
What html2canvas can and cannot reproduce
The renderer walks the DOM, reads computed styles and implements CSS properties individually. It is therefore a DOM reconstruction, not a capture of the compositor’s final pixels. Unsupported or partially implemented CSS can differ from what you see in the browser. Browser extensions, video frames, plugins and content hidden behind cross-origin boundaries may not appear.
- Good fit: a user-triggered preview, invoice, chart or card rendered from accessible DOM in the current browser.
- Risky: exact visual regression testing, pages dependent on cross-origin assets, complex filters or embedded third-party frames.
- Not a server renderer: it requires browser APIs and is not suitable for Node.js by itself.
Run screenshot jobs in Node.js
Node.js has no DOM, layout engine or canvas environment equivalent to a user’s browser. Use a real browser automation tool such as Puppeteer or Playwright for server-side jobs. Those tools launch Chromium (or another supported browser), navigate to the URL and capture the browser’s pixels. Choose this route when you need scheduled jobs, a backend API, authentication flows or repeatable viewport settings.
Use html2canvas in the browser when the capture is initiated by a user and the page’s same-origin policy is acceptable. Use a headless browser when the job must run without a user’s tab or must reproduce the browser compositor rather than reconstructing DOM.
Or skip the browser setup
ScreenshotNeo provides a website screenshot API and MCP server. One GET request returns PNG, JPEG, WebP or PDF, so there is no DOM integration, bundler configuration or browser process to maintain.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
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)
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. Before capture it accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups and chat widgets. Bot checks, blank pages, timeouts, failed loads and cache hits are not billed; response headers identify the page verdict and billing status. Its MCP server includes take_screenshot, get_page_info and capture_pdf for Claude, Cursor and other MCP clients. The Free plan includes 1,000 screenshots each month without a card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.
Performance, reliability and cost decisions
Keep browser captures manageable
- Capture the smallest element that meets your requirement instead of the entire document.
- Use an explicit scale and avoid unnecessary high-resolution canvases.
- Wait until fonts, images and asynchronous data have loaded before calling the API.
- For long pages, split captures and stitch them outside the browser rather than creating one enormous canvas.
- Remove animations and blinking cursors in
oncloneso timing does not change the output.
Choose based on fidelity and execution location
| Requirement | Suitable approach | Reason |
|---|---|---|
| Capture a user-visible DOM card in a browser | html2canvas | No server rendering; direct access to the current DOM. |
| Exact browser pixels, third-party frames or backend scheduling | Puppeteer or Playwright | Drives a real browser and can run on a server. |
| Managed URL-to-image/PDF requests and AI-agent workflows | ScreenshotNeo | One API request, cleaning controls and usage-based billing. |
No authoritative performance benchmark establishes a universal html2canvas speed or accuracy percentage. Rendering time depends on DOM size, images, fonts, device memory and scale.
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 →Rank #4
Troubleshooting checklist
The call throws because the element is missing
Ensure the selector matches and run the capture after the component mounts. Log the value returned by document.querySelector before calling html2canvas.
The image is blank or cut off
Inspect canvas dimensions and reduce scale or the capture region. For a long element, set windowWidth and windowHeight to its scroll dimensions. If the result is still blank, split the capture to stay below platform dimension and area limits.
Images disappear
Confirm that the image URL is reachable, then try useCORS: true. Verify the image response contains a suitable CORS header. Otherwise use a same-origin proxy; allowTaint is not a policy bypass.
toDataURL reports a security error
A resource tainted the canvas, usually a cross-origin image. Fix the server headers or proxy the asset before exporting.
Styles do not match the page
Check whether the CSS feature is supported by html2canvas. Simplify unsupported effects, provide a fallback style in onclone, or switch to a real-browser screenshot for compositor-level fidelity.
An iframe is empty
Only same-origin frames can be inspected. A cross-origin or restrictive sandbox frame must be captured separately by a service that can access it, or omitted.
Best Value
- JavaScript Jquery
- Introduces core programming concepts in JavaScript and jQuery
- Uses clear descriptions, inspiring examples, and easy-to-follow diagrams
Fonts or data are missing intermittently
Start the capture after web fonts resolve and asynchronous content has rendered. A user click, an explicit loading state or a short application-level wait is more reliable than assuming navigation has finished.
FAQ
Does html2canvas take a screenshot of the monitor?
No. It reconstructs the selected DOM and styles into a canvas, so the output can differ from the browser’s final pixels.
Can I use it without a framework?
Yes. Use the documented CDN build or import the package in any page with a module-capable bundler; the library does not require React, Vue or another framework.
Can a user export a canvas containing a remote image?
Only when that image is permitted by CORS or delivered through a same-origin proxy. Otherwise browser security can prevent export.
Should I use html2canvas for automated visual regression tests?
Use a real-browser capture for tests that require compositor-level pixels, cross-origin frames or browser features html2canvas does not implement. html2canvas is better for in-page, user-facing exports.
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.

