October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsWindows FixRecommendedWindows errors stealing your time? Find the fix fastScan stability, cleanup and performance issues.Fix NowOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
html2canvas

Why html2canvas Takes So Long to Capture Screenshots (and How to Find the Bottleneck)

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

html2canvas is often slow because it does not save the pixels your browser has already painted. It walks the target DOM, reads styles and other page state, loads resources, and builds a new canvas representation. On a large or CSS-heavy page, cloning and style inspection can take longer than the final drawing. The practical fix is to measure each phase on the affected browser and page, then reduce the work your capture actually needs.

What html2canvas is really doing

The official documentation describes html2canvas as a DOM-based renderer: “The script traverses through the DOM of the page it is loaded on.” It then reads properties and constructs a representation in a canvas. In its own words, it “does not actually take a screenshot of the page, but builds a representation of it based on the properties it reads from the DOM.”

That distinction explains why a visually simple page can still take a long time. A native browser screenshot can copy a composited surface. html2canvas must inspect descendants, computed styles, fonts, images, backgrounds, pseudo-elements and layout-related values, then emulate supported CSS in JavaScript. The FAQ notes that every CSS property must be implemented manually, so it will never have complete CSS support: html2canvas FAQ.

Why large pages amplify the cost

  • More DOM nodes mean more cloning and parsing work.
  • Deeply nested or component-generated markup increases traversal overhead.
  • Computed styles, including CSS custom properties, may be expensive to copy.
  • Images, fonts and other resources can delay the resource phase.
  • A high device-pixel-ratio creates a larger canvas and more pixels to render.

These costs are page- and browser-dependent. A reported Firefox/JupyterLab issue found 500–600 ms in Chrome versus 6–7 seconds in Firefox for one toolbar capture using html2canvas 1.4.1 on Windows 10; the reporter associated the slowdown with computed-style copying and custom properties. A separate report described about 30 seconds in Safari 16.5.2 versus about 3 seconds in Firefox and Chrome while cloning roughly 3,000 nodes on macOS 13.4.1. Neither report is a general benchmark or a promise about current browsers.

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.

Measure the slow phase before changing code

Start with the exact production page, target element, browser, operating system, html2canvas version and scale setting. Use a non-minified build while investigating and enable the library’s logging option. The documented configuration is at html2canvas configuration options.

const target = document.querySelector('#invoice');

const canvas = await html2canvas(target, {
  logging: true,
  // Set this explicitly while comparing runs:
  scale: 1
});
document.body.appendChild(canvas);

In versions that expose phase messages, note the elapsed time for cloning, node parsing, image or resource loading and rendering. Repeat several times after a cold load and a warm load. Record whether the target is a small component, a full page or a long scrolling region. This separates a DOM/style bottleneck from slow network resources or the canvas draw itself.

A useful diagnostic matrix

Observed slow phase Most likely area to test First experiment
Clone or computed-style copying DOM size, custom properties, browser-specific style work Capture a smaller subtree; exclude descendants; test property filtering
Node parsing Deep or node-heavy markup Remove nonessential regions and compare node counts
Images or resources Network, fonts, cross-origin policy Check requests, wait for assets, then test CORS or a proxy
Rendering Canvas dimensions and pixel count Use an explicit lower scale and a smaller capture area

Reduce the amount of page html2canvas must process

Capture the smallest useful subtree

Pass the component that must be shared or saved, not document.body, when a card, chart or panel is sufficient.

const chart = document.querySelector('.sales-chart');
const canvas = await html2canvas(chart, { logging: true });

This reduces traversal, style inspection and output pixels at the same time. It also avoids unrelated advertisements, navigation, chat controls and hidden application containers.

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

Exclude descendants with ignoreElements or a data attribute

The configuration supports both a predicate and the data-html2canvas-ignore attribute.

const canvas = await html2canvas(document.querySelector('#report'), {
  ignoreElements: element => element.matches('.live-clock, .chat-launcher')
});
<aside data-html2canvas-ignore>Toolbar not included in the image</aside>

Exclude only content that is genuinely unnecessary. Removing a node that affects layout can change the captured composition.

Test cullOffscreen for long viewport captures

cullOffscreen can avoid work for content outside the viewport. It is intended for viewport-sized captures of long pages and is conservative; it is not a universal solution for full-page output. Compare the result visually because offscreen content that contributes to layout or effects may still matter.

Choose scale intentionally

The documented default is window.devicePixelRatio. On a Retina or other high-density display, that can create a much larger bitmap than expected. Test an explicit value:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
const canvas = await html2canvas(target, {
  scale: 1,       // compare with 0.75 or 2 for your quality needs
  logging: true
});

A lower scale usually reduces pixel work and memory, but the sources do not establish a fixed speedup. Check text sharpness, dimensions and downstream file size before adopting it.

When CSS custom properties or a browser are the culprit

