Hardware FixRecommendedDevice not working? Your driver may be the problemCheck updates for common hardware issues.Fix DriversOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsPC HealthRecommendedCrashes, freezes, slowdowns? Check your PC nowSpot repairable issues before they interrupt work.Check PC×
Skip to content
CORS

How to Capture a Modal With html2canvas (and Save It as a PNG)

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

Capture the modal after it is visible, not the whole page: select its root element, call html2canvas(modal), then export the returned canvas with toBlob() or toDataURL(). The browser library reconstructs the selected DOM and CSS; it does not make a native browser screenshot. That distinction explains most differences in fonts, filters, cross-origin images, fixed positioning and very tall dialogs.

What html2canvas actually captures

html2canvas walks the selected element, reads its computed styles and paints a representation into a canvas in the browser. It can capture a modal or any other DOM subtree without navigating away or asking the user for a system screenshot. Because it reconstructs the page, browser security rules and CSS support still apply: an image from another origin needs permission, and a CSS effect that the library does not implement may look different from the live dialog.

Install the package from npm:

npm install @html2canvas/html2canvas

In a browser module, import it and capture the dialog only after it is open, laid out and finished animating.

Basic modal-to-PNG implementation

This example assumes the dialog has id="my-modal". It keeps the background transparent, requests a high-density canvas, permits CORS-enabled images, and sizes the virtual window from the modal’s scroll dimensions.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import html2canvas from '@html2canvas/html2canvas';

