Insert the div, wait until the browser has painted it and its fonts and images are ready, then pass that element to html2canvas(). html2canvas reads the DOM state at capture time; it does not monitor future mutations. The dependable sequence is: update the DOM → wait for a repaint and required resources → call html2canvas(element) → export the canvas.
The reliable capture sequence
Keep a reference to the newly created node rather than querying an old selector before insertion. After appending it, wait for at least one requestAnimationFrame(). That gives style and layout a browser frame to settle. If text metrics depend on web fonts, await document.fonts.ready. For images inside the div, wait for loading and decoding before rendering.
- Create or update the element.
- Append it to a rendered part of the document.
- Await a repaint boundary.
- Await fonts when custom fonts affect wrapping or height.
- Await every image in the target subtree.
- Await another frame for late layout changes.
- Call
html2canvas(target)and export the returned canvas.
Complete browser example
Install the package with your package manager, then import it in an evergreen browser application:
import html2canvas from '@html2canvas/html2canvas';
const nextFrame = () => new Promise(requestAnimationFrame);
async function waitForImages(root) {
await Promise.all([...root.querySelectorAll('img')].map(async img => {
if (img.complete && img.naturalWidth > 0) {
if (img.decode) await img.decode().catch(() => {});
return;
}
await new Promise(resolve => {
img.addEventListener('load', resolve, { once: true });
img.addEventListener('error', resolve, { once: true });
});
if (img.decode) await img.decode().catch(() => {});
}));
}
export async function captureDynamicDiv() {
const card = document.createElement('div');
card.id = 'capture-card';
card.className = 'card';
card.innerHTML = `
<h2>New content</h2>
<img src="/images/chart.png" alt="Chart">
`;
document.querySelector('#app').append(card);
await nextFrame();
if (document.fonts?.ready) await document.fonts.ready;
await waitForImages(card);
await nextFrame();
const canvas = await html2canvas(card, {
backgroundColor: '#fff',
useCORS: true,
onclone: clonedDoc => {
clonedDoc.querySelectorAll('.capture-ignore').forEach(node => node.remove());
}
});
return canvas.toDataURL('image/png');
}
The function returns a data URL that can be assigned to an image, downloaded, or sent to your application. The Promise returned by html2canvas resolves after its DOM reconstruction finishes; it is not a browser-native pixel snapshot.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
#1 Best Overall
- PORTABLE SCANNER FOR USE ON-THE-GO — The fastest and lightest mobile single-sheet-fed compact document scanner in its class¹
- QUICK DOCUMENT SCANNING ― This Epson ultra-fast scanner scans a single page as quickly as 5.5 seconds²; Windows and Mac compatible
- VERSATILE PAPER HANDLING ― Portable scanner scans documents up to 8.5 x 72 in; Also easily digitizes receipts and ID cards to make accounting, bookkeeping, and organizing simpler
- INTUITIVE, HIGH-SPEED SOFTWARE — Epson ScanSmart Software³ is a smart tool allowing you to easily scan, review, and save; Stay organized easily with the help of this Epson scanner
- EASY SETUP — USB-powered connect to your computer for quick and simple scanning; No batteries or external power supply required to operate portable document scanner; Standard Connectivity: USB 2.0
Why a dynamically inserted div is missing
The capture ran before insertion committed
If you call html2canvas immediately after changing framework state or appending markup, layout may still reflect the previous DOM. Call the function from the framework’s post-render/update hook, or await a frame after direct insertion.
The node exists but has no rendered size
Check the exact reference and inspect getBoundingClientRect(). A removed node, a stale selector, display:none, or zero width and height leaves html2canvas with nothing measurable. Keep the element mounted and visible during capture.
Images or fonts changed the layout later
Unloaded fonts can change line breaks and element height. An undecoded image can occupy the wrong space or appear blank. Await document.fonts.ready, image load events, and HTMLImageElement.decode() where available, then take another frame.
Expecting automatic mutation tracking
html2canvas captures the element you give it at one point in time. It does not observe future mutations automatically. If another component controls insertion, a MutationObserver can start the same workflow, but debounce it so a burst of mutations produces one capture rather than many.
Rank #2
- FAST SPEEDS - Scans color and black and white documents a blazing speed up to 16ppm (1). Color scanning won’t slow you down as the color scan speed is the same as the black and white scan speed.
- ULTRA COMPACT – At less than 1 foot in length and only about 1. 5lbs in weight you can fit this device virtually anywhere (a bag, a purse, even a pocket).
- READY WHENEVER YOU ARE – The DS-640 mobile scanner is powered via an included micro USB 3. 0 cable allowing you to use it even where there is no outlet available. Plug it into you PC or laptop and you are ready to scan.
- WORKS YOUR WAY – Use the Brother free iPrint&Scan desktop app for scanning to multiple “Scan-to” destinations like PC, Network, cloud services, Email and OCR. (2) Supports Windows, Mac and Linux and TWAIN/WIA for PC/ICA for Mac/SANE drivers. (3)
- OPTIMIZE IMAGES AND TEXT – Automatic color detection/adjustment, image rotation (PC only), bleed through prevention/background removal, text enhancement, color drop to enhance scans. Software suite includes document management and OCR software. (4)
Capturing from frameworks
State updates are often asynchronous. In React, trigger capture from an effect that runs after the content-rendering state has committed and use a ref to the target node. In Vue, wait for nextTick(); in Angular, run after the view update. The framework-specific hook only solves insertion timing—you still need the repaint, font, and image waits shown above.
Options that make dynamic captures usable
onclone for capture-only changes
html2canvas clones the document before reconstructing the target. Use onclone to remove transient controls, pause animation classes, or alter capture-only styles without changing the live page. For example:
const canvas = await html2canvas(card, {
onclone: clonedDoc => {
clonedDoc.querySelectorAll('.capture-ignore').forEach(el => el.remove());
clonedDoc.querySelectorAll('.is-animating').forEach(el => {
el.classList.remove('is-animating');
});
}
});
ignoreElements and data-html2canvas-ignore are alternatives for excluding buttons, resize handles, or overlays.
External images: useCORS and proxy
Set useCORS: true when image servers send the required CORS headers. The option cannot override browser security policy: the remote server must permit the request. If it cannot, configure a same-origin image proxy with proxy. Cross-origin iframes and plugin-rendered content remain restricted.
Rank #3
- FAST DOCUMENT SCANNING — Document scanner with feeder allows you to speed through stacks with a 50-sheet Auto Document Feeder (ADF); Efficient office scanner to help you scan more productively
- INTUITIVE, HIGH-SPEED SOFTWARE — Quickly scan with this desktop document scanner; Epson ScanSmart Software lets you easily preview scans, email files, upload to the cloud, and more; Plus, automatic file naming saves even more time
- SEAMLESS INTEGRATION — Easily incorporate your data into most document management software with the included TWAIN driver; Office document scanner integrates seamlessly with business workflows
- EASY SHARING — Duplex scanner allows you to scan straight to email or popular cloud storage2 services like Dropbox, Evernote, Google Drive, and OneDrive for simple storage and sharing
- SIMPLE FILE MANAGEMENT — Scanner allows the creation of searchable PDFs with Optical Character Recognition (OCR) and convert scans to editable Word or Excel files effortlessly; Designed for home and office document scanning
const canvas = await html2canvas(card, {
useCORS: true,
proxy: '/image-proxy'
});
Do not treat a canvas that becomes tainted as a library bug. Fix the asset’s response headers or proxy it from a server you control.
Sharpness and crop
scale defaults to the device pixel ratio. Set it deliberately when output size must be predictable. Use x, y, width, and height to capture a known region. A larger scale increases memory use.
Large or off-screen content
For a long dynamically generated panel, set windowWidth and windowHeight to the dimensions needed for rendering, often the document’s scroll dimensions:
const canvas = await html2canvas(card, {
windowWidth: Math.max(document.documentElement.scrollWidth, document.body.scrollWidth),
windowHeight: Math.max(document.documentElement.scrollHeight, document.body.scrollHeight),
scale: 1
});
Very large canvases can hit browser implementation limits or exhaust memory. Capture sections, reduce scale, or use a browser-level screenshot service when a single giant image is required.
Rank #4
- Scanner type: Document
- Connectivity technology: USB
- With Auto Scan Mode, the scanner automatically detects what you're scanning
- Digitize documents and images
Image timeout
The documented imageTimeout default is 15,000 milliseconds. Lower it for fast-failing UI or raise it for slow assets, while still handling failed images:
const canvas = await html2canvas(card, { imageTimeout: 30000 });
Handling content that arrives later
For data loaded after the div is inserted, do not use a fixed delay as your only synchronization method. Resolve the data request, update the DOM, then run the readiness sequence. If you cannot control the producer, observe only the container and debounce:
let timer;
const observer = new MutationObserver(() => {
clearTimeout(timer);
timer = setTimeout(async () => {
observer.disconnect();
try {
await captureDynamicDiv();
} finally {
observer.observe(document.querySelector('#app'), { childList: true, subtree: true });
}
}, 100);
});
observer.observe(document.querySelector('#app'), { childList: true, subtree: true });
This pattern is an application-level coordination strategy. It prevents repeated captures during a group of related mutations; it is not automatic behavior provided by html2canvas.
Troubleshooting checklist
| Symptom | Likely cause | Fix |
|---|---|---|
| New div is absent | Stale reference, removed node, or capture before render | Capture the returned element reference after append; await a frame and verify it is connected. |
| Blank or zero-size image | display:none, zero dimensions, or hidden ancestor |
Inspect getBoundingClientRect(); render the node visibly before capture. |
| Text wraps differently | Web font not ready | Await document.fonts.ready, then await another frame. |
| Image is missing | Still loading, decode incomplete, or CORS blocked | Await load/decode; use useCORS with correct server headers or a same-origin proxy. |
| Only part of a long panel appears | Viewport or canvas dimensions are too small | Set windowWidth/windowHeight, capture sections, and reduce scale if necessary. |
| Animated state is inconsistent | Capture occurred mid-transition | Pause animation in onclone or remove animation classes from the clone. |
| Iframe or plugin content is blank | Browser same-origin or unsupported-content restrictions | Render the content in your own DOM, configure permitted CORS, or use a browser-level screenshot. |
toDataURL() fails with a security error |
Canvas was tainted by an unpermitted cross-origin image | Correct CORS headers or proxy the image before capture. |
When html2canvas is the right tool
Choose html2canvas when a client-side reconstruction of your DOM is sufficient and you need control inside the page. It is convenient for exporting a card, invoice, chart, or preview after JavaScript has populated it. It is not pixel-perfect: unsupported CSS, cross-origin frames, plugins, and browser rendering details can differ from what the user sees. A browser-level screenshot is the better choice when exact pixels, inaccessible embedded content, or very large pages matter more than running entirely in the client.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Best Value
- OUR MOST ADVANCED SCANSNAP. Large touchscreen, fast 45ppm double-sided scanning, 100-sheet document feeder, Wi-Fi and USB connectivity, automatic optimizations, and support for cloud services. Upgraded replacement for the discontinued iX1600
- CUSTOMIZABLE. SHARABLE. Select personalized profiles from the touchscreen. Send to PC, Mac, mobile devices, and clouds. QUICK MENU lets you quickly scan-drag-drop to your favorite computer apps
- STABLE WIRELESS OR USB CONNECTION. Built-in Wi-Fi 6 for the fastest and most secure scanning. Connect to smart devices or cloud services without a computer. USB-C connection also available
- PHOTO AND DOCUMENT ORGANIZATION MADE EFFORTLESS. Easily manage, edit, and use scanned data from documents, receipts, photos, and business cards. Automatically optimize, name, and sort files
- AVOIDS PAPER JAMS AND DAMAGE. Features a brake roller system to feed paper smoothly, a multi-feed sensor that detects pages stuck together, and skew detection to prevent paper damage and data loss
Or skip the browser setup
ScreenshotNeo provides a website screenshot API and MCP server. One request renders a URL and returns PNG, JPEG, WebP, or PDF. It accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing status.
For a server-side page capture, use the API documented at https://screenshotneo.com/docs/:
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}`);
ScreenshotNeo also supports element selectors, full-page lazy-image loading, dark mode, device presets, retina scale, custom CSS and JavaScript, clicks, waits, blocked requests, headers, cookies, user agents, timezone and geolocation, transparent backgrounds, resizing, chosen cache TTLs, signed links, asynchronous webhooks, bulk capture of up to 100 URLs per call, PDF options, usage data, and an OpenAPI specification. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients.
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. Sign up free for ScreenshotNeo.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Frequently Asked Questions
Does html2canvas wait for a div inserted by JavaScript?
No. It captures the DOM state when called, so your code must coordinate insertion, repaint, fonts, images, and the capture call.
Can I capture a div that is outside the viewport?
Usually, but configure rendering dimensions for long content and account for browser canvas limits. Splitting a very large panel is safer than creating one enormous canvas.
Will html2canvas reproduce every CSS property exactly?
No. It reconstructs supported DOM and CSS into a canvas. Pixel-perfect output, cross-origin frames, and plugin content require a browser-level screenshot approach.
What should I do if the dynamic content is a remote URL rather than local DOM?
Use a browser-level renderer such as ScreenshotNeo, which loads the URL remotely and can wait, run custom JavaScript, select elements, and return an image or PDF.
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 reinstallQuick 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.

