To capture a modal with html2canvas, select the modal after it is visible, call await html2canvas(modalElement, options), then export the returned canvas as a PNG. Capturing the modal element—not the whole document—keeps the result focused, but fixed positioning, scrollable content, cross-origin images, unsupported CSS, and canvas-size limits need explicit handling.
What html2canvas actually captures
html2canvas reconstructs the selected DOM tree and its computed CSS in a new canvas inside the browser. It is not a native operating-system screenshot and does not capture pixels exactly as a browser compositor or screen-grab API would. The project describes it as taking “screenshots” of webpages or parts of them directly in the user’s browser.
That distinction explains most surprises: the cloned render can differ from the live modal when a CSS feature is unsupported, an image cannot be read because of browser security rules, or the virtual window is smaller than the dialog’s content.
Basic modal capture and PNG download
Install the library
For an npm-based application, install the current package with:
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →#1 Best Overall
- Easily record quick videos of your screen and camera that offer the same connection as a meeting without the calendar wrangling
- Draw on your screen as you record video with customizable arrows, squares, and step numbers to emphasize important information
- Provide clear feedback and explain complex concepts with easy-to-use professional mark-up tools and templates
- Instantly create a shareable link where your viewers can leave comments and annotations or upload directly to the apps you use every day
- Version Note: This listing is for Snagit 2024. Please note that official technical support and software updates for this version are scheduled to conclude on December 31, 2026.
npm install @html2canvas/html2canvas
Import it in your application, or load the browser build according to your bundler’s normal dependency rules.
Capture the visible element
Keep the dialog open and wait until its final layout is on screen. The following example captures a modal with the ID my-modal, preserves transparency, requests high-density output, and sizes the virtual window to the modal’s scrollable dimensions.
import html2canvas from '@html2canvas/html2canvas';
async function downloadModal() {
const modal = document.querySelector('#my-modal');
if (!(modal instanceof HTMLElement)) {
throw new Error('Modal #my-modal was not found');
}
const canvas = await html2canvas(modal, {
backgroundColor: null,
scale: window.devicePixelRatio,
useCORS: true,
windowWidth: modal.scrollWidth,
windowHeight: modal.scrollHeight,
});
canvas.toBlob((blob) => {
if (!blob) {
throw new Error('The browser could not create a PNG blob');
}
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = 'modal.png';
link.click();
URL.revokeObjectURL(url);
}, 'image/png');
}
document.querySelector('#download-modal')?.addEventListener('click', downloadModal);
toBlob() is preferable when you want a file or upload stream. If you need an inline data URL instead, use canvas.toDataURL('image/png'):
const dataUrl = canvas.toDataURL('image/png');
window.open(dataUrl, '_blank');
A reliable capture sequence
- Open the modal. Do not capture a hidden element with
display:none; it has no usable layout to reconstruct. - Wait for the final state. Finish opening animations, render asynchronous content, and wait for images or fonts your design requires.
- Select the modal root. Use an ID, a class selector, or your framework’s element ref.
- Measure the content. Read
scrollWidthandscrollHeightwhen the dialog can scroll or contains content taller than its viewport. - Call html2canvas. Pass only the options needed for positioning, image loading, output scale, and exclusions.
- Export the canvas. Choose
toBlob()for a downloadable file or upload, andtoDataURL()for a data URL.
Preventing a cropped modal
Scrollable or tall dialogs
A modal may have a small visible viewport while its content is much taller. Set the virtual window to the element’s scroll dimensions:
const modal = document.querySelector('#my-modal');
const canvas = await html2canvas(modal, {
windowWidth: modal.scrollWidth,
windowHeight: modal.scrollHeight,
});
This gives the cloned render enough virtual space for the full dialog. If you intentionally want only the visible viewport, omit these dimensions and capture the element at its displayed size.
Fixed-position dialogs
Fixed elements are positioned relative to the browser viewport. When the page has been scrolled, pass the offsets used by the live layout so the cloned render places the modal correctly:
Rank #2
- Record videos and take screenshots of your computer screen including sound
- Highlight the movement of your mouse
- Record your webcam and insert it into your screen video
- Edit your recording easily
- Perfect for video tutorials, gaming videos, online classes and more
const canvas = await html2canvas(modal, {
scrollX: window.scrollX,
scrollY: window.scrollY,
windowWidth: modal.scrollWidth,
windowHeight: modal.scrollHeight,
});
Use the offsets that match the state in which the dialog is visible. If the modal is inside a scrolling container, inspect that container’s scroll position as well; changing only the document’s offsets cannot correct a separately scrolling element.
Animations and transitions
Capture after the opening transition has finished. A simple approach is to wait for a known class or a short, UI-specific delay:
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →await new Promise((resolve) => requestAnimationFrame(() => resolve()));
const modal = document.querySelector('#my-modal');
const canvas = await html2canvas(modal);
For deterministic output, disable transitions on a capture-only class, wait for images to complete, and then remove the class after export.
Images inside the modal: same-origin, CORS, and proxies
Images hosted on the same origin normally work. An image from another origin must be served with an appropriate Access-Control-Allow-Origin response header. Set useCORS: true only when that server-side permission exists:
const canvas = await html2canvas(modal, {
useCORS: true,
});
useCORS does not bypass browser security. If the image server sends no CORS permission, use a server-side proxy that fetches the asset and serves it from an allowed origin, or host the asset on the same origin as the page. A canvas containing unreadable cross-origin pixels becomes tainted, so export methods such as toBlob() or toDataURL() can fail.
Check the browser’s Network and Console panels for blocked image requests and CORS errors. Also verify that CSS background images—not only <img> elements—come from an origin that permits access.
Rank #3
- Screen capture software records all your screens, a desktop, a single program or any selected portion
- Capture video from a webcam, network IP camera or video input device
- Use video overlay to record your screen and webcamsimultaneously
- Intuitive user interface to allow you to get right to video recording
- Save your recordings to ASF, AVI, and WMV
Improving output quality without exhausting memory
Use an appropriate scale
The default scale is based on the device pixel ratio. You can set it explicitly:
const scale = Math.min(window.devicePixelRatio || 1, 2);
const canvas = await html2canvas(modal, { scale });
A larger scale produces more pixels and sharper text, but memory use rises with the square of the scale. A very large or very tall modal can exceed a browser’s canvas dimensions; limits vary by browser and device. The result may be blank or partial without a useful exception. Reduce scale, capture a smaller region, or split a very tall dialog into sections.
Choose a background deliberately
backgroundColor: nullkeeps transparent areas transparent.- A CSS color such as
'#ffffff'gives a predictable opaque background for documents and previews.
Exclude transient controls
Add data-html2canvas-ignore to controls that should not appear in the image:
<button data-html2canvas-ignore>Close</button>
<button data-html2canvas-ignore>Copy</button>
You can also exclude nodes programmatically with an ignore predicate:
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteWindows 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 reinstallconst canvas = await html2canvas(modal, {
ignoreElements: (element) => element.matches('.capture-exclude'),
});
Use this for close icons, copy buttons, loading spinners, focus hints, or other UI that is useful interactively but not in a saved image.
CSS and layout differences
html2canvas reads the DOM and computed styles, then implements a supported subset of CSS. Common layout usually reproduces well, but test the exact browsers and effects your application supports. Complex filters, transforms, unusual layout properties, and browser-specific rendering can differ from the live modal. If a visual effect is essential, replace it temporarily with a simpler capture style or validate the output in each target browser.
Rank #4
- Capture video directly to your hard drive
- Record video in many video file formats including avi, wmv, flv, mpg, 3gp, mp4, mov and more
- Capture video from a webcam, network IP camera or a video input device (e.g.: VHS recorder)
- Screen capture software records the entire screen, a single window or any selected portion
- Digital zoom with the mouse scroll wheel, and drag to scroll the recording window
Troubleshooting checklist
The output is blank or only partly rendered
- Log
canvas.widthandcanvas.height. A zero or unexpectedly huge value points to hidden layout or canvas-size problems. - Lower
scaleand capture a smaller region if the modal is very large. - Confirm the modal is visible and has nonzero dimensions when the call starts.
- Wait for asynchronous content and images before capturing.
The modal is cropped
- Set
windowWidth: modal.scrollWidthandwindowHeight: modal.scrollHeightfor tall or scrollable content. - Provide the correct
scrollXandscrollYfor fixed-position layouts. - Check whether an inner scrolling container, rather than the document, owns the scroll position.
Images are missing or export throws a security error
- Confirm same-origin URLs, or configure the image server’s CORS headers.
- Use
useCORS: trueonly with a server that permits your page’s origin. - Use a CORS-capable proxy or same-origin asset hosting when you cannot change the remote server.
- Inspect CSS background images as well as image elements.
CSS does not match the live modal
Check unsupported filters, transforms, fonts, and layout features. Simplify the capture-only style and compare results in the browsers you support.
Close buttons or overlays appear in the image
Mark them with data-html2canvas-ignore or match them in ignoreElements.
Free tools Windows power users keep installed
One-click scans. No signup required.
The capture runs before content is ready
Move the call behind the modal’s “open” state, await your data fetch, and wait for required images:
async function waitForImages(root) {
const images = [...root.querySelectorAll('img')];
await Promise.all(images.map((image) => {
if (image.complete) return Promise.resolve();
return new Promise((resolve) => {
image.addEventListener('load', resolve, { once: true });
image.addEventListener('error', resolve, { once: true });
});
}));
}
await waitForImages(modal);
const canvas = await html2canvas(modal);
Performance and reliability decisions
- Capture scope: selecting the modal is faster and less error-prone than cloning the entire page.
- Pixel count: keep scale and dimensions as low as your output requires; high-DPI captures consume substantially more memory.
- Asset readiness: wait for images and final layout instead of retrying a half-rendered capture.
- Browser coverage: test the CSS effects and canvas dimensions used by your real audience.
- Export choice: use Blob output for file workflows and data URLs for small, immediate previews.
Or skip the browser setup
If you need a server-rendered screenshot rather than a DOM reconstruction, ScreenshotNeo accepts one GET request and returns a PNG, JPEG, WebP, or PDF. It can capture a page or a single element by CSS selector, wait for a selector, delay, or network idle, load lazy images, apply custom CSS or JavaScript, set viewport and device options, and hide selectors. These options are useful when reproducing a modal requires a real browser session instead of html2canvas’s supported CSS subset.
Example request (see the ScreenshotNeo API documentation for all parameters):
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}`);
const buffer = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then((fs) => fs.writeFile('shot.webp', buffer));
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, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account to try it.
When to use html2canvas versus a browser screenshot service
| Need | html2canvas | ScreenshotNeo |
|---|---|---|
| Capture an element already rendered in the user’s page | Directly select the DOM node and export locally | Requires a URL reachable by the service |
| Exact browser-compositor fidelity | Can differ for unsupported CSS and cross-origin assets | Uses a browser capture workflow for the requested page |
| Cross-origin image handling | Requires CORS or a proxy | Handles the target page server-side |
| Client-side privacy and no upload | Rendering stays in the browser | Page is requested by the API |
| Automation and batch work | You build the browser-side orchestration | Supports async jobs, signed webhooks, bulk capture of up to 100 URLs per call, caching with a chosen TTL, and a usage API |
Use html2canvas when the modal is already in your application and a client-side image is the goal. Use a service when you need repeatable server-side captures, real browser rendering, or automation across many URLs.
Best Value
- 【1080P HD High Quality】Capture resolution up to 1080p for video source and it is ideal for all HDMI devices such as PS4, PS3, Xbox One, Xbox 360, Wii U, DVDs, DSLR, Camera, Security Camera and set top box. Note: Video input supports 4K30/60Hz and 1080p120/144Hz. Does not support 4K120Hz/144Hz. Output supports up to 2K30Hz.
- 【Plug and Play】No driver or external power supply required, true PnP. Once plugged in, the device is identified automatically as a webcam. Detect input and adjust output automatically. Won't occupy CPU, optional audio capture. No freeze with correct setting.
- 【Compatible with Multiple Systems】suitable for Windows and Mac OS. High speed USB 3.0 technology and superior low latency technology makes it easier for you to transmit live streaming to Twitch, Youtube, Facebook, Twitter, OBS, Potplayer and VLC.
- 【HDMI LOOP-OUT】Based on the high-speed USB 3.0 technology, it can capture one single channel HD HDMI video signal. There is no delay when you are playing game live.
- 【Support Mic-in for Commentary】Rybozen capture card has microphone input and you can use it to add external commentary when playing a game. Please note: it only accepts 3.5mm TRS standard microphone headset.
FAQ
Can html2canvas capture a modal that is off-screen?
It can capture content outside the visible portion when the element has measurable scroll dimensions and the virtual window is sized accordingly. A hidden element with no layout cannot be reconstructed reliably.
Why does toDataURL() fail after the capture succeeds?
The canvas is usually tainted by an image or background asset from another origin without the required CORS permission. Fix the asset response or route it through a permitted proxy before exporting.
Should I always set useCORS?
No. Set it when external images are expected and their servers send appropriate CORS headers. The option cannot grant permission that the image server did not provide.
Recommended Free Tools
How can I capture only part of a modal?
Wrap the desired region in its own element and pass that element to html2canvas, or temporarily hide excluded children with the ignore attribute or predicate.
Frequently Asked Questions
Can html2canvas capture a modal that is off-screen?
It can capture content outside the visible portion when the element has measurable scroll dimensions and the virtual window is sized accordingly. A hidden element with no layout cannot be reconstructed reliably.
Why does toDataURL() fail after the capture succeeds?
The canvas is usually tainted by an image or background asset from another origin without the required CORS permission. Fix the asset response or route it through a permitted proxy before exporting.
Should I always set useCORS?
No. Set it when external images are expected and their servers send appropriate CORS headers. The option cannot grant permission that the image server did not provide.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Scan for outdated or missing drivers - takes under a minute3Repair Windows errors before they cause bigger problemsHow can I capture only part of a modal?
Wrap the desired region in its own element and pass that element to html2canvas, or temporarily hide excluded children with the ignore attribute or predicate.
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.

