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> asynchronously. Install the browser package, pass an element such as document.querySelector('#capture'), await the returned Promise, and then export or display the canvas. It reconstructs the image from the DOM and styles; it does not copy the browser’s already-rendered pixels, so unsupported CSS, cross-origin images and very large elements can produce differences or incomplete output.

What html2canvas actually does

html2canvas walks the selected element, reads its computed styles and child nodes, and paints a new canvas. The project documentation describes this limitation directly: “The screenshot is based on the DOM and as such may not be 100% accurate to the real representation as it does not make an actual screenshot, but builds the screenshot based on the information available on the page.”

This distinction determines when to use it. It is useful when code running in a page needs an image of a component, report, receipt or dashboard. It is not a pixel-level browser screenshot API. Every CSS property must be implemented by the library; the project FAQ therefore says html2canvas “will never have full CSS support.”

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

Install and capture an element

Install the package

The official getting-started guide shows the package named html2canvas and installation through npm, Yarn or pnpm:

npm install html2canvas
# or
yarn add html2canvas
# or
pnpm add html2canvas

Use it from browser code bundled by your application:

import html2canvas from 'html2canvas';

const element = document.querySelector('#capture');
if (!element) throw new Error('Capture element was not found');

const canvas = await html2canvas(element);
document.body.appendChild(canvas);

The function accepts a DOM element and an optional options object. It returns a Promise resolving to a canvas, so do not call toDataURL(), append the result or inspect dimensions until the Promise has resolved.

Display, download or obtain bytes

const canvas = await html2canvas(document.querySelector('#capture'));

// Display it somewhere else
preview.replaceChildren(canvas);

// Download a PNG
const link = document.createElement('a');
link.download = 'capture.png';
link.href = canvas.toDataURL('image/png');
link.click();

For JPEG, pass an image type and quality to toDataURL():

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
const jpeg = canvas.toDataURL('image/jpeg', 0.9);

Keep the export step on the client. A canvas containing inaccessible cross-origin image data may be tainted and refuse pixel-reading operations.

Capture options you will commonly need

Start with the default call, then add only the options that solve a demonstrated problem. The exact option behavior depends on browser support and the library version.

  • backgroundColor: Set a color when the captured element’s transparent background should become opaque. Use null when you need transparency and the rest of the rendering path supports it.
  • scale: Controls the pixel density of the output canvas. A larger value can improve detail but increases memory use and may hit browser canvas limits sooner.
  • windowWidth and windowHeight: Define the viewport dimensions used while rendering. They are especially useful when responsive CSS changes the layout or when a long element needs its scroll dimensions.
  • useCORS: Requests images with CORS enabled. It works only when the image server sends a suitable Access-Control-Allow-Origin header; it does not bypass browser security.
  • proxy: Points to a server-side proxy that retrieves remote resources and returns them in a browser-usable form. The proxy must be configured correctly and must respect the resource owner’s security policy.
  • allowTaint: Changes how cross-origin images are handled, but allowing taint does not make a tainted canvas readable. If you need PNG or JPEG bytes, solve the CORS or proxy issue instead.
  • ignoreElements: Excludes matching nodes through a predicate, useful for buttons, live controls or animated overlays that should not appear in the exported image.
  • logging: Enables diagnostic messages while reducing a reproduction case.

Check the project’s supported-features documentation for a CSS property that renders differently. An option cannot add support for a property the renderer does not implement.

Rank #2
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

Build a reliable capture workflow

  1. Capture a stable state. Wait until data, fonts and images needed by the element have loaded. Pause animations or apply a temporary class if movement makes output inconsistent.
  2. Choose the element, not the page. Select the smallest container that contains the content you need. Smaller canvases are less likely to exceed device limits.
  3. Set the intended viewport. If responsive breakpoints matter, pass matching windowWidth and windowHeight values and test each target browser.
  4. Render and inspect. Await the Promise, check canvas.width and canvas.height, and verify the result visually before uploading or downloading it.
  5. Export only after success. Call toBlob() for a Blob when possible; it avoids keeping a large base64 string in memory.
const target = document.querySelector('#capture');
const canvas = await html2canvas(target, {
  backgroundColor: '#ffffff',
  scale: Math.min(window.devicePixelRatio || 1, 2),
  windowWidth: target.scrollWidth,
  windowHeight: target.scrollHeight,
  useCORS: true
});

canvas.toBlob((blob) => {
  if (!blob) throw new Error('The browser could not encode the canvas');
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = 'element.png';
  a.click();
  URL.revokeObjectURL(url);
}, 'image/png');

The useCORS setting in this example is appropriate only when every remote image involved is served with compatible CORS headers. Remove it or fix the image server when that condition is not true.

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

Images, fonts and cross-origin content

Why images disappear

An image hosted on another origin is subject to normal browser security rules. If the response lacks an appropriate Access-Control-Allow-Origin header, the browser may prevent html2canvas from reading it, or may taint the resulting canvas so pixel export fails.

Fixes that are actually valid

  • Serve the image from the same origin as the page.
  • Configure the image host to send a suitable CORS response header, then use useCORS: true.
  • Fetch the resource through a properly configured proxy that returns it in a form the page is allowed to use.

