Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import 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
Sale
HTML and CSS: Design and Build Websites
  • 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:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
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
Sale
Web Design with HTML, CSS, JavaScript and jQuery Set
  • 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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Transparent 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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
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.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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 onclone so 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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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
Sale
JavaScript and jQuery: Interactive Front-End Web Development
  • 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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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

SaleBestseller No. 1
HTML and CSS: Design and Build Websites
HTML and CSS: Design and Build Websites
HTML CSS Design and Build Web Sites; Comes with secure packaging; It can be a gift option
$15.74
SaleBestseller No. 2
Web Design with HTML, CSS, JavaScript and jQuery Set
Web Design with HTML, CSS, JavaScript and jQuery Set
Brand: Wiley; Set of 2 Volumes
$35.05
SaleBestseller No. 3
SaleBestseller No. 5
JavaScript and jQuery: Interactive Front-End Web Development
JavaScript and jQuery: Interactive Front-End Web Development
JavaScript Jquery; Introduces core programming concepts in JavaScript and jQuery; Uses clear descriptions, inspiring examples, and easy-to-follow diagrams
$24.90

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.