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

A blank or half-rendered dom-to-image result usually means one stage of its export pipeline failed—not that the visible page is empty. Check, in order: page readiness, target visibility, external assets and CORS, SVG/canvas handling, browser support, and output dimensions. The fixes below help you identify the failing stage and correct it without guessing.

Why a page that looks normal can produce a blank image

dom-to-image does not photograph the browser’s already-painted pixels. It recursively clones the selected DOM node, copies computed styles, rebuilds pseudo-elements, embeds fonts and images, serializes the clone as XML inside an SVG foreignObject, and (for PNG or JPEG) rasterizes that SVG in an off-screen canvas. A failure in any intermediate step can leave the final image empty or truncated even though the live page looks correct.

The original project and maintained compatible forks differ in browser behavior and options. Confirm which package and version your application uses before applying a workaround; historical browser statements in the original README should not be treated as a current support matrix.

Use this isolation sequence first

  1. Capture only after the intended state exists. Wait for the target node, layout, injected stylesheets, fonts, and lazy content.
  2. Verify the selected node and its box. Check that it is the element you expect and that its width and height are greater than zero.
  3. Test external resources. Inspect network and console errors for images, fonts, and stylesheets, especially cross-origin requests.
  4. Test special content separately. WebGL, video, and cross-origin iframes have restrictions that ordinary DOM content does not.
  5. Reduce the output. Try a smaller element or lower scale to rule out canvas dimension limits.
  6. Compare a supported browser and package version. If the same node works elsewhere, the problem may be SVG foreignObject behavior or a fork-specific implementation detail.

1. Wait for the real page state

Calling the library immediately after inserting markup is a common cause of an empty capture. The target may exist before its stylesheet, web font, image, or lazy component has finished loading.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#1 Best Overall
Elebase USB to USB C Adapter for iPhone 18 Pro Max,USBC Car Charger Adapter
  • Read Before You Buy — No Video Output: These adapters support charging and USB 2.0 data transfer, but cannot transmit video signals. Except for standard USB webcams (which use USB data only), they are not compatible with HDMI/DisplayPort cables, video-capable USB-C hubs, or docking stations with video output.
  • Convert USB-A Ports to USB-C: Designed to connect USB-C earphones, cables, flash drives, card readers, and other USB-C accessories to standard USB-A ports. Plug-and-play with no drivers or software required.
  • Aluminum Alloy Housing: Built with a sturdy aluminum alloy shell that aids in heat dissipation and protects against daily wear and scratches. Designed to maintain a stable and secure connection.
  • Compact & Travel-Friendly: The ultra-compact design allows the adapter to stay plugged into your device without blocking adjacent ports or adding bulk, reducing wear and tear on your original USB ports.
  • 12-Month Warranty: Backed by a 12-month manufacturer warranty for peace of mind. Designed to meet strict quality control standards for reliable everyday performance.

Wait for stylesheets and fonts

If you inject a stylesheet, await its load event before capturing. The maintained fork waits for fonts already loading through document.fonts.ready, but it cannot wait for a stylesheet that has not started or finished loading.

function waitForStylesheet(link) {
  if (link.sheet) return Promise.resolve();
  return new Promise((resolve, reject) => {
    link.addEventListener('load', resolve, { once: true });
    link.addEventListener('error', () => reject(new Error(`Stylesheet failed: ${link.href}`)), { once: true });
  });
}

async function readyForCapture(root, stylesheetLinks = []) {
  await Promise.all(stylesheetLinks.map(waitForStylesheet));
  if (document.fonts?.ready) await document.fonts.ready;
  await new Promise(requestAnimationFrame);
  await new Promise(requestAnimationFrame);
  if (!root || root.getBoundingClientRect().width === 0 || root.getBoundingClientRect().height === 0) {
    throw new Error('Capture root has no layout size');
  }
}

Also trigger or await lazy content before capture. A library cannot render content that your application has not yet added to the DOM.

2. Check visibility, dimensions, and ancestors

A root with display:none or opacity:0 may have no useful capture box or may be intentionally hidden. Verify the element selected by your query and inspect its computed style and rectangle:

