DriversRecommendedOutdated drivers can make a good PC feel brokenScan driver issues before chasing fixes manually.Scan NowOctober 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 Now×
Skip to content
CORS

How to Fix SVGs Not Appearing in html2canvas

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

If an SVG is visible in your browser but missing from an html2canvas result, the usual cause is not the SVG syntax itself. html2canvas walks a cloned DOM and rebuilds pixels from the properties and resources it understands; cross-origin rules, clone-only styles, late rendering, unsupported SVG features, and canvas limits can all produce a blank or partial result.

Start by identifying how the SVG enters the page, then verify loading and dimensions, expose resource errors, fix CORS or proxying, and test the cloned document. The steps below isolate each failure without changing your production page blindly.

1. Identify which kind of SVG is missing

The remedy depends on where the SVG lives. Inspect the element in DevTools and classify it before changing html2canvas options.

  • Inline SVG: an <svg> element in the captured DOM. Its paths, styles, variables, masks, filters, and generated children must survive the clone.
  • External SVG image: an <img src="...svg">. The image must finish loading and satisfy the browser’s origin policy.
  • CSS background: an SVG URL in background-image or a pseudo-element. The computed style in the clone must still contain the URL.
  • SVG dependencies: an <image>, <use>, external stylesheet, font, or referenced file. A missing dependency can make an otherwise valid SVG appear empty.
  • Late component output: markup inserted by React, Vue, Web Components, a chart library, or another script after your capture call. html2canvas cannot capture nodes that do not exist yet.

Take a minimal inline SVG and capture it beside the real component. If the minimal shape works, focus on your application’s markup, resources, or styles rather than the library installation.

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

2. Verify loading, size, and capture geometry

Wait for every dependency

Call html2canvas only after the SVG element exists and its dependent images and fonts have loaded. For an image element, wait for img.decode() when available and handle rejected promises. For a component, wait for its render-complete signal rather than an arbitrary short timeout. A network request that is still pending at capture time can leave an empty image in the clone.

Check computed dimensions

In DevTools, inspect the SVG or image’s computed width and height. Both must be greater than zero. Also check that the node is inside the element passed to html2canvas, is not clipped by an ancestor, and is within the effective viewport. CSS such as display:none, a collapsed flex item, or a zero-sized parent can produce a valid-looking DOM with no drawable area.

Confirm the right node and timing

Use a stable selector and log the node immediately before capture:

const target = document.querySelector('#capture');
const logo = target?.querySelector('svg, img[src$=".svg"]');
console.log({ target, logo, rect: logo?.getBoundingClientRect() });

If the rectangle is zero-sized or logo is null, fix application timing or layout first. This test also catches capturing a wrapper that does not contain the SVG.

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

3. Turn on html2canvas diagnostics

Use logging and the documented onError callback to surface failed image, SVG, and background-image resources. This configuration is a diagnostic baseline:

const canvas = await html2canvas(document.querySelector('#capture'), {
  logging: true,
  useCORS: true,                 // only when the server sends Access-Control-Allow-Origin
  proxy: '/same-origin-image-proxy', // alternative when you control a proxy
  foreignObjectRendering: false, // enable only for a deliberate compatibility test
  onError: error => console.warn(
    'html2canvas resource failed:', error.message
  ),
});
document.body.appendChild(canvas);

Do not enable useCORS and a proxy indiscriminately. Choose one path based on where the SVG is hosted and which server you control. The configuration reference also exposes isResourceSameOrigin, onclone, imageTimeout, windowWidth, and windowHeight for narrower tests.

4. Fix cross-origin SVGs correctly

Use CORS only with a cooperating image server

An external SVG is subject to the same-origin policy. Setting useCORS: true does not grant permission; the SVG response must include an appropriate Access-Control-Allow-Origin header. If the remote server omits that header, html2canvas may skip the resource or the canvas may become unreadable. Check the SVG request in the Network panel and inspect its response headers.

When you control the image server, configure it to return an origin that is allowed by your application (or the permitted wildcard policy for your use case), then keep useCORS: true. Test the actual response, including redirects: a redirect to a host without the header still fails.

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

Use a same-origin proxy when you cannot change the host

A proxy fetches the SVG on your server and serves it from the same origin as the page. Set proxy to that endpoint and remove useCORS unless your implementation specifically needs both. The proxy must validate destination URLs, restrict schemes and hosts, return the correct SVG content type, and avoid becoming an open server-side request forgery endpoint. It also needs suitable caching and timeout limits for production.

Remember nested resources

CORS applies to files referenced inside an SVG as well, such as an embedded raster image, external stylesheet, or font. Making the top-level .svg request accessible does not automatically make every nested URL accessible. Inline those resources where practical or configure headers for each origin.

5. Repair styles and generated content in the clone

html2canvas clones the document before rendering. A style that exists only in runtime state, a stylesheet unavailable to the clone, a CSS variable defined on an ancestor outside the captured node, or markup generated after cloning can disappear even though the original page looks correct.

Use onclone to add clone-only fixes. The callback changes the cloned document, not the live page:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
await html2canvas(document.querySelector('#capture'), {
  onclone: clonedDocument => {
    const svg = clonedDocument.querySelector('#brand-mark');
    if (svg) {
      svg.style.display = 'block';
      svg.style.width = '160px';
      svg.style.height = '40px';
      svg.style.setProperty('--brand-color', '#111827');
    }

    const style = clonedDocument.createElement('style');
    style.textContent = `
      #brand-mark .needs-fill { fill: var(--brand-color); }
    `;
    clonedDocument.head.appendChild(style);
  }
});

Use this for deterministic capture rules, not as a substitute for fixing the application’s real CSS. If the SVG depends on a web font, wait for document.fonts.ready before calling html2canvas and ensure the font resource is available under the same origin or valid CORS.

6. Test foreignObjectRendering as an experiment

foreignObjectRendering is disabled by default. When enabled, html2canvas asks the browser to render HTML through an SVG foreignObject path. It can help with some CSS or SVG combinations, but browser support and CSS behavior vary. Test it as a controlled comparison, not a universal fix:

const options = {
  foreignObjectRendering: true,
  logging: true,
  onError: error => console.warn(error),
};
const canvas = await html2canvas(document.querySelector('#capture'), options);

Capture the same fixture with the option both on and off in every browser you support. If one mode works only in one engine, keep the result browser-specific rather than assuming it is portable.

7. Account for browser-specific SVG behavior

An issue filed on April 13, 2020 reported SVG overflow or incorrect geometry in Safari, Epiphany, and iOS with html2canvas 1.0.0-rc.5, while JPEGs rendered correctly. That report is a compatibility lead, not proof that every current release has the same defect. Reproduce the problem with your current html2canvas version and browser combination.

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

Create a small test page containing only the SVG, explicit pixel dimensions, and one capture button. Compare Chromium, Firefox, and WebKit-based browsers. If WebKit alone fails, simplify transforms, overflow, masks, and nested viewBoxes; also try a raster export for that browser when exact vector fidelity is not required. Record the library version, browser version, SVG markup, and whether the asset is inline or external so a regression can be isolated.

8. Rule out canvas-size limits

If the entire canvas is blank, truncated, or unexpectedly clipped, the SVG may be innocent. Browser canvas dimensions have implementation limits. The html2canvas FAQ gives an approximate maximum dimension of about 32,767 pixels for current Chrome/Chromium, Firefox, and desktop Safari, but the practical limit varies with browser, GPU, operating system, and device.

For a tall page, derive the capture viewport from the element’s scroll dimensions or capture smaller sections:

const element = document.querySelector('#capture');
const rect = element.getBoundingClientRect();
const canvas = await html2canvas(element, {
  windowWidth: Math.max(document.documentElement.scrollWidth, rect.width),
  windowHeight: Math.max(document.documentElement.scrollHeight, rect.height),
  logging: true,
});

Lower the scale, split long documents into panels, or reduce the requested region when memory use is high. A small inline SVG that works in isolation but disappears only on a very large page points to this class of problem.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

