Keep the inline <svg> in the DOM and call html2canvas(element) normally. html2canvas lists SVG as a supported element: it serializes the SVG and renders that serialization as an image inside the resulting canvas. If the SVG is missing or styled differently, verify its size and the captured bounds, inspect resource errors, then compare the default renderer with the optional foreignObjectRendering mode. Neither path is a native browser screenshot, and neither guarantees pixel-perfect output for every SVG or CSS feature.
What html2canvas does with an inline SVG
html2canvas reconstructs an image from DOM information rather than asking the browser to take a native screenshot. Its feature list explicitly includes inline <svg>. During rendering, the library serializes the SVG element, uses its measured bounds for the serialized image’s dimensions, and draws that image into the canvas. This is why a normal call is the correct first approach:
const target = document.querySelector('#card');
const canvas = await html2canvas(target);
document.querySelector('#output').replaceChildren(canvas);
The returned value is a Promise that resolves to a <canvas>. html2canvas runs in the browser; it is not intended for Node.js. The captured subtree must contain the SVG at render time, and the SVG must have a usable rendered size.
Minimal complete example
This page draws an inline SVG logo and captures the surrounding card. The SVG is not loaded as a separate file, so no cross-origin image request is involved.
Free tools Windows power users keep installed
One-click scans. No signup required.
#1 Best Overall
<button id="capture">Capture</button>
<div id="card">
<svg width="240" height="120" viewBox="0 0 240 120"
role="img" aria-label="Blue circle and label">
<rect width="240" height="120" rx="12" fill="#f3f6ff"/>
<circle cx="52" cy="60" r="28" fill="#2563eb"/>
<text x="96" y="68" font-family="sans-serif" font-size="22"
fill="#111827">Inline SVG</text>
</svg>
</div>
<div id="output"></div>
<script src="https://cdn.jsdelivr.net/npm/html2canvas@latest/dist/html2canvas.min.js"></script>
<script>
document.querySelector('#capture').addEventListener('click', async () => {
const canvas = await html2canvas(document.querySelector('#card'));
document.querySelector('#output').replaceChildren(canvas);
});
</script>
For production, pin the html2canvas version you have tested instead of using a floating CDN tag. Wait until fonts, images and any data used by the SVG are ready before calling the function.
Make the SVG’s geometry unambiguous
Give it a rendered width and height
An SVG with no intrinsic dimensions, a zero-sized parent, or CSS that collapses it can serialize successfully yet contribute no visible pixels. Set width and height, or give the SVG a CSS size, and ensure its parent is displayed when capture starts.
#card svg {
display: block;
width: 240px;
height: 120px;
}
Check the same geometry the library will see:
const svg = document.querySelector('#card svg');
console.log(svg.getBoundingClientRect().toJSON());
console.log(getComputedStyle(svg).display, getComputedStyle(svg).visibility);
Capture a container that includes the SVG
html2canvas(svg) captures only the SVG. If you need its card background, labels or surrounding layout, pass the container instead. Inspect the target’s getBoundingClientRect() as well; an SVG can be visible on screen while being outside an overflow-clipped or off-screen target you selected by mistake.
Rank #2
Wait for layout and fonts
Capture after the relevant state has been applied. In an async flow, wait for document fonts and images before rendering:
await document.fonts.ready;
await Promise.all([...document.images].map(img => {
if (img.complete) return Promise.resolve();
return new Promise(resolve => {
img.addEventListener('load', resolve, { once: true });
img.addEventListener('error', resolve, { once: true });
});
}));
const canvas = await html2canvas(document.querySelector('#card'));
Try foreignObjectRendering as a deliberate comparison
foreignObjectRendering is an optional mode and defaults to false. When enabled, html2canvas asks the browser to draw a foreignObject representation, but the project detects whether the browser supports ForeignObject drawing. Support and visual results are browser-dependent, so treat this as a mode to test—not a universal SVG fix.
const canvas = await html2canvas(document.querySelector('#card'), {
foreignObjectRendering: true
});
Compare both outputs in the browsers your application supports. Look at SVG text, filters, masks, gradients, clipping, inherited styles and surrounding CSS. Keep the mode that produces an acceptable result for your actual documents; do not assume that one renderer wins for every SVG.
External SVG resources, images and origin policy
An inline SVG can reference external assets through an image, pattern, filter, stylesheet or other URL. Those requests still obey browser security policy. The useCORS option is false by default and only helps when the remote server sends suitable CORS headers:
const canvas = await html2canvas(target, {
useCORS: true,
onError(error) {
console.error('html2canvas resource or render error', error);
}
});
onError is a notification hook: html2canvas can continue rendering after a resource failure. It is useful for identifying the URL or stage that failed, but it does not bypass origin restrictions. If the server cannot provide the required headers, use a properly configured proxy (the proxy option defaults to null) or host the asset on an origin you control.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsDo not confuse an inline SVG with an external SVG image. Inline markup is already part of the captured DOM; an external resource must load successfully and be permitted for canvas use. A canvas affected by disallowed cross-origin content may be unusable when you later call toDataURL() or toBlob().
Rank #4
Why the SVG may look different from the browser
Selective CSS support
html2canvas implements CSS properties manually. Its FAQ states that full CSS support is not a goal, so a property can be absent or only partially reproduced even though the live page looks correct. This applies to CSS on the SVG, CSS inherited from ancestors, and CSS used by the surrounding target.
SVG features and computed styles
Test complex features separately: external stylesheets, CSS variables, filters, masks, clip paths, blend modes, animations and web-font text. Freeze animations before capture and provide explicit presentation attributes or computed values when practical. A browser screenshot engine and html2canvas are different rendering paths; matching every paint detail is not an achievable expectation.
Scale and output dimensions
The scale option defaults to the device pixel ratio. A higher scale can improve apparent sharpness while increasing memory and encoding time; it does not add support for an unimplemented CSS property.
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 →Best Value
const dpr = window.devicePixelRatio || 1;
const canvas = await html2canvas(target, { scale: Math.min(dpr, 2) });
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.A repeatable debugging order
- Confirm the target. Log the selected element, its SVG descendants and
getBoundingClientRect(). Verify that the target is visible, has non-zero dimensions and includes the SVG. - Capture the simplest case. Remove unrelated components and reduce the SVG to a rectangle, circle and text. If that works, add filters, masks, external assets and CSS one at a time.
- Inspect logs and
onError. Keep the browser console open and attach the callback shown above. Distinguish a missing resource from a painting difference. - Check origin and network responses. Look for failed requests, redirects, authentication requirements and missing CORS headers. Set
useCORS: trueonly when the server is configured for it; otherwise use a proxy. - Compare renderer modes. Capture once with the default renderer and once with
foreignObjectRendering: truein each target browser. Record which SVG feature differs. - Check timing. Wait for fonts, images, data binding and layout changes. Capture after transitions or animations have settled.
- Build a minimal reproduction. Keep the reduced HTML, CSS, SVG and exact browser/version. A small test case makes an incomplete CSS implementation or browser-specific behavior actionable.
Performance, reliability and export details
- Capture only what you need. A smaller subtree uses less memory and finishes sooner than the entire document.
- Avoid oversized canvases. Large full-page targets multiplied by a high
scalecan exhaust memory. Lower the scale, split the page, or capture a smaller region. - Handle the Promise. Add a
try/catcharound capture so a rejected render does not leave the UI in a loading state. - Choose an export deliberately. Use
canvas.toBlob()for downloadable PNG output without creating a large base64 string; usetoDataURL()only when a data URL is required. - Expect nondeterminism from live pages. Network timing, fonts, animations and responsive layout can change pixels between captures. Freeze those inputs when visual consistency matters.
try {
const canvas = await html2canvas(target, {
backgroundColor: '#ffffff',
onError: console.error
});
canvas.toBlob(blob => {
if (!blob) return;
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = 'capture.png';
link.click();
URL.revokeObjectURL(link.href);
}, 'image/png');
} catch (error) {
console.error('Capture failed', error);
}
Or skip the browser setup
If your requirement is a screenshot of a live URL rather than a canvas reconstructed inside your page, ScreenshotNeo provides a website screenshot API. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups and chat widgets; bot checks, blank pages, timeouts, failed loads and cache hits are not billed, and response headers identify the page verdict and billing status. It also offers an MCP server with take_screenshot, get_page_info and capture_pdf for Claude, Cursor and other MCP clients.
One request returns an image or PDF. See the ScreenshotNeo API documentation for all options:
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 has 63 capture options, including full-page lazy-image loading, CSS-selector element capture, dark mode, device presets, custom viewport and retina scale, PDF controls, custom CSS and JavaScript, clicks, selector or network-idle waits, request blocking, headers, cookies, user agent, authorization, timezone, geolocation, transparent backgrounds, resizing, cache TTL, signed links, async webhooks, bulk capture of 100 URLs per call, a usage API and an OpenAPI specification. Every feature is on every plan. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000. Create a free ScreenshotNeo account.
Frequently Asked Questions
Can html2canvas capture an SVG loaded with an <img> tag?
It may, provided the image loads and its origin policy permits canvas use. For a cross-origin asset, the server must send suitable CORS headers or you need a configured proxy; an inline SVG avoids that separate image request.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Does foreignObjectRendering support every browser?
No. It is browser-dependent, defaults to false, and html2canvas performs feature detection. Test both modes in the browsers and SVG designs you actually support.
Why does my exported canvas become unusable after drawing an SVG?
A cross-origin image or other resource without permission can taint the canvas. Inspect failed requests and response headers, then enable CORS only with server support or route the resource through a properly configured proxy.
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.

