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

Keep the inline <svg> inside the element you pass to html2canvas(), then call the function normally. html2canvas explicitly supports SVG elements by serializing each SVG and rendering that serialized image. If the result is missing or styled differently, verify the SVG’s rendered bounds and resources first; only then compare the optional foreignObjectRendering mode.

What html2canvas actually renders

html2canvas reconstructs an image from the target DOM. It is not a native browser screenshot facility: it reads DOM and CSS information and draws only the features implemented by the library. Consequently, output can differ from what the browser displays, especially for CSS properties or SVG features that the renderer does not implement. The project’s FAQ says that every CSS property must be implemented manually, so full CSS support is not a goal.

Inline SVG is nevertheless a documented feature. The normal renderer serializes the <svg> element, measures its parsed bounds, assigns dimensions to the serialized representation, and draws it as an image. This is the path to try first.

Basic inline-SVG example

The getting-started API accepts a DOM element and an optional options object. It returns a Promise that resolves to a canvas.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
<div id="card">
  <h2>Weekly sign-ups</h2>
  <svg width="320" height="120" viewBox="0 0 320 120" role="img" aria-label="A rising line chart">
    <rect width="320" height="120" fill="#f4f7fb" />
    <polyline points="20,95 80,70 140,78 200,42 270,52 305,20"
      fill="none" stroke="#1769e0" stroke-width="5" stroke-linecap="round" stroke-linejoin="round" />
    <circle cx="305" cy="20" r="6" fill="#1769e0" />
  </svg>
</div>
<button id="save">Save PNG</button>
<script src="https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js"></script>
<script>
  const card = document.querySelector('#card');
  document.querySelector('#save').addEventListener('click', async () => {
    const canvas = await html2canvas(card);
    const link = document.createElement('a');
    link.download = 'card.png';
    link.href = canvas.toDataURL('image/png');
    link.click();
  });
</script>

For a production page, load the version your application has approved rather than silently changing versions through a CDN. The API is browser-side; the getting-started documentation does not describe it as a Node.js renderer.

Capture only the SVG

const svg = document.querySelector('#card svg');
const canvas = await html2canvas(svg, { scale: window.devicePixelRatio });
document.body.appendChild(canvas);

Capturing the parent is usually preferable when surrounding labels, backgrounds, or layout matter. Capturing the SVG itself makes geometry problems easier to see.

Make the SVG measurable before rendering

html2canvas uses the element’s measured bounds when it serializes the SVG. An SVG with no effective width or height, a collapsed parent, or a target outside the visible layout can therefore produce an empty or clipped result.

  • Inspect svg.getBoundingClientRect() in DevTools. Confirm that width and height are greater than zero.
  • Give the SVG an explicit width and height, or ensure its CSS and viewBox produce a non-zero used size.
  • Check that the element passed to html2canvas contains the SVG and is not replaced, hidden, or clipped by a parent.
  • Wait until fonts, data-driven markup, and layout-changing scripts have finished before calling the function.
const target = document.querySelector('#card');
const svg = target.querySelector('svg');
console.log({
  target: target.getBoundingClientRect().toJSON(),
  svg: svg?.getBoundingClientRect().toJSON(),
  svgMarkup: svg?.outerHTML.slice(0, 200)
});
const canvas = await html2canvas(target);

The bounds check is diagnostic, not a guarantee: unusual SVG constructions can still expose implementation gaps.

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

Try the ForeignObject renderer when the normal path differs

foreignObjectRendering is an optional mode. Its default is false. When enabled, html2canvas asks the browser to draw the DOM through an SVG ForeignObject, where supported. Project code performs feature detection for ForeignObject drawing, so availability is browser-dependent.

const canvas = await html2canvas(document.querySelector('#card'), {
  foreignObjectRendering: true
});

Use this as a comparison, not a universal fix. Test both modes in the browsers your application supports and compare:

  • whether the inline SVG appears at all;
  • stroke widths, clipping, filters, text, and inherited styles;
  • images or backgrounds referenced by the SVG;
  • the final dimensions and visual fidelity.

Do not assume that ForeignObject wins for every SVG. A browser may support the feature while still producing different results for particular CSS, SVG, or resource combinations.

External images, fonts, and origin policy

An inline SVG can contain external references such as raster images, fonts, or stylesheets. Browser security rules still apply. The useCORS option defaults to false; setting it to true only helps when the remote server sends appropriate CORS headers.

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.
const canvas = await html2canvas(target, {
  useCORS: true,
  onError(error) {
    console.error('html2canvas resource/render error:', error);
  }
});