const root = document.querySelector('#receipt');
const rect = root?.getBoundingClientRect();
console.log({
  root,
  display: root && getComputedStyle(root).display,
  opacity: root && getComputedStyle(root).opacity,
  width: rect?.width,
  height: rect?.height
});

The maintained fork offers ensureShown for a hidden capture root. That option cannot reveal a hidden ancestor above the root. Temporarily reveal or move the ancestor, then capture. Avoid using visibility:hidden, collapsed containers, zero-sized flex children, or a selector that matches a template rather than the rendered component.

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

3. Diagnose images, fonts, and other external assets

Every external resource must be fetched and embedded into the clone. A bad URL, missing credentials, blocked request, or cross-origin policy can break that process. Open the browser’s Network and Console panels and look for 404/403 responses, CORS errors, certificate failures, and requests that are still pending when capture begins.

Rank #2
Anker USB-C Hub, 5-in-1 USB Hub for Laptops, 4K HDMI Multiport Adapter
  • 5-in-1 USB-C Hub: Experience comprehensive connectivity featuring a Power Delivery input, two USB-A 2.0 ports, a USB-A 3.0 port, and an HDMI port. (Note: The USB-C power delivery input port is only for connecting an external wall charger to power your laptop and cannot power peripheral devices.)
  • 90W Pass-Through Charging: Achieve optimal charging with 90W pass-through power to your laptop, supported by a total input of 100W, with the hub reserving 10W for operational efficiency. (Note: Wall charger not included.)
  • Quick Data Transfers: Accelerate your productivity with rapid data transfers using a high-speed 5Gbps USB 3.0 port and two 480Mbps USB 2.0 ports.
  • 4K HDMI Display: Enhance your visual experience with a hub capable of delivering 4K resolution at 30Hz in both mirror and extend modes. Please note that this hub is compatible with MacBook (macOS 12 and newer), Windows 10 and 11, ChromeOS, and laptops equipped with DP Alt Mode and Power Delivery. Note: This device is not compatible with Linux.
  • What You Get: Anker USB-C Hub (5-in-1, 4K HDMI), welcome guide, 18-month warranty, and our friendly customer service.

Cross-origin images

Browser security prevents JavaScript from reading pixels from an image that lacks suitable CORS permission. A client-side library cannot grant itself that permission. Serve the image with an appropriate Access-Control-Allow-Origin response, use a controlled same-origin proxy, or use the maintained fork’s documented requestInterceptor/corsImg facilities. Credentials and allowed origins must match your deployment.

As a diagnostic, replace external images with a same-origin test asset. If the capture then works, fix delivery rather than changing canvas code. The maintained fork documents that broken content images can be skipped so the rest of the image renders; attach a rejection handler because errors during final rasterization can still reject the promise.

domtoimage.toPng(root)
  .then(dataUrl => {
    const img = new Image();
    img.src = dataUrl;
    document.body.appendChild(img);
  })
  .catch(error => {
    console.error('dom-to-image capture failed', error);
  });

Fonts and CSS

Missing font files can change layout or prevent the clone from completing. Confirm that font requests succeed, await document.fonts.ready, and ensure stylesheets are accessible from the page that performs the capture. A stylesheet loaded from an origin that refuses access can leave the clone visually incomplete.

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

4. Handle canvas, WebGL, video, and iframes

WebGL

WebGL drawing buffers may be cleared before the library reads them. The maintained fork requires the context to be created with preserveDrawingBuffer: true when you need a snapshot:

const gl = canvas.getContext('webgl', { preserveDrawingBuffer: true });

You must set this at context creation; enabling it later cannot restore an already-created buffer.