If logs show that cloning or computed-style copying dominates, inspect the styles used by the captured subtree. Frameworks can generate many custom properties, and browser implementations may handle computed-style access differently. Treat this as a hypothesis, not a universal explanation: the Firefox report is one environment, and the Safari report is another.

The configuration API provides onCopyProperty, which lets you handle or skip selected properties while styles are cloned. The documentation gives filtering custom properties beginning with -- as an example:

const canvas = await html2canvas(target, {
  onCopyProperty: (property, value) => {
    if (property.startsWith('--')) {
      return; // skip only if these variables are irrelevant to the capture
    }
    return value;
  },
  logging: true
});

Do not remove variables that control colors, spacing, dimensions or typography in the target. Compare the image and layout with and without the callback, and keep the change only when the omitted properties are not needed.

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

Resource loading and cross-origin images are separate problems

An image that is slow to download can make capture appear slow, while an image that violates canvas origin rules can be missing or taint the canvas. Investigate these after timing the resource phase rather than treating them as DOM performance.

  • Wait until critical images and fonts have loaded before invoking html2canvas.
  • Use useCORS only when the remote server sends suitable CORS headers.
  • If you control neither origin nor headers, evaluate the FAQ’s proxy approach: html2canvas FAQ.
  • Check browser network errors and the console for blocked resources.
await document.fonts.ready;
await Promise.all([...document.images].map(img =>
  img.complete ? Promise.resolve() : new Promise(resolve => {
    img.addEventListener('load', resolve, { once: true });
    img.addEventListener('error', resolve, { once: true });
  })
));

const canvas = await html2canvas(target, {
  useCORS: true,
  logging: true
});

Do not confuse slowness with canvas limits or bad output

Canvas dimension and memory limits can produce blank or clipped output; they do not necessarily mean html2canvas is still working. Very tall full-page captures can exceed a browser’s maximum canvas size. Try a smaller element, a lower scale or tiled captures. Cross-origin images can also produce an unusable canvas even when the render itself completed. Diagnose those failures independently from timing.

A repeatable troubleshooting workflow

  1. Reproduce with the version your project actually ships, recording browser, OS, target selector and scale.
  2. Enable logging and identify whether cloning, parsing, resources or rendering dominates.
  3. Capture a smaller subtree and compare the elapsed time and visual result.
  4. Exclude nonessential descendants with ignoreElements or data-html2canvas-ignore.
  5. For viewport captures of long pages, test cullOffscreen.
  6. Test explicit scales such as 1 and your current device-pixel ratio; verify quality.
  7. If style cloning is slow, inspect custom properties and cautiously test onCopyProperty.
  8. If resources are slow or absent, inspect network timing, CORS headers and proxy options.
  9. Repeat on every supported browser with the real production page. Do not turn isolated issue timings into guarantees.

When html2canvas is the wrong capture method

html2canvas fits client-side rendering of a selected DOM element when its supported CSS and performance meet your needs. A browser extension capturing the visible tab can use the browser’s native extension screenshot APIs. For server-side generation, the FAQ points to Puppeteer and Playwright, which drive a real browser headlessly. Compare capture scope, CSS fidelity, security boundaries, deployment environment and measured performance on your workload; no source establishes one universally fastest option.

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

Or skip the browser setup

If you need a reliable website image rather than an in-page DOM reconstruction, ScreenshotNeo provides a website screenshot API and MCP server. It accepts consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups and chat widgets before capture. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and response headers identify the page verdict and billing status.

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

One GET request is enough:

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

See the complete parameter reference and options in the ScreenshotNeo documentation. It supports full-page lazy-image loading, CSS-selector element capture, dark mode, device presets and custom viewports, retina scale, PDF output, custom CSS and JavaScript, clicks, waits, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, TTL caching, signed image links, asynchronous webhooks, bulk capture of up to 100 URLs per call, usage data and an OpenAPI specification. An MCP server provides take_screenshot, get_page_info and capture_pdf 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; every feature is available on every plan, and annual billing provides two months free. Create a free ScreenshotNeo account to try it without a card.

What the timing reports actually show

A 2017 issue reported 8 seconds for 883 nodes and 66 seconds for 2,660 nodes in html2canvas 0.5 beta4. That is historical context, not an estimate for modern versions: issue 1250. The newer Firefox/JupyterLab and Safari reports likewise describe particular pages and systems, not representative cross-browser benchmarks: issue 3191 and issue 3108.

Frequently Asked Questions

Does reducing DOM nodes always make html2canvas faster?

No. It often reduces traversal and style work, but resource loading, browser behavior and canvas pixel count can dominate. Measure the phases on your page.

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

Can I fix every slowdown by setting scale to 1?

No. Scale changes output pixel work and memory. It will not fix slow cloning, blocked images or unsupported CSS, and the quality trade-off must be checked.

Why is the screenshot blank even though capture completed?

Canvas size limits, memory pressure or cross-origin resources can cause blank output. Treat those as output and origin problems, separate from phase timing.

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
PC Slower Than It Used to Be?Free scan - under a minute
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.