ScreenshotNeo

BlogHow-to

Fix SVG Icons That Disappear When Converting HTML to PNG

SVG icons can appear in the browser but vanish from PNG exports. Identify the converter, check how each icon is loaded, and fix the failing resource or CORS path.

By the ScreenshotNeo team4 October 20269 min read

A browser-visible SVG icon can disappear in a PNG export because the export tool uses a separate rendering and resource-loading path. First identify the converter and how the icon is embedded; if you use html2canvas, check its resource errors and cross-origin settings, then make the SVG and its dependencies load in a way the browser permits. There is no universal switch that fixes every converter or bypasses browser security.

This guide uses html2canvas for runnable examples. If your application uses another library or a server-side browser, its options and behavior may differ. Start with a small reproduction in the same browser and library version as your real export.

1. Identify how the icon reaches the page

Inspect the icon in the DOM and classify it before changing export settings:

  • Inline SVG: the <svg> element and its shapes are in the HTML.
  • SVG image: an <img src="...svg"> loads a separate file.
  • CSS background: a rule such as background-image: url(...) loads the SVG as a resource.
  • External SVG sprite: markup such as <svg><use href="/icons.svg#check"></use></svg> refers to a symbol in another file.

Inline SVG is a useful first diagnostic because it removes a separate network request. External SVG files and sprite references have additional loading paths; an SVG used as an image may also have restrictions on external resources it tries to load. Check the browser’s Network and Console panels for the SVG, sprite, stylesheet, font, or image requests involved.

2. Reproduce the export with html2canvas

Install html2canvas in your project using your package manager, then capture a specific element after it has rendered:

import html2canvas from 'html2canvas';

const element = document.querySelector('#report');
if (!element) throw new Error('Capture target #report was not found');

const canvas = await html2canvas(element, {
  backgroundColor: '#ffffff',
  scale: window.devicePixelRatio || 1,
  useCORS: true,
  imageTimeout: 15000,
  onError(error) {
    console.error('html2canvas resource error:', error);
  }
});

const png = canvas.toDataURL('image/png');
const link = document.createElement('a');
link.href = png;
link.download = 'report.png';
link.click();

The useCORS option asks html2canvas to attempt CORS-enabled image loading. It does not grant permission: the asset server must return suitable CORS headers. The callback helps surface resource failures, but inspect the browser console and network requests too. For a basic diagnostic, set scale: 1 and use a small target so output size does not obscure the resource problem.

See the html2canvas configuration reference for the options supported by the version you use, and its FAQ for documented browser content policy limitations.

3. Fix the failing resource path

Inline the SVG to test external loading

Temporarily replace an external SVG image or sprite use with an inline SVG containing the same paths. If the inline version appears in the PNG, the failure is likely in the external resource path or one of its dependencies. This is a diagnostic, not proof that every renderer supports the SVG features in question.

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true">
  <path d="M5 12l4 4L19 6" fill="none" stroke="currentColor" stroke-width="2"/>
</svg>

If the SVG depends on CSS variables, external stylesheets, web fonts, or linked images, check whether those dependencies are present in the export context. A self-contained SVG or one with dependencies embedded as data URLs can narrow down external-load problems. SVG image contexts restrict loading external resources such as images and stylesheets; embedding can help diagnose that case, though renderer support still matters. See the MDN guide to SVG as an image.

Enable CORS only when the server allows it

For a cross-origin image or SVG, use useCORS: true with html2canvas and configure the asset server to allow the origin that is loading it. Verify the response headers in the Network panel. If the remote server does not grant permission, a client-side option cannot override that policy.

When you control the application, alternatives include serving the asset from the same origin or retrieving it through an application-side proxy that you control. Ensure the proxy only fetches appropriate resources and returns the content type and caching behavior your application expects.

Check external sprite references

An <svg><use> reference can look correct in the live page while its separate sprite request fails during capture. Confirm that the sprite URL resolves from the page’s origin, the fragment identifier names an existing symbol, and the request succeeds before starting the export. As a test, inline the referenced symbol or use a local sprite.

4. Understand canvas security and relevant html2canvas options

Canvas export has a security boundary. Drawing an image from another origin without the required CORS permission can taint the canvas; reading or exporting a tainted canvas can raise a SecurityError. The html2canvas FAQ states that it cannot circumvent browser content policy restrictions. Do not treat allowTaint as a CORS bypass: allowing a draw does not make a tainted canvas readable.