Neither useCORS nor a proxy is a method for evading browser policy. If you do not control the remote host, replacing the image or omitting it may be the only dependable choice. Web fonts and late-loading assets should also be ready before capture; otherwise text can fall back to a different font or appear before the final layout settles.

Why the canvas differs from the live page

Differences are expected when a CSS feature is unsupported or only partly implemented. Complex filters, blending, generated content, form controls, pseudo-elements, SVG details and browser-native widgets can require a minimal test case to identify the exact limitation. Compare a reduced element against the project’s supported-features list rather than assuming a browser screenshot should match.

For a true view of browser-rendered pixels, use an actual browser screenshot mechanism instead. The official FAQ points extension authors to native extension screenshot APIs and server-side users to Puppeteer or Playwright driving a headless browser. Those tools solve a different problem: they control a browser and capture its rendered view, while html2canvas runs in the page and reconstructs a canvas.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

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

Long pages, blank output and performance limits

Canvas dimensions are limited by the browser and device. A very tall report can therefore be blank, clipped or partially painted. There is no universal safe maximum: limits vary by browser, operating system, GPU and available memory.

  • Capture a smaller element or split a long document into sections.
  • Lower scale before increasing dimensions.
  • Use windowWidth and windowHeight that match the element’s scroll dimensions when a full element capture is required.
  • Remove unnecessary images and animations from the capture.
  • Test on the least capable browser and device you support.

Large canvases consume memory both while painting and while encoding. Prefer toBlob() over a large data URL, release object URLs after download, and avoid running several full-page captures concurrently.

Browser and runtime support

The current official guide describes modern evergreen browsers, including Chrome or Chromium-based browsers, Firefox and Safari. html2canvas depends on window, document and computed styles, so it is client-side browser software, not a Node.js renderer.

Node.js applications

Importing html2canvas in a plain Node.js process will not provide the DOM and browser APIs it needs. For server-side screenshots, the FAQ names Puppeteer or Playwright with a headless browser. If your server receives a URL and must capture the page as a user would see it, use one of those browser-controlled approaches or a screenshot API.

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

Browser extensions

For an extension, the FAQ recommends the browser’s native extension screenshot APIs as the more reliable choice for that context. They capture browser-rendered pixels rather than rebuilding the page from DOM information.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. One GET request returns a PNG, JPEG, WebP or PDF, without adding html2canvas to the page:

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 documentation for all parameters. The equivalent Python and Node.js requests are:

Rank #4
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
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}`);

Before capture, ScreenshotNeo accepts cookie and consent banners and removes more than 60 known consent platforms, newsletter popups and chat widgets; each cleanup step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and response headers identify the page verdict and billing result. Its MCP server provides take_screenshot, get_page_info and capture_pdf tools for Claude, Cursor and other MCP clients. Every plan includes features such as full-page lazy-image loading, CSS-selector element capture, device presets, custom CSS and JavaScript, waits, request blocking, cookies and headers, geolocation, PDFs, signed links, async webhooks, bulk capture and a usage API. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots.

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

Create a free ScreenshotNeo account to try those 1,000 monthly screenshots without a card.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshooting checklist

“document is not defined” or import errors

You are running browser-only code in Node.js, during server-side rendering, or before the page environment exists. Move the call into client-side code after the target element is mounted, or use Puppeteer, Playwright or a screenshot API on the server.

Remote images are missing

Inspect the image response headers. Add useCORS: true only after the host sends a suitable CORS header; otherwise use same-origin assets or a properly configured proxy.

toDataURL() throws a security error

The canvas is tainted by inaccessible image data. Fix the resource’s CORS configuration or remove that asset; html2canvas cannot override the browser’s rule.

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

Styles or controls look different

Reduce the page to the smallest element that shows the difference, check whether the CSS property is supported, and replace unsupported effects with simpler styles for the export version.

The result is blank or cut off

Reduce the capture area or scale, split long content, and set viewport dimensions to the element’s scroll dimensions. Test on the target browser and device because canvas limits differ.

The capture is inconsistent

Wait for data, fonts and images; stop animations; capture one element at a time; and avoid changing layout while html2canvas is walking the DOM.

FAQ

Does html2canvas take a screenshot of the screen?

No. It reconstructs a canvas from DOM and styles, so it can differ from pixels visible in the browser.

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

Is html2canvas suitable for a server-rendered image service?

Not by itself. It requires browser APIs; use a headless browser or a screenshot service for server-side work.

Can it bypass a CAPTCHA or cross-origin restriction?

No. Browser security and the target site’s bot controls still apply.

Where can I see a visual comparison?

The project’s official examples page provides a side-by-side HTML/CSS editor and html2canvas output for experimenting with supported and unsupported behavior.

Frequently Asked Questions

Can I capture an element that is currently off-screen?

html2canvas can render an element outside the visible viewport, but the resulting dimensions still must fit browser canvas limits. For very large content, split the capture or reduce its scale.

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

Should I use the scoped @html2canvas package instead?

The available package listings do not establish that it is an official replacement for html2canvas. Follow the current project installation guidance and verify release and maintainer information before changing package names.

The Bottom Line

Use html2canvas when you need a client-side, DOM-based rendering of a manageable element and can accept differences from a real browser screenshot. Use a headless browser, extension API or ScreenshotNeo when you need browser-pixel fidelity, server-side operation or a managed capture workflow.

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.