October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsSlow PC?RecommendedPC slow today? Run a repair scan before it gets worseResolve common Windows issues and optimize system performance.Scan NowOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
Canvas

How to Save SVG Images with html2canvas (PNG vs. Real SVG)

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.

html2canvas saves a rendered SVG region as a raster PNG, not as an editable SVG file. Call html2canvas(element), wait for its Promise, convert the returned canvas with toDataURL('image/png'), and download that data URL. If you need vector editability, download the original SVG markup or resource separately; do not rename the PNG to .svg.

Decide which file you actually need

“Save an SVG image” can mean two different jobs. A visual snapshot includes the surrounding DOM, CSS layout, fonts and the SVG as it appears in the browser. An editable asset is the SVG source itself, with paths, text and attributes preserved. html2canvas is designed for the first job: it reconstructs a view from the DOM and properties it understands, then paints that view onto a canvas. The documented download workflow produces PNG data.

Goal Correct method Result
Download what a page region looks like Pass the region to html2canvas and download canvas.toDataURL('image/png') Raster PNG; convenient for previews and reports
Keep paths and text editable Download the inline SVG markup or fetch the original SVG resource SVG source; remains vector and editable
Capture a page without installing browser code Use a screenshot service such as ScreenshotNeo PNG, JPEG, WebP or PDF from an API request

Save a rendered region as a PNG with html2canvas

Minimal browser example

Load html2canvas in your page, give the target a real selector, and trigger the capture from a user action. The anchor’s download value controls the suggested filename.

<button id='save-png' type='button'>Save PNG</button>
<div id='capture'>
  <svg width='320' height='180' viewBox='0 0 320 180' role='img' aria-label='Sample chart'>
    <rect width='320' height='180' fill='#102a43' />
    <circle cx='90' cy='90' r='48' fill='#2f80ed' />
    <text x='160' y='98' fill='white' font-size='22'>SVG chart</text>
  </svg>
</div>
<script src='https://cdn.jsdelivr.net/npm/html2canvas@latest/dist/html2canvas.min.js'></script>
<script>
document.querySelector('#save-png').addEventListener('click', async () => {
  const element = document.querySelector('#capture');
  if (!element) throw new Error('Capture element was not found');
  const canvas = await html2canvas(element);
  const link = document.createElement('a');
  link.download = 'screenshot.png';
  link.href = canvas.toDataURL('image/png');
  link.click();
});
</script>

The Promise resolves to a canvas. Calling toDataURL('image/png') produces a PNG data URL, so the downloaded file is rasterized even when the source inside the region is SVG.

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.

Useful capture options

Set options only for a reason, because each one affects fidelity, security or rendering time.

  • useCORS: true asks the browser to load cross-origin images with CORS. It works only when the asset server sends an appropriate Access-Control-Allow-Origin response.
  • proxy can route supported remote resources through a server you control when direct browser access is not permitted.
  • scale controls output density. A larger value gives more pixels but consumes more memory.
  • backgroundColor sets a solid background; use null when transparency is required and the rendered content supports it.
  • windowWidth and windowHeight define the virtual viewport used during reconstruction. For a full element, matching them to the element’s scroll dimensions can prevent clipping.
  • width, height, x and y limit the capture to a known rectangle when you do not want the entire element.
const element = document.querySelector('#capture');
const canvas = await html2canvas(element, {
  useCORS: true,
  scale: window.devicePixelRatio,
  backgroundColor: null,
  windowWidth: element.scrollWidth,
  windowHeight: element.scrollHeight
});
const link = document.createElement('a');
link.download = '[email protected]';
link.href = canvas.toDataURL('image/png');
link.click();

Download the original SVG when editability matters

Inline SVG

An inline <svg> element already contains the source in the DOM. Serialize it and create a Blob instead of passing it through html2canvas.

function downloadInlineSvg(selector, filename = 'graphic.svg') {
  const svg = document.querySelector(selector);
  if (!(svg instanceof SVGElement)) {
    throw new Error('An inline SVG element is required');
  }
  const source = new XMLSerializer().serializeToString(svg);
  const blob = new Blob([source], { type: 'image/svg+xml;charset=utf-8' });
  const url = URL.createObjectURL(blob);
  const link = document.createElement('a');
  link.href = url;
  link.download = filename;
  link.click();
  URL.revokeObjectURL(url);
}

downloadInlineSvg('#capture svg');

This preserves the SVG markup, but external stylesheets, web fonts and referenced files may not be self-contained. If another editor must open the file offline, inline the required styles and embed or package referenced assets.

SVG loaded as an external resource

For an <img src='diagram.svg'>, request the URL and save the response as a Blob only when the server permits that cross-origin request. Otherwise, download it from the same origin or configure the server; browser security cannot be bypassed by JavaScript.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
async function downloadSvgUrl(url, filename = 'diagram.svg') {
  const response = await fetch(url, { mode: 'cors' });
  if (!response.ok) throw new Error(`SVG request failed: ${response.status}`);
  const blob = await response.blob();
  if (blob.type && !blob.type.includes('svg')) {
    throw new Error(`Expected SVG data, received ${blob.type}`);
  }
  const objectUrl = URL.createObjectURL(blob);
  const link = document.createElement('a');
  link.href = objectUrl;
  link.download = filename;
  link.click();
  URL.revokeObjectURL(objectUrl);
}

downloadSvgUrl('/assets/diagram.svg');

Do not present a canvas PNG as an SVG by changing its extension. It will still contain pixels and will fail wherever vector editing or infinite scaling is expected.

Why the captured SVG can differ from the browser

