html2canvas
html2canvas is a client-side JavaScript library, currently at stable version 1.4.1, designed to take "screenshots" of webpages or specific DOM elements directly within the user's browser. It operates by reading the Document Object Model (DOM) and applied CSS styles to construct a canvas image, entirely on the client-side, without requiring server-side rendering. A key differentiator is its complete client-side operation, making it suitable for browser-only screenshot needs like generating certificates or tickets. However, it's important to note that it produces a DOM-based representation, which might not be 100% pixel-accurate compared to an actual screenshot, and has limitations regarding unsupported CSS properties. The project maintains a fairly active release cadence, but the README explicitly warns that it is in a "very experimental state" and not recommended for production use, implying potential instability or breaking changes. It is explicitly not suitable for Node.js environments for rendering and requires a proxy for handling cross-origin content.
Common errors
-
Failed to load image <URL>: Cross-origin images are not allowed to be loaded.
cause Attempting to render a DOM element containing images from a different origin without a proxy or CORS headers.fixEnsure cross-origin images are served with appropriate CORS headers or configure a proxy server to fetch and serve them from the same origin as your application, then specify the `proxy` option in html2canvas. Options like `allowTaint: true` and `useCORS: true` can help but do not bypass the fundamental Same-Origin Policy. -
ReferenceError: Promise is not defined
cause Running html2canvas in an environment (typically an older browser like IE11) that does not natively support JavaScript Promises.fixInclude a Promise polyfill (e.g., `es6-promise` via a script tag or npm import) before initializing html2canvas. -
Module 'html2canvas' is not ESM
cause This error can occur when importing `html2canvas` in an ESM context within a Node.js environment where it's not correctly transpiled or configured for server-side usage, despite `package.json`'s `engines` field allowing Node.js installation.fixhtml2canvas is not designed for rendering in Node.js. If you encounter this when trying to bundle for the browser, ensure your bundler (Webpack, Rollup, Parcel) is correctly configured to handle the library's module format for browser consumption. For server-side screenshot needs, use a headless browser solution. -
The generated canvas image does not perfectly match the webpage's appearance (e.g., missing shadows, incorrect fonts, misaligned elements).
cause html2canvas's DOM-based rendering mechanism has limitations and does not support all CSS properties and rendering intricacies of a browser's native rendering engine. Specific unsupported properties include `box-shadow`, `filter`, and certain `transform` effects.fixConsult the html2canvas 'Features' documentation for a list of supported and unsupported CSS properties. Adjust your CSS to use supported properties where possible, or accept that certain complex visual effects may not render identically.
Warnings
- gotcha html2canvas is explicitly stated to be in a 'very experimental state' in the official README, despite its active maintenance. This implies that APIs or internal behavior might change significantly between versions, and it may not be fully production-ready in terms of stability or comprehensive feature support. Users should test thoroughly and anticipate potential breaking changes or limitations.
- gotcha The library is designed for client-side browser usage and is 'not suitable' for use in Node.js environments for rendering. While it can be installed via npm, attempting to use its core rendering functionality server-side will fail.
- gotcha Rendering cross-origin content (e.g., images, iframes) directly will fail due to browser Same-Origin Policy restrictions. html2canvas does not circumvent these policies and requires a proxy server to load such content.
- gotcha html2canvas creates a screenshot based on the DOM structure and computed styles, not an actual pixel-by-pixel render. This means the output may not be 100% accurate to the visual representation in the browser, especially for complex CSS properties like `box-shadow`, `filter`, or certain transforms, which may not be fully supported.
- gotcha The library utilizes JavaScript Promises and expects them to be available globally. Older browsers (e.g., IE9-IE11) lack native Promise support.
Install
-
npm install html2canvas -
yarn add html2canvas -
pnpm add html2canvas
Imports
- html2canvas
import { html2canvas } from 'html2canvas';import html2canvas from 'html2canvas';
- html2canvas
const html2canvas = require('html2canvas'); - html2canvas
<script src="https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js"></script> <script> html2canvas(document.body).then(canvas => { // ... }); </script>
Quickstart
import html2canvas from 'html2canvas';
const captureAndDisplayBody = async () => {
const bodyElement = document.body;
try {
const canvas = await html2canvas(bodyElement, {
allowTaint: true, // Set to true if you are handling tainted canvases (e.g., cross-origin images without proxy)
useCORS: true, // Attempt to load images using CORS
logging: true // Enable logging for debugging
});
// Create an image element from the canvas
const img = document.createElement('img');
img.src = canvas.toDataURL('image/png');
img.alt = 'Screenshot of the page body';
img.style.maxWidth = '100%';
img.style.border = '2px solid blue';
// Append the image to the document or a specific container
document.getElementById('screenshot-container')?.appendChild(img);
console.log('Screenshot captured and displayed successfully!');
} catch (error) {
console.error('Error capturing screenshot:', error);
}
};
// Example of triggering the capture (e.g., on a button click or after DOM load)
document.addEventListener('DOMContentLoaded', () => {
const button = document.createElement('button');
button.textContent = 'Take Screenshot of Body';
button.onclick = captureAndDisplayBody;
document.body.prepend(button);
const container = document.createElement('div');
container.id = 'screenshot-container';
document.body.appendChild(container);
});