Option What it does When to consider it Limit
useCORS Attempts to load images using CORS. A cross-origin image server is configured to allow the requesting origin. Cannot supply missing server permission; documented default is false.
proxy Uses a proxy for resource loading. You have a suitable proxy path for resources that the browser cannot load directly. Requires a working proxy; it is not a browser security bypass.
imageTimeout Sets the image load timeout. A legitimate asset is slow and you need to test whether timing is the issue. Increasing it does not fix an invalid URL, denied CORS request, or unsupported SVG feature. The documented default is 15000 ms.
onError Receives resource errors during rendering. You need diagnostic logging for failed loads. Use it alongside Network and Console inspection.
foreignObjectRendering Selects an alternative rendering path supported by html2canvas. You suspect the library’s rendering path is involved and want a controlled comparison. It is renderer- and browser-dependent; documented default is false.
allowTaint Controls whether tainting images may be drawn. Only when you understand the consequences for later canvas reads. Does not make a tainted canvas safe to export or bypass CORS.

Change one setting at a time and compare the result in the target browser. The project configuration documentation is the authority for available options and defaults; confirm them against the installed version.

5. Use a short diagnostic checklist

  1. Record the converter name and version, browser, and whether the icon is inline, an image, a background, or an external sprite.
  2. Check Network and Console for failed SVG, sprite, stylesheet, font, or image requests.
  3. Wait for the icon and its dependencies to load before starting capture.
  4. Try an inline, self-contained SVG to isolate external loading.
  5. For cross-origin assets, verify the response’s CORS headers and use the converter’s CORS option where applicable.
  6. Test a same-origin asset or suitable application proxy if you cannot change the remote server.
  7. For html2canvas, compare rendering settings one at a time and review the installed version’s documentation.
  8. If the output canvas raises a security error, fix the resource permission path; do not rely on allowTaint to make the canvas readable.

6. Troubleshooting common symptoms

Symptom Likely cause What to try
Icon is visible in the page but missing in the PNG The export renderer could not load or render the resource. Check resource requests and try an inline SVG reproduction.
Only remote SVGs disappear The remote server denies CORS, or the renderer’s cross-origin loading path is not enabled. Verify response headers; for html2canvas, test useCORS: true. Use same-origin hosting or a suitable proxy if needed.
Inline icon works, external sprite icon does not The sprite request, URL, or symbol fragment is failing. Inspect the sprite response and fragment; test a local or inline symbol.
Export throws SecurityError The canvas is tainted by a cross-origin resource. Load the asset through a permitted CORS path or same-origin route before reading or exporting the canvas.
Icon appears inconsistently Capture starts before the icon or dependency finishes loading, or a request times out. Wait for the relevant resource or selector, inspect network timing, and adjust the documented timeout only if the asset is merely slow.
Inline SVG still disappears The issue may be unsupported markup or styling, an SVG feature, or a renderer/browser limitation. Reduce the SVG to a simple path, remove dependencies, and compare a minimal reproduction in the exact browser and converter version.

7. Performance, reliability, and cost considerations

For client-side capture, keep the capture target and its dependencies as small as practical. A full-page export has more content and resources to render than a single component. Higher output scale increases pixel dimensions and memory use, so begin with scale 1 while diagnosing and increase it only when resolution requires it. A longer image timeout can accommodate slow assets but also makes a failed capture wait longer.

Reliability depends on making the same resources available to the export renderer that the page needs, and testing in the browsers you support. Record the converter version and browser with bug reports. Browser security policy remains in effect even when the page itself displays the icon correctly.

Client-side libraries avoid a separate screenshot API charge, but your application still bears browser execution, debugging, and maintenance costs. If you run captures in your own browser infrastructure, account for the resources and operational work that setup requires. The appropriate choice depends on whether you need an in-browser export or a repeatable capture service.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. Its API takes a URL and returns an image or PDF. For a page capture, use the documented request format below; see the ScreenshotNeo API documentation for authentication and available parameters. This captures a URL; it is not a substitute for debugging a broken client-side html2canvas pipeline.

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 request failed: ${res.status}`);
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer())));

Replace the example URL with the page you want to capture and use your API key. ScreenshotNeo removes cookie banners, newsletter popups, and chat widgets before capture. Bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000.

Sign up free for 1,000 screenshots a month, with no card required.

Frequently asked questions

Will changing the icon from SVG to PNG always fix the export?

No. A PNG can follow the same cross-origin loading and canvas rules. First determine whether the problem is resource loading, CORS, or renderer support.

Does useCORS: true make any remote SVG exportable?

No. It asks html2canvas to attempt CORS loading. The remote server must permit the request, and the SVG must be supported by the renderer.

Why does the icon show on screen but not in my downloaded image?

The browser’s normal page display and the export renderer can load and draw resources differently. A successful page display does not prove the export pipeline can use every resource.

What details should I include when asking for help?

Share a minimal reproduction, converter and version, browser, the icon’s markup type, relevant console or network errors, and whether the asset is same-origin or cross-origin.

Primary references