async function saveModal() {
  const modal = document.querySelector('#my-modal');
  if (!modal) 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('#save-modal')?.addEventListener('click', saveModal);

toBlob() is a good default for downloads and file uploads because it avoids building a large base64 string. If you need an inline image or a data URL, use canvas.toDataURL('image/png') instead:

const dataUrl = canvas.toDataURL('image/png');
document.querySelector('#preview').src = dataUrl;

Capture at the right moment

  1. Open the modal. Do not capture a hidden element with display:none; it has no usable layout for the cloned render.
  2. Wait for layout. If an opening animation changes size or position, wait for its final frame. A practical browser-side wait is await new Promise(requestAnimationFrame), repeated if your framework needs more than one frame.
  3. Wait for assets. Ensure images have loaded and any asynchronous text or data has been inserted before calling html2canvas.
  4. Select the root. Use an id, a class, or a framework ref pointing at the dialog container, rather than document.body.
  5. Export the result. Check that the callback receives a Blob before creating the object URL, then release that URL after starting the download.

A framework ref is equivalent to document.querySelector; the important detail is that the ref resolves to the visible modal root at capture time.

Preventing cropped fixed or scrollable dialogs

Modal backdrops are commonly fixed to the viewport while the dialog itself is centered, constrained by max-height, or internally scrollable. html2canvas renders a cloned document, so the viewport used for that clone matters. Set windowWidth and windowHeight to the dimensions needed by the modal’s content when the output is clipped. For a tall dialog, use its scrollWidth and scrollHeight as in the example.

const rect = modal.getBoundingClientRect();
const canvas = await html2canvas(modal, {
  scrollX: window.scrollX,
  scrollY: window.scrollY,
  windowWidth: Math.max(modal.scrollWidth, Math.ceil(rect.width)),
  windowHeight: Math.max(modal.scrollHeight, Math.ceil(rect.height)),
  scale: Math.min(window.devicePixelRatio, 2)
});

Use the actual scroll offsets when the fixed element’s appearance depends on the page position. If the dialog intentionally shows only a scrollable viewport, capture that viewport element and its visible dimensions; if you want all content, capture the content container and size the virtual window for its full scroll dimensions.

Free tools Windows power users keep installed

One-click scans. No signup required.

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

Do not assume that increasing dimensions indefinitely solves clipping. Browser canvas width and height limits vary by browser and device. A canvas that is too large can be blank or partial without throwing an obvious exception. Reduce scale, capture a smaller region, or split an exceptionally tall modal into several images.

Images, CORS and tainted canvases

Same-origin images normally work. An image hosted on another origin must be served with an appropriate Access-Control-Allow-Origin response header. Setting useCORS:true tells html2canvas to request CORS-enabled images; it cannot grant permission that the image server did not send.

  • Preferred: host the image on the same origin as the page.
  • Also valid: configure the image host to allow your page’s origin, then keep useCORS:true.
  • When you control neither host: route the asset through a server-side CORS proxy for external images, or replace it with a same-origin copy.

If an external image is fetched without the required permission, the canvas may become tainted. Reading it with toBlob() or toDataURL() can then fail for security reasons. This is a browser boundary, not a setting html2canvas can bypass. Check image response headers in the browser’s network panel and make sure the URL is the one actually used by the modal, including responsive-image sources.

Sharper output without exhausting memory

The scale option controls the canvas pixel density. window.devicePixelRatio generally produces a crisp result on a Retina or other high-density display, while scale:1 uses CSS-pixel dimensions. Higher values increase memory and processing cost quadratically: doubling both width and height requires roughly four times as many pixels.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
const dpr = window.devicePixelRatio || 1;
const scale = Math.min(dpr, 2); // a practical ceiling for large dialogs
const canvas = await html2canvas(modal, { scale });

Choose the smallest scale that meets the required print or UI quality. For a large report modal, a capped scale is safer than blindly using a very high device-pixel ratio.

Hide controls and transient UI

Close buttons, copy controls, loading spinners and hover-only overlays often do not belong in the exported image. Add data-html2canvas-ignore to an element that should be omitted:

<button type="button" data-html2canvas-ignore>Close</button>
<button type="button" data-html2canvas-ignore>Copy</button>

You can also omit elements programmatically with the configuration’s ignore predicate:

const canvas = await html2canvas(modal, {
  ignoreElements: (element) =>
    element.matches('.close-button, .temporary-overlay')
});

Keep the modal visible while capturing; ignoring an element is different from hiding the entire dialog.

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

Common failures and precise fixes

Blank or partially rendered canvas

  • Inspect canvas.width and canvas.height. Zero or unexpectedly huge values indicate a layout or canvas-limit problem.
  • Lower scale, reduce the capture region, or split a very tall dialog.
  • Verify the modal was visible and had non-zero dimensions when the call began.

The modal is cropped

  • Use windowWidth: modal.scrollWidth and windowHeight: modal.scrollHeight for content that must fit.
  • Provide the relevant scrollX and scrollY when fixed positioning depends on page scroll.
  • Capture the correct inner element: a scroll viewport produces only its viewport, while its content element can include the full scroll height.

Images are missing or export throws a security error

  • Confirm the image is same-origin, or confirm its server sends Access-Control-Allow-Origin.
  • Keep useCORS:true only when the server is configured for CORS; otherwise use a proxy or same-origin asset.
  • Check every image, including CSS background images, because one disallowed resource can affect export.

CSS does not match the live modal

html2canvas supports many common CSS properties but is not a native browser compositor. Complex filters, transforms, unusual layout properties and other partially supported effects can differ. Simplify those effects for the capture variant, test the browsers you support, or use a native browser screenshot when pixel-identical rendering is required.

Unwanted buttons or overlays appear

Add data-html2canvas-ignore or an ignoreElements predicate to remove transient controls from the cloned render.

The capture races an animation or image load

Move the capture after the final animation frame and after the required image/data promises resolve. A screenshot call that runs immediately after opening the dialog can legitimately capture its intermediate state.

When html2canvas is the wrong boundary

Use html2canvas when the modal is in your page, you can select its DOM, and a reconstructed canvas is acceptable. It is especially convenient for client-side previews and downloads. Choose a native browser screenshot service when you need the browser’s own compositing, content outside your DOM, or server-side automation without exposing a capture button to visitors. The trade-off is straightforward: html2canvas is direct DOM integration; a browser screenshot is closer to what a user sees but requires browser automation or an API.

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

Or skip the browser setup

ScreenshotNeo captures a URL through a website screenshot API, so you do not have to install a browser library or manage canvas limits. It accepts the consent banner like a visitor and removes more than 60 known consent platforms, newsletter popups and chat widgets before capture; each cleanup step can be disabled. Only clean shots are billed: bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits cost nothing, and the response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP server provides take_screenshot, get_page_info and capture_pdf tools for Claude, Cursor and other MCP clients.

For a publicly reachable page containing the modal, one GET request returns an image. See the ScreenshotNeo documentation for all options.

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

Beyond a URL, ScreenshotNeo supports full-page captures with lazy images loaded, CSS-selector element capture, dark mode, 12 device presets plus custom viewports, Retina scale, PDF paper settings and page ranges, HTML/CSS-to-image, custom CSS and JavaScript, pre-capture clicks, hidden selectors, waits for selectors/delays/network idle, request and resource blocking, custom headers/cookies/user agents/Authorization, timezone and geolocation, transparent backgrounds, resizing, selectable-TTL caching, signed image links, asynchronous jobs with signed webhooks, bulk capture for up to 100 URLs per call, a usage API and an OpenAPI specification. Parameter names used by other screenshot APIs also work, which can simplify migration.

The Free plan includes 1,000 shots per month with no card. Paid plans start at $5 for 3,000 shots; every feature is included on every plan, and yearly billing provides two months free. Create a free ScreenshotNeo account to start.

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

Quick decision checklist

  • Need a client-side image of a DOM modal you control? Select the visible root and use html2canvas.
  • Seeing clipping? Match virtual window dimensions to the modal’s scroll dimensions and provide fixed-position scroll offsets.
  • Missing images? Fix same-origin/CORS delivery or use a proxy; useCORS alone is not permission.
  • Need crisp output? Increase scale carefully and watch canvas limits.
  • Need a server-side, native browser capture? Use a screenshot API such as ScreenshotNeo instead of reproducing browser setup in the page.

Frequently Asked Questions

Can html2canvas capture a modal that is inside an iframe?

Only when the iframe content is accessible under the browser’s same-origin rules and you can select its document. Cross-origin iframe content is blocked by browser security and cannot be read by html2canvas.

Should I use toBlob or toDataURL for a modal download?

Use toBlob for a file or upload workflow; it avoids constructing a large base64 string. Use toDataURL when another API specifically requires an inline data URL.

Why does the PNG have a transparent background?

The example sets backgroundColor to null, which preserves transparency. Set a CSS color such as ‘#fff’ in the html2canvas options when the exported image needs an opaque background.

Can I capture only one element inside the modal?

Yes. Pass that child element instead of the modal root, or use ScreenshotNeo’s selector-based element capture when the page is being rendered through its API.

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.

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.

Leave a Reply

Your email address will not be published. Required fields are marked *

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

Read next

Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
Outdated Drivers Are Slowing You DownFree scan - exact matches

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.