The usual fix is to render against the element’s full scroll dimensions instead of the visible viewport. Set both windowWidth and windowHeight to the target’s scrollWidth and scrollHeight. For a document, use the document’s full scroll dimensions. If the result is still blank or truncated, check canvas size limits, pixel-density scaling, cross-origin images, nested scrolling, fixed overlays, unsupported CSS and cross-origin iframes.
Use the element’s scroll dimensions
html2canvas creates a canvas by rendering a cloned version of the page. By default, its virtual rendering window follows the browser viewport. A tall element can therefore be painted only through the visible portion, even though the DOM contains more content.
const element = document.querySelector('#capture');
const canvas = await html2canvas(element, {
windowWidth: element.scrollWidth,
windowHeight: element.scrollHeight,
});
document.body.appendChild(canvas);
This is the pattern shown in the project’s FAQ for output that is empty or cut off halfway: enlarge the rendering window to match the content. Make sure the element is laid out at the size you intend to capture before reading its dimensions.
Capture a whole document
For a page rather than a component, measure the document or body instead of using window.innerWidth and window.innerHeight. Different layouts report scrolling on different roots, so select the largest relevant values.
#1 Best Overall
const root = document.documentElement;
const body = document.body;
const width = Math.max(root.scrollWidth, body ? body.scrollWidth : 0);
const height = Math.max(root.scrollHeight, body ? body.scrollHeight : 0);
const canvas = await html2canvas(root, {
windowWidth: width,
windowHeight: height,
});
If a page uses a wrapper with its own scrollbar, capture that wrapper and use its scrollWidth and scrollHeight; the document dimensions may not include content inside the nested scroller.
A diagnostic capture that handles common layout problems
The following function makes the crop explicit, caps scale at two device pixels per CSS pixel, enables CORS checks for images, and removes nodes marked for exclusion in the cloned document.
async function captureWholeElement(element) {
const width = element.scrollWidth;
const height = element.scrollHeight;
return html2canvas(element, {
windowWidth: width,
windowHeight: height,
width,
height,
scale: Math.min(window.devicePixelRatio || 1, 2),
useCORS: true,
onclone: (clonedDocument) => {
clonedDocument
.querySelectorAll('[data-html2canvas-ignore]')
.forEach((node) => node.remove());
},
});
}
const canvas = await captureWholeElement(
document.querySelector('#capture')
);
useCORS: true is useful only when the image host sends an appropriate Access-Control-Allow-Origin header. It cannot bypass the browser’s same-origin policy. The onclone callback changes only the cloned document used for rendering, not the live page.
Control the crop, scroll position and fixed elements
Set an explicit crop
The configuration supports x, y, width and height. Use them when you need a specific rectangle rather than the entire target.
const canvas = await html2canvas(element, {
x: 0,
y: 0,
width: element.scrollWidth,
height: element.scrollHeight,
windowWidth: element.scrollWidth,
windowHeight: element.scrollHeight,
});
Keep the crop and rendering window conceptually separate: the window determines what the renderer can see, while the crop determines what is written to the output.
Handle scrolled containers
For a nested scrolling element, temporarily expand it or set its scroll position before capture. scrollX and scrollY control the scroll position used for rendering. A scrollbar that remains in the clone can hide content at the edge.
const scroller = document.querySelector('.scroll-panel');
const oldOverflow = scroller.style.overflow;
const oldHeight = scroller.style.height;
scroller.style.overflow = 'visible';
scroller.style.height = `${scroller.scrollHeight}px`;
try {
const canvas = await html2canvas(scroller, {
windowWidth: scroller.scrollWidth,
windowHeight: scroller.scrollHeight,
scrollX: 0,
scrollY: 0,
});
document.body.appendChild(canvas);
} finally {
scroller.style.overflow = oldOverflow;
scroller.style.height = oldHeight;
}
Remove sticky headers, menus and overlays
Sticky or fixed nodes can repeat over every part of a tall capture or cover the bottom edge. Mark disposable controls with data-html2canvas-ignore:
<button data-html2canvas-ignore>Open menu</button>
The attribute is honored by html2canvas. You can also remove or restyle those nodes in onclone, which avoids changing the user-visible page.
Free tools Windows power users keep installed
One-click scans. No signup required.
Canvas limits: why a blank or partial image can be silent
The html2canvas FAQ warns that “The canvas may hit browser size limits.” Browsers can fail silently when one canvas dimension or the total pixel area is too large. The FAQ’s rough current guidance is about 32,767 pixels per dimension for Chrome/Chromium, Firefox and desktop Safari, with lower limits on iOS Safari; these are approximate implementation limits, not a universal specification.
Rank #3
Scale multiplies the pixel dimensions
scale defaults to window.devicePixelRatio. A 12,000-pixel CSS height at a device-pixel ratio of three becomes roughly 36,000 output pixels and may exceed a browser limit. Lower the scale deliberately:
const canvas = await html2canvas(element, {
windowWidth: element.scrollWidth,
windowHeight: element.scrollHeight,
scale: 1,
});
The trade-off is resolution: lower scale produces fewer output pixels and can make text less sharp. A cap such as Math.min(devicePixelRatio, 2) is a practical compromise for long pages.
Split and stitch very large captures
If the content remains too tall, capture several vertical sections and combine them with a second canvas or an image-processing step. Use explicit y and height values for each section, keeping each canvas below the browser’s dimension and area limits. For server-side generation, the html2canvas FAQ points to browser automation workflows such as Puppeteer or Playwright, which can take screenshots without relying on one enormous in-page canvas.
Missing images and cross-origin content
Images without CORS permission
With the default allowTaint: false, html2canvas checks images that could taint the canvas and may skip them. useCORS: true succeeds only if the image server returns a suitable Access-Control-Allow-Origin response header. Configure the asset host or route images through a same-origin proxy you control.
Rank #4
Do not treat allowTaint: true as a general fix: a tainted canvas cannot be safely exported with methods such as toDataURL or toBlob.
Cross-origin iframes
html2canvas cannot render a cross-origin iframe because browser security prevents access to that frame’s contentDocument. You need cooperation from the embedded application, a same-origin deployment, an exported representation, or a browser automation approach that captures the rendered page externally.
CSS and DOM limitations
html2canvas is not a screenshot of the browser’s compositor. It reconstructs the image from the DOM and styles, and its documentation notes that every CSS property must be manually implemented, so it will never have full CSS support. A complete canvas can therefore differ from what the browser displays.
Windows 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 reinstallOutdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware match- Check unsupported or partially supported effects when a section is present but visually wrong.
- Wait until fonts, images and asynchronous data have loaded before calling html2canvas.
- Disable animations and transitions in the clone if elements move during rendering.
- Verify that content is not hidden by
overflow: hidden, clipping, transforms or collapsed accordions.
A reliable capture checklist
- Select the actual element that owns the content, including any nested scrolling panel.
- Read
scrollWidthandscrollHeightafter layout, fonts and images have settled. - Pass those values as
windowWidthandwindowHeight; add explicitwidthandheightwhen you need a fixed crop. - Set
scrollXandscrollYdeliberately for scrolled or fixed-position layouts. - Hide overlays and controls with
data-html2canvas-ignoreor anonclonecallback. - Use
useCORSonly when the asset server permits it; otherwise use a same-origin proxy. - Cap
scaleand check the resulting pixel dimensions before attempting a very tall capture. - Split the job or move to Puppeteer/Playwright when browser canvas limits remain the blocker.
Common symptoms and fixes
| Symptom | Likely cause | Action |
|---|---|---|
| Only the visible viewport appears | Rendering window equals viewport | Use the target’s scrollWidth and scrollHeight for windowWidth/windowHeight. |
| Bottom half is blank | Canvas dimension or total area limit | Lower scale, split the capture, or use browser automation. |
| Images are missing | Cross-origin response lacks CORS headers | Configure Access-Control-Allow-Origin, use useCORS, or proxy the images. |
| Header repeats or covers content | Fixed/sticky positioning | Hide it in the clone, adjust scroll values, or capture an expanded layout. |
| Embedded app is absent | Cross-origin iframe security | Make it same-origin, obtain an export, or capture externally. |
| Layout looks different despite full height | Unsupported CSS or timing | Wait for resources, disable motion, and simplify unsupported styles. |
Or skip the browser setup
ScreenshotNeo provides a website screenshot API and MCP server when you need a rendered page rather than a DOM canvas. One GET request 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 the capture; each step can be disabled. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and response headers identify the page verdict and billing result.
Use the API documentation at https://screenshotneo.com/docs/ for the full option set, including full-page lazy-image loading, CSS-selector element capture, device presets, retina scale, PDF controls, custom CSS and JavaScript, clicks, waits, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, TTL caching, signed links, asynchronous webhooks, bulk capture and usage reporting. Its MCP server exposes take_screenshot, get_page_info and capture_pdf to Claude, Cursor and other MCP clients.
Best Value
- Used Book in Good Condition
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 shots per month with no card. Paid plans start at $5 for 3,000 shots; every feature is on every plan. Create a free ScreenshotNeo account to try it.
When to choose html2canvas versus an external screenshot
Use html2canvas when the capture must run in the current browser, you need direct access to the DOM, or you can control the assets and CSS. Choose Puppeteer or Playwright for server-side browser rendering, very tall pages that exceed canvas limits, or workflows requiring browser-level behavior. Choose an external API when you want a simple HTTP call, PDF output, retries and operational handling without maintaining browser infrastructure.
Frequently Asked Questions
Does html2canvas capture content below an element with a scrollbar automatically?
Not reliably. Capture the scrolling element itself, use its scroll dimensions, and temporarily expand or otherwise neutralize the inner scrollbar when necessary.
Will increasing width and height fix a cross-origin iframe?
No. Dimensions affect the rendering window, but browser security still prevents html2canvas from reading a cross-origin iframe’s document.
What should I check first when the canvas is completely blank?
Check the target dimensions, then reduce scale and test a smaller region. A browser canvas limit can fail silently; also verify that the element is visible and that required resources have loaded.
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.
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 problems