Rank #3
Sale
Anker USB C Hub, 7in1 Multi-Port USB Adapter, 4K@60Hz USBC to HDMI Splitter
  • Sleek 7-in-1 USB-C Hub: Features an HDMI port, two USB-A 3.0 ports, and a USB-C data port, each providing 5Gbps transfer speeds. It also includes a USB-C PD input port for charging up to 100W and dual SD and TF card slots, all in a compact design.
  • Flawless 4K@60Hz Video with HDMI: Delivers exceptional clarity and smoothness with its 4K@60Hz HDMI port, making it ideal for high-definition presentations and entertainment. (Note: Only the HDMI port supports video projection; the USB-C port is for data transfer only.)
  • Double Up on Efficiency: The two USB-A 3.0 ports and a USB-C port support a fast 5Gbps data rate, significantly boosting your transfer speeds and improving productivity.
  • Fast and Reliable 85W Charging: Offers high-capacity, speedy charging for laptops up to 85W, so you spend less time tethered to an outlet and more time being productive.
  • What You Get: Anker USB-C Hub (7-in-1), welcome guide, 18-month warranty, and our friendly customer service.

Video

Video frames are not captured reliably by this pipeline. Use an accessible poster image or draw an allowed frame into a same-origin canvas, then capture that replacement.

Cross-origin iframes

Content inside an iframe from another origin is not readable by page JavaScript. Capture a representation you control, use a same-origin integration, or perform the capture in a context with access to the content. Do not expect a DOM clone to bypass the browser’s same-origin policy.

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.

Tainted canvases

If a canvas contains pixels from a source without CORS permission, reading it can fail. Fix the source headers or proxy the asset; changing the dom-to-image call does not remove the restriction.

5. Reduce oversized captures and partial output

Browsers impose implementation-dependent limits on canvas dimensions and total pixel area. Excessive scale can produce a blank canvas, an image that stops halfway, or a rejected promise. Test the smallest useful case first, then increase dimensions gradually.

  • Capture a child region instead of the entire page.
  • Lower the library’s scale or pixelRatio option.
  • Split a long document into several regions and combine them server-side or in a separate image step.
  • Remove unnecessary shadows, huge gradients, and off-screen content while diagnosing.

The maintained fork reports clamping an excessive multiplier and logging a warning. That behavior is fork-specific; do not assume every dom-to-image release handles oversized output the same way. The general html2canvas FAQ likewise warns that oversized canvases can be blank or partial, which is useful evidence for the class of failure but not a guarantee about a particular dom-to-image version.

Rank #4
Sale
UGREEN USB to USB C Adapter Combo 4-Pack, 10Gbps USB C Converter Space Gray
  • Dual Converters, Infinite Potential:Includes 2× USB C male to USB A female adapters and 2× USB A male to USB C female adapters. Perfect for a wide range of uses—tablets with Bluetooth keyboards, expand USB ports on macbook, and more. Two different converters for all your daily needs
  • Next-Level 10Gbps & 3A Charging: No more slow 480Mbps, this usb to usb c adapter has a transfer speed of up to 10Gbps, allowing you to do more transferring in less time. This usb adapter fits both USB A and USB C charger, supporting up to 3A fast charging
  • Upgraded Exquisite Craftsmanship: With an aluminum alloy housing and metal connector, the usbc to usb adapter is extremely durable and sturdy. Rigorously tested to withstand more than 10,000 times of plugging and unplugging, ensuring long-lasting performance
  • Broad Compatible: The usb c to usb adapter widely supports all USB C/ USB A devices like laptops, tablets, cellphones, car chargers, and phone chargers. Such as compatible with MacBook Pro/Air 2023/2022, Thunderbolt 4/3 Devices,Apple MagSafe Watch 9/8/7/SE/Ultra, iPad Pro 2022/2021, Samsung Galaxy S23/S20/S10, and iPhone 17/16/15 Pro. Plug and play
  • Please Note: To reach 10Gbps speed, keep the cable under 3.3 ft. For USB A Male to USB C adapters, try flipping the USB C connector. USB C Male to USB A adapters support bidirectional 10Gbps transfer within 3.3 ft

6. Browser and package differences

SVG foreignObject support and security rules vary by browser. The original project describes Safari as unsupported because of stricter foreignObject security; the maintained fork calls Safari unreliable and suggests generating SVG and rasterizing it server-side. Treat this as a compatibility limitation, not a missing CSS declaration.

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

Reproduce the same node in another browser that your chosen fork supports, record the exact package version, and test its SVG output separately from PNG/JPEG output. If SVG is correct but PNG is blank, the failure is in rasterization rather than cloning.