If the origin cannot provide the required headers, configure a proxy (the documented proxy option defaults to null) rather than attempting to bypass browser security. A proxy must fetch the resource server-side and return it with headers suitable for the browser. Avoid embedding secrets in client-side proxy URLs.

onError is a notification hook for resource-load or render failures; html2canvas can continue rendering after reporting an error. Check the browser console, network panel, and callback output for the specific URL that failed.

CSS and SVG features that look different

Inline SVG support does not mean every styling mechanism is reproduced. The library implements CSS properties individually. If a property is absent or only partly rendered, simplify the case and test the smallest example that still fails.

  • Replace complex filters, masks, or blend modes with a simple fill and stroke to identify the unsupported feature.
  • Move critical presentation from external stylesheets into SVG attributes or inline styles for a controlled test.
  • Check inherited color, font, and opacity values on the SVG and its ancestors.
  • Compare a static SVG with the same SVG after JavaScript has populated data or changed attributes.

This approach distinguishes a geometry problem from a CSS-implementation limitation.

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

A practical debugging order

  1. Confirm the target. Log the element passed to html2canvas and verify that it contains the expected inline <svg>.
  2. Confirm rendered bounds. Inspect getBoundingClientRect() for both target and SVG; correct zero dimensions, clipping, or premature capture.
  3. Capture the simplest case. Try a rectangle and one path with explicit dimensions. Add styling and effects back one feature at a time.
  4. Inspect failures. Read console messages, network errors, and the onError callback. Pay special attention to cross-origin URLs.
  5. Test origin handling. Use useCORS: true only with a server that sends suitable CORS headers; otherwise use a configured proxy.
  6. Compare renderer modes. Run once with the default renderer and once with foreignObjectRendering: true in each target browser.
  7. Check output scaling. The scale option defaults to the device pixel ratio. Set it deliberately when comparing screenshots or controlling memory use.
  8. Reduce to a minimal reproduction. Remove unrelated DOM, CSS, scripts, and SVG features. A small reproducible case is the project’s recommended way to investigate missing or partial CSS rendering.

Common symptoms and fixes

Symptom Likely cause Next action
SVG is absent Zero-sized/collapsed bounds, wrong target, or a resource/render failure Log bounds and target contents; add onError; test a minimal SVG
Only external artwork is missing Cross-origin response lacks permission Use server CORS headers or a proxy; do not rely on useCORS alone
Styles are incomplete CSS property is not fully implemented Reduce the CSS, inline critical SVG presentation, and compare renderer modes
Output is clipped Measured bounds or parent overflow do not include the artwork Set explicit dimensions and inspect every ancestor’s layout
Modes disagree by browser ForeignObject support and implementation vary Choose the mode that meets your supported-browser tests; do not generalize from one browser

Performance, reliability, and output expectations

Capture only the subtree you need. Large full-page DOM trees, high scale values, embedded images, and complex SVG filters increase memory and rendering time. Delay capture until the visual state is stable, and avoid starting several large captures simultaneously. Treat the returned canvas as generated output: export it with toBlob() for large files instead of keeping many data URLs in memory.

There is no documented promise of pixel-perfect parity with a browser screenshot. Validate the exact SVG and browsers important to your product, and retain a fallback such as the original SVG or a server-side rendering path when visual fidelity is a hard requirement.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

ScreenshotNeo provides a website screenshot API and MCP server. A single request captures a URL as PNG, JPEG, WebP, or PDF, which is useful when you need the rendered page rather than a canvas reconstructed in your app.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

See the ScreenshotNeo documentation for options. Before capture it accepts cookie/consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers report the page verdict and billing status. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. Sign up free.

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

FAQ

Does html2canvas support inline SVG?

Yes. The documented feature list says SVG elements are serialized and rendered as images. Individual SVG, CSS, and resource combinations can still fail or differ.

Should I always enable foreignObjectRendering?

No. It is off by default and depends on browser support. Compare it with the default renderer for the browsers and SVG features you actually use.

Can html2canvas run in Node.js?

The getting-started documentation describes a browser-side API returning a canvas and does not present it as a Node.js renderer.

Will useCORS: true bypass security errors?

No. The remote server must send suitable CORS headers; otherwise use a properly configured proxy.

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

Frequently Asked Questions

Can an SVG loaded through an external <img> be treated like inline SVG?

It follows image loading and origin rules rather than the documented inline-element path. Test it separately, and ensure the response is permitted by CORS or served through a proxy.

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.