Recommended Free Tools
html2canvas throws IndexSizeError when a zero or otherwise invalid width or height reaches the Canvas 2D drawImage() call. The usual causes are a hidden or collapsed capture target, a component captured before layout, an empty child canvas, or an image whose intrinsic dimensions are still zero. Verify dimensions immediately before capture, wait for layout and assets, make capture-only changes in onclone, and instrument resource failures. The workflow below fixes the error without changing the live page.
What the error means
IndexSizeError is the browser’s Canvas 2D argument-validation error. In html2canvas, the renderer eventually calls drawImage() with dimensions calculated from your DOM and its images or canvases. A width or height of zero (or another invalid numeric value) can make that call fail. The same symptom is often reported as “Failed to execute drawImage on CanvasRenderingContext2D” or “image argument is a canvas element with a width or height of 0.”
html2canvas may allocate an intermediate canvas with at least one pixel, but that does not guarantee that the later draw operation receives positive requested dimensions. Therefore, changing only the output canvas size does not repair the underlying invalid element or asset.
1. Check the capture target before calling html2canvas
Start by proving that the node exists, is attached, and has a positive rendered and scroll size. Run this immediately before the capture, not during an earlier mount phase.
#1 Best Overall
- CRISP CLARITY: This 23.8″ Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
- INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
- THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors
- WORK SEAMLESSLY: This sleek monitor is virtually bezel-free on three sides, so the screen looks even bigger for the viewer. This minimalistic design also allows for seamless multi-monitor setups that enhance your workflow and boost productivity
- A BETTER READING EXPERIENCE: For busy office workers, EasyRead mode provides a more paper-like experience for when viewing lengthy documents
const node = document.querySelector('#capture');
if (!node) throw new Error('capture target missing');
const rect = node.getBoundingClientRect();
console.table({
rectWidth: rect.width,
rectHeight: rect.height,
scrollWidth: node.scrollWidth,
scrollHeight: node.scrollHeight,
display: getComputedStyle(node).display,
visibility: getComputedStyle(node).visibility
});
if (rect.width <= 0 || rect.height <= 0) {
throw new Error(`capture target has invalid size: ${rect.width}x${rect.height}`);
}
A positive scrollWidth alone is not sufficient: an element can contain content while its rendered rectangle is zero because it or an ancestor is display:none, collapsed, detached, or otherwise not laid out.
Common dimension failures
- Hidden ancestor: a modal, tab, accordion panel, or route is still
display:none. - Not mounted or measured: a framework component has rendered its shell but has not completed its size calculation.
- Collapsed layout: flex/grid constraints, zero-height parents, or an off-screen technique that also removes layout.
- Empty child canvas: a chart or drawing surface was created with
width="0"orheight="0". - Unready media: an image, SVG, background, or nested canvas has no intrinsic dimensions at capture time.
2. Make hidden content renderable
Do not capture an element while it or a required ancestor is display:none. Render it visibly, place it off-screen while preserving layout, or alter only the cloned document used by html2canvas.
For a normal page, a capture-only class can preserve dimensions without showing the content to users:
.capture-staging {
position: absolute !important;
left: -100000px !important;
top: 0 !important;
display: block !important;
visibility: visible !important;
}
Apply the class after the component has mounted and remove it after capture. Avoid display:none, content-visibility:hidden, or a detached document for the target. If a parent controls visibility, fix the parent or use onclone so the live interface is untouched.
Free tools Windows power users keep installed
One-click scans. No signup required.
Rank #2
- CRISP CLARITY: This 22 inch class (21.5″ viewable) Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
- 100HZ FAST REFRESH RATE: 100Hz brings your favorite movies and video games to life. Stream, binge, and play effortlessly
- SMOOTH ACTION WITH ADAPTIVE-SYNC: Adaptive-Sync technology ensures fluid action sequences and rapid response time. Every frame will be rendered smoothly with crystal clarity and without stutter
- INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
- THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors
3. Wait for layout, fonts, and images
Capture only after the browser has performed layout and the component has finished measuring itself. In a client-rendered application, that may mean waiting for the next animation frame after state changes. Wait for fonts as well, because a late font swap can change widths and heights.
await document.fonts?.ready;
await new Promise(requestAnimationFrame);
await new Promise(requestAnimationFrame);
For images inside the target, resolve both already-complete images and images that are still loading. Treat an error as a completed wait so one broken URL does not leave your promise pending forever.
const images = [...node.querySelectorAll('img')];
await Promise.all(images.map(img => {
if (img.complete) return Promise.resolve();
return new Promise(resolve => {
img.addEventListener('load', resolve, { once: true });
img.addEventListener('error', resolve, { once: true });
});
}));
await Promise.all(images.map(img =>
typeof img.decode === 'function' ? img.decode().catch(() => {}) : Promise.resolve()
));
Inspect every descendant canvas too:
for (const canvas of node.querySelectorAll('canvas')) {
if (canvas.width <= 0 || canvas.height <= 0) {
throw new Error(`invalid child canvas: ${canvas.width}x${canvas.height}`);
}
}
4. Use onclone for safe capture-only fixes
html2canvas’s documented onclone option receives the cloned document. It is the right place to reveal sections marked for capture, remove animations, and give empty placeholders safe dimensions without mutating the user’s live page.
const canvas = await html2canvas(node, {
onclone: clonedDoc => {
clonedDoc.querySelectorAll('[data-capture-hidden]').forEach(el => {
el.removeAttribute('hidden');
el.style.display = 'block';
el.style.visibility = 'visible';
});
clonedDoc.querySelectorAll('*').forEach(el => {
el.style.setProperty('transition', 'none', 'important');
el.style.setProperty('animation', 'none', 'important');
});
}
});
Only assign fallback dimensions when an empty placeholder is intentionally part of the design. Giving an accidentally broken chart a width does not recreate its data; fix the chart’s initialization first.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Fix the driver behind crashes, sound loss and screen glitches3Repair Windows errors before they cause bigger problemsRank #3
- Clear visuals. Fluid motion: A 144Hz refresh rate and 1ms MPRT deliver smooth, tear‑free motion across work, gaming, and streaming for clearer, more fluid viewing.
- Eye comfort: TÜV Rheinland 3‑star* certification reduces harmful blue light while preserving stunning color quality without compromise. *TÜV Rheinland 3-star eye comfort certification.
- Wide viewing angle: Get consistent views across a wide 178° /178° viewing angle.
- In-Plane Switching (IPS): See excellent color accuracy and consistency across wide viewing angles with In-plane Switching (IPS) technology.
- Ultra-thin bezels: Maximize your viewing experience with thin bezels.
5. Capture large or full-page content correctly
Blank or cut-off output can be a separate canvas-area problem. Set windowWidth and windowHeight to the target’s scroll dimensions when capturing a long element, and reduce scale if the resulting bitmap is too large.
const canvas = await html2canvas(node, {
windowWidth: Math.max(node.scrollWidth, 1),
windowHeight: Math.max(node.scrollHeight, 1),
scale: Math.min(window.devicePixelRatio || 1, 2),
backgroundColor: '#ffffff'
});
If the page remains too large, capture smaller sections and stitch them, crop to the required region, or use a lower scale. Browser limits vary; Safari has stricter area behavior in the documented issue discussion, so test large captures in every browser you support. The often-repeated Safari area number of 5,242,880 pixels is user-reported in that discussion, not a universal browser specification.
6. Distinguish CORS failures from dimension failures
Remote images introduce a different class of problem. useCORS:true works only when the image server supplies an appropriate Access-Control-Allow-Origin response. Otherwise, use a same-origin proxy or change the asset delivery configuration.
const canvas = await html2canvas(node, {
useCORS: true,
allowTaint: false
});
CORS errors typically taint the canvas or cause images to be skipped. They do not normally explain a zero-size drawImage() argument. Fix dimensions first, then investigate cross-origin headers if images are missing or the browser reports a security exception.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Rank #4
- CURVED FOR ENHANCED ENGAGEMENT: An immersive viewing experience with a curved monitor that wraps more closely around your field of vision; It creates a wider view, enhancing depth perception and minimizing peripheral distraction
- SMOOTH PERFORMANCE FOR SEAMLESS CONTENT: Stay in the action when playing games, watching videos, or working on creative projects; The 100Hz refresh rate reduces lag and motion blur so you don't miss a thing in fast-paced moments¹
- MORE GAMING POWER: Gain the edge with optimizable game settings; Color and image contrast can be adjusted to see scenes more vividly and spot enemies hiding in the dark; Game Mode adjusts any game to fill the screen so you can view every detail²
- KEEP IT EASY ON THE EYES: Care for your eyes and stay comfortable, even during long sessions; Advanced eye comfort technology certified by TÜV reduces eye strain by minimizing blue light and reducing irritating screen flicker²
- INCREASED VERSATILITY: Connect to more; Plug devices straight into your monitor for increased flexibility, making your computing environment even more convenient
7. Instrument the failing resource
Use the documented onError callback and the browser stack to identify whether the invalid dimensions came from an image, child canvas, background, SVG, or iframe.
const canvas = await html2canvas(node, {
onError: error => {
console.error('html2canvas resource failed', error);
}
});
When the stack points into an image or canvas draw, temporarily remove half of the target’s children, capture again, and narrow the failing subtree. Log each candidate’s naturalWidth/naturalHeight for images and width/height for canvases. This binary-search approach is faster than changing random html2canvas options.
A defensive end-to-end example
async function captureElement(selector) {
const node = document.querySelector(selector);
if (!node) throw new Error('capture target missing');
const rect = node.getBoundingClientRect();
if (rect.width <= 0 || rect.height <= 0) {
throw new Error(`capture target has invalid size: ${rect.width}x${rect.height}`);
}
await document.fonts?.ready;
await Promise.all([...node.querySelectorAll('img')].map(img => {
if (img.complete) return Promise.resolve();
return new Promise(resolve => {
img.addEventListener('load', resolve, { once: true });
img.addEventListener('error', resolve, { once: true });
});
}));
for (const child of node.querySelectorAll('canvas')) {
if (child.width <= 0 || child.height <= 0) {
throw new Error(`invalid child canvas: ${child.width}x${child.height}`);
}
}
return html2canvas(node, {
windowWidth: Math.max(node.scrollWidth, 1),
windowHeight: Math.max(node.scrollHeight, 1),
scale: Math.min(window.devicePixelRatio || 1, 2),
useCORS: true,
onclone: clonedDoc => {
clonedDoc.querySelectorAll('[data-capture-hidden]').forEach(el => {
el.removeAttribute('hidden');
el.style.display = 'block';
});
},
onError: error => console.error('html2canvas resource failed', error)
});
}
Troubleshooting by symptom
| Symptom | Likely cause | Fix |
|---|---|---|
IndexSizeError immediately |
Target or child canvas has a zero dimension | Log rectangles and canvas sizes; render hidden ancestors and initialize canvases before capture. |
| Fails only on a tab or modal | Panel is display:none until opened |
Capture while open, stage it off-screen, or reveal it in onclone. |
| Fails intermittently | Race with layout, fonts, or image decoding | Wait for mount, two animation frames, document.fonts.ready, and image completion. |
| Images missing, security exception | Cross-origin response lacks CORS headers | Enable server CORS or proxy images through your origin; keep useCORS:true. |
| Blank or cut-off long image | Canvas area or viewport dimensions are too large | Match window dimensions, lower scale, crop, or tile; test Safari separately. |
| Only one widget breaks the capture | Invalid SVG, iframe, background, image, or nested canvas | Use onError, inspect the stack, and isolate descendants until the resource is found. |
When to use a different capture method
html2canvas reconstructs a page from the DOM and CSS, so it can diverge from browser pixels and cannot freely read cross-origin content. Compare approaches on DOM fidelity, browser-native fidelity, cross-origin asset support, maximum capture area, whether the code runs in an ordinary page or an extension, and maintenance cost. The html2canvas FAQ notes that major browsers expose native screenshot APIs in extension APIs that are more reliable and do not have canvas size limits. Those APIs require an extension context; they are not a drop-in replacement for a script running on an ordinary website.
Or skip the browser setup
For server-side screenshots, ScreenshotNeo accepts one request and returns PNG, JPEG, WebP, or PDF. It accepts cookie and consent banners like a visitor, then removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and whether it was billed. An MCP server provides take_screenshot, get_page_info, and capture_pdf tools to Claude, Cursor, and other MCP clients.
Read the parameter reference in the ScreenshotNeo documentation. The same endpoint supports full-page lazy-image loading, CSS-selector element capture, dark mode, device presets or custom viewports, retina scale, PDF paper and page options, custom CSS and JavaScript, clicks, selector or network-idle 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.
Best Value
- 【INTEGRATED SPEAKERS】Whether you're at work or in the midst of an intense gaming session, our built-in speakers provide rich and seamless audio, all while keeping your desk clutter-free.
- 【EASY ON THE EYES】 Protect your eyes and enhance your comfort with Blue-Light Shift technology. This feature reduces harmful blue light emissions from your screen, helping to alleviate eye strain during long hours of use and promoting healthier viewing habits.
- 【WIDEN YOUR PERSPECTIVE】Our sleek minimal bezel design ensures undivided attention. The nearly bezel-free display seamlessly connects in a dual monitor arrangement, delivering an unobstructed view that lets you focus on more at once, completely distraction-free.
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}`);
The Free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 screenshots; yearly billing provides two months free. Sign up for the free plan to capture without managing browser layout, CORS, or canvas limits.
FAQ
Does setting scale: 1 fix IndexSizeError?
It can reduce oversized-canvas failures, but it does not make a hidden target, empty canvas, or zero-dimension image valid. Check dimensions first.
Can I capture an iframe with html2canvas?
Only same-origin iframe content can be inspected as ordinary DOM. Cross-origin frames remain isolated by the browser’s security model.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Should I catch the exception and retry?
A retry without changing layout or asset state usually repeats the same invalid draw. Retry only after the failing dimension or readiness condition has been corrected.
Frequently Asked Questions
Does setting scale: 1 fix IndexSizeError?
It can reduce oversized-canvas failures, but it does not make a hidden target, empty canvas, or zero-dimension image valid. Check dimensions first.
Can I capture an iframe with html2canvas?
Only same-origin iframe content can be inspected as ordinary DOM. Cross-origin frames remain isolated by the browser’s security model.
Should I catch the exception and retry?
A retry without changing layout or asset state usually repeats the same invalid draw. Retry only after the failing dimension or readiness condition has been corrected.
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.