9. Remedy by SVG type

SVG form First checks Most reliable remedy
Inline <svg> Clone contains the element, nonzero box, inherited variables and styles Use onclone to provide deterministic CSS; simplify unsupported filters or masks
<img src="...svg"> Image decoded, response headers, redirects, nested resources Same-origin hosting, valid CORS with useCORS, or a controlled proxy
CSS background Computed background in the clone, pseudo-element content, URL origin Move critical artwork into an inline element or make the background resource accessible
<use>/<image> Referenced fragment or file loads under the same origin policy Inline the symbol/resource or expose every dependency to the capture origin
Late component output Render completion and font/image readiness Capture after the component’s committed DOM and resources are ready

10. A repeatable debugging procedure

  1. Capture a minimal inline SVG with explicit width and height.
  2. Capture the real node with logging and onError enabled.
  3. Inspect computed dimensions and verify the node is inside the target.
  4. Wait for image decoding and fonts, then capture again.
  5. For external files, inspect response headers and choose valid CORS or a same-origin proxy.
  6. Use onclone to restore missing variables, styles, or generated markup.
  7. Compare foreignObjectRendering on and off.
  8. Reproduce in each target browser with a small fixture.
  9. If the whole output fails, reduce dimensions or split the capture to test canvas limits.

11. Performance, reliability, and server-side alternatives

Client-side html2canvas runs in the user’s browser, so memory, GPU limits, network conditions, and browser security policy affect the result. Keep capture regions small, avoid unnecessarily high scale factors, cache stable assets, and set an explicit image timeout for slow resources. Log failures in development and remove sensitive URLs or headers from production logs.

For server-side screenshots, the html2canvas FAQ points to browser automation tools such as Puppeteer or Playwright because html2canvas relies on browser APIs (window, document, computed styles) that do not exist in Node.js. That is a different architecture: a real browser loads the page, while html2canvas reconstructs a DOM into a canvas in the page itself.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server for developers. One request returns a PNG, JPEG, WebP, or PDF and handles the browser session for you. Cookie and consent banners, newsletter popups, and chat widgets are removed before the shot. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers identify the page verdict and billing status.

Use the API documented at https://screenshotneo.com/docs/:

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

ScreenshotNeo also provides an MCP server with take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. Every feature is on every plan; the Free plan includes 1,000 shots per month without a card, and paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account to try it.

Troubleshooting common symptoms

Symptom Likely cause Fix
Only a remote SVG is absent Missing CORS header or failed redirect Configure Access-Control-Allow-Origin, or use a same-origin proxy
Inline SVG is blank but text appears Clone lacks styles, variables, or generated children Inspect onclone; add clone-only CSS/content and explicit dimensions
Works after a delay Image, font, or component was not ready Wait for decode, fonts, and render completion before capture
Whole canvas is blank Canvas dimensions or memory limit Use smaller regions, lower scale, and explicit window dimensions
Safari differs from Chrome WebKit SVG geometry or overflow behavior Build a minimal reproduction and test the current versions; simplify geometry
Console shows no useful detail Diagnostics disabled Enable logging and onError; inspect Network responses

Frequently Asked Questions

Can I fix a cross-origin SVG by setting only crossorigin="anonymous"?

No. The SVG server must return a compatible Access-Control-Allow-Origin header, or you must fetch it through a same-origin proxy.

Does html2canvas support every SVG filter and mask?

No. It reconstructs supported DOM and CSS features, so browser display does not guarantee identical html2canvas output. Simplify unsupported effects or use a browser screenshot workflow when exact rendering is required.

Why does an SVG disappear only when it is very tall?

The capture may exceed a browser canvas dimension or memory limit. Test a smaller region and compare the result before changing SVG code.

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

Is html2canvas suitable for Node.js server rendering?

Not by itself. It relies on browser globals and computed styles; server-side capture generally uses a real browser through Puppeteer or Playwright.

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 *

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

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

Read next

Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
Crashes, No Sound, or Screen Glitches?Free driver scan

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.