html2canvas is not a literal screenshot of browser pixels. It reads the DOM and supported CSS properties, then reconstructs the appearance. Unsupported SVG features, filters, masks, blend modes, unusual text rendering, missing fonts and dynamically changed attributes can therefore produce differences. One reported issue describes an SVG line missing from a saved image; treat such reports as asset- and browser-specific, not as proof that every SVG line will disappear.

Capture after the page has finished changing the SVG. If JavaScript adds paths, loads data or swaps classes, wait for that work before calling html2canvas. Test the exact SVG markup and target browsers; current getting-started documentation lists evergreen Chrome/Chromium, Firefox and Safari support, but your deployed versions and fonts are the deciding factor.

Handle cross-origin images and tainted canvases

A remote SVG, raster image or resource referenced by an SVG can taint the canvas. A tainted canvas cannot be read back with toDataURL() or similar APIs. useCORS: true helps only if the remote server explicitly permits your origin. It does not grant permission by itself.

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

Check these conditions

  • Open the asset URL in the network panel and verify the response includes a suitable Access-Control-Allow-Origin value.
  • Use the exact final URL after redirects. A same-origin URL that redirects to a CDN can become cross-origin; a January 17, 2023 repository issue reports this as an edge case where useCORS did not solve the redirect.
  • Use a documented proxy option when you control a server that can fetch and relay the asset with correct headers.
  • Do not rely on allowTaint: true to make exportable pixels. It permits drawing in some cases but does not make a tainted canvas readable.

Prevent blank, clipped or oversized output

Blank or partially captured image

Confirm that the selector resolves, the element is visible, and the SVG has dimensions. For a long page region, compare the element’s scrollWidth and scrollHeight with the windowWidth and windowHeight options. Lazy content must be loaded before capture; html2canvas cannot paint an image that has not arrived.

Canvas-size limits

Browsers impose maximum canvas dimensions and total pixel budgets. A large full-page element combined with a high scale can exceed those limits, yielding a clipped or empty canvas. Reduce the scale, capture sections separately, or lower the virtual window dimensions, then test in every target browser.

Fonts and layout shifts

Wait for web fonts and data-driven layout to settle. Capture after document.fonts.ready when your application uses web fonts, and avoid changing the DOM while html2canvas is traversing it. A stable layout makes repeated downloads more predictable.

Troubleshooting checklist

Symptom Likely cause Fix
SecurityError from toDataURL() Cross-origin resource tainted the canvas Enable server CORS, use useCORS, serve the asset from your origin, or configure a proxy.
SVG is missing a line, filter or text effect Renderer does not implement that property or the asset differs by browser Test the actual markup, simplify or inline the effect, and compare supported browsers.
Image is blank Selector, dimensions, load timing or canvas limit Log the element, wait for assets, set matching window dimensions and reduce scale.
Capture is cut off Viewport dimensions are smaller than the element’s scroll area Set windowWidth/windowHeight from scrollWidth/scrollHeight, or capture in sections.
Downloaded file opens but is not editable It is a PNG raster capture Download the original SVG source using serialization or a permitted fetch.

Performance, reliability and security notes

  • Capturing a large DOM subtree costs CPU and memory because styles and nodes are reconstructed. Capture the smallest useful element.
  • Higher pixel density improves sharpness but multiplies memory use. Choose a scale that matches the display or document where the PNG will be used.
  • Run the capture in response to a user action when possible, and handle Promise rejection so a failed export does not appear successful.
  • Never put private credentials in page JavaScript merely to fetch a protected SVG. Use a server endpoint that authenticates and streams an authorized file.
  • Keep the original SVG available when users may need accessibility, text selection or later editing; a PNG cannot restore that structure.
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 is a website screenshot API and MCP server for developers. It captures a URL as PNG, JPEG, WebP or PDF, rather than requiring html2canvas and a browser page. Before capture it accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups and chat widgets; each cleanup step can be disabled. Only clean shots are billed: bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits cost nothing, and the response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP server exposes take_screenshot, get_page_info and capture_pdf for Claude, Cursor and other MCP clients.

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

Use the API documentation at https://screenshotneo.com/docs/ for authentication and options. A one-request capture looks like this:

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)
r.raise_for_status()
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}`);
if (!res.ok) throw new Error(`Screenshot failed: ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));

ScreenshotNeo supports full-page captures with lazy images loaded, CSS-selector element capture, dark mode, device presets or custom viewports, retina scale, PDF paper and page options, custom CSS and JavaScript, click and wait conditions, request blocking, headers, cookies, user agents, Authorization, timezone, geolocation, transparent backgrounds, resizing, configurable caching, signed links, asynchronous webhooks, bulk capture of up to 100 URLs per call, a usage API and an OpenAPI specification. Parameter names used by other screenshot APIs also work for easier migration.

Plan Included shots Price
Free 1,000 per month $0, no card
Starter 3,000 $5
Growth 15,000 $15
Pro 60,000 $39
Scale 250,000 $99
Business 1,000,000 $249

Every feature is available on every plan, and yearly billing gives two months free. Start with 1,000 free screenshots a month with no card; paid plans start at $5 for 3,000 shots.

Frequently Asked Questions

Can a PNG exported by html2canvas be converted back into editable SVG?

No. The PNG contains pixels only. You need the original SVG markup or resource to retain paths, text and vector editability.

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

Why does the downloaded image look different from a browser screenshot?

html2canvas reconstructs the DOM and supported properties rather than reading browser pixels directly, so unsupported SVG or CSS features can render differently.

What is the safest way to save a protected SVG?

Fetch it through an authenticated server endpoint and stream the response, rather than exposing private credentials in client-side JavaScript.

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 *

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

Read next

Recommended PC Tool
Recommended PC Tool
Outdated Drivers Are Slowing You DownFree scan - exact matches
PC Slower Than It Used to Be?Free scan - under a minute

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.