Practical diagnostic matrix

Symptom Likely stage Next check
Completely blank output Readiness, hidden root, CORS, WebGL, or canvas size Log dimensions, replace external assets, lower scale
Only fonts or images missing Resource embedding Inspect network responses and await fonts/stylesheets
Bottom half is cut off Canvas dimensions or clone layout Capture a smaller region and reduce scale
Works in one browser only foreignObject or browser security Check fork support and generate SVG/server-render
WebGL area is empty Discarded drawing buffer Create the context with preserveDrawingBuffer: true
Promise rejects at the end Final rasterization Catch the error and inspect tainted or oversized canvas causes
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Client-side capture versus server-side rendering

Client-side dom-to-image is convenient when the page, assets, and browser context are under your control. It is less suitable when you need broad browser consistency, inaccessible third-party content, or very large output. A server-side browser renderer can load a page in a controlled environment and avoid many client CORS and foreignObject differences, but it adds infrastructure, authentication, waiting, and cost considerations. Choose based on access to source assets, required browser coverage, output size, and deployment architecture rather than assuming one approach is universally best.

Or skip the browser setup

ScreenshotNeo is a hosted website screenshot API and MCP server. One GET request returns PNG, JPEG, WebP, or PDF. Before capture it accepts cookie/consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be turned off. Bot checks/CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers report the page verdict and billing status.

Use the API when you want a clean page render without configuring a local browser. Full-page capture, lazy-image loading, CSS-selector element capture, device presets, custom CSS/JavaScript, waits, request blocking, headers/cookies, geolocation, PDF options, caching, signed links, asynchronous jobs, bulk capture, and an MCP server for AI agents are available. See the ScreenshotNeo documentation for parameters and response details.

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

Best Value
Anker USB C Hub, 5-in-1 USBC to HDMI Splitter with 4K Display
  • 5-in-1 Connectivity: Equipped with a 4K HDMI port, a 5 Gbps USB-C data port, two 5 Gbps USB-A ports, and a USB C 100W PD-IN port. Note: The USB C 100W PD-IN port supports only charging and does not support data transfer devices such as headphones or speakers.
  • Powerful Pass-Through Charging: Supports up to 85W pass-through charging so you can power up your laptop while you use the hub. Note: Pass-through charging requires a charger (not included). Note: To achieve full power for iPad, we recommend using a 45W wall charger.
  • Transfer Files in Seconds: Move files to and from your laptop at speeds of up to 5 Gbps via the USB-C and USB-A data ports. Note: The USB C 5Gbps Data port does not support video output.
  • HD Display: Connect to the HDMI port to stream or mirror content to an external monitor in resolutions of up to 4K@30Hz. Note: The USB-C ports do not support video output.
  • What You Get: Anker 332 USB-C Hub (5-in-1), welcome guide, our worry-free 18-month warranty, and friendly customer service.

When to replace dom-to-image

Keep the library when you control the page and need a browser-side export. Consider a maintained fork when its fixes and options match your application. Move to server-side rendering when Safari or cross-origin restrictions are decisive, when output is consistently too large, or when you need repeatable captures outside a user’s browser. In every case, first prove whether the failure is readiness, visibility, resources, special content, rasterization, or dimensions; that diagnosis determines the least disruptive fix.

Frequently Asked Questions

Why is the produced canvas empty or cuts off halfway through?

That wording describes two different failures: an empty canvas usually points to hidden or not-ready content, blocked resources, WebGL buffer loss, or an excessive canvas size; a halfway image most often requires reducing capture dimensions or scale and checking the clone’s layout.

Can dom-to-image capture a cross-origin iframe?

No. Browser same-origin rules prevent the page from reading another origin’s iframe contents. Use a same-origin integration, an accessible representation, or a rendering context that has permission to access the content.

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

Should I use PNG, JPEG, or SVG while debugging?

Try SVG first to separate cloning and serialization from canvas rasterization. If SVG is correct but PNG or JPEG is not, investigate canvas security, WebGL preservation, and output dimensions.

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.