Converting SVG to an Image with JavaScript
How to turn an SVG logo into a PNG or other raster image with JavaScript, using an image element and a canvas, plus the caveats that matter for favicon files.
Contents
The short answer
In the browser, you convert an SVG to a raster image by loading the SVG markup into an image element, drawing that image onto a canvas at the pixel size you need, and exporting the canvas as a PNG, JPEG or similar bitmap. The result is a raster copy of the artwork. It is no longer vector, so it cannot be scaled up cleanly or edited as paths. For a vector logo, the SVG stays the master file, and each exported image is a fixed-size output made for a specific use, such as a favicon.
What is being converted
An SVG file is XML markup. It can describe shapes, paths and text, and it can also carry embedded raster images. Converting it to an image means rasterizing it: the browser renders the markup into a grid of pixels at a chosen width and height. Shapes and paths render sharply at whatever size you pick. Any bitmap embedded inside the SVG renders only as sharply as its own resolution allows. Rasterizing therefore does not improve an SVG that is mostly a wrapped bitmap, and the .svg extension alone does not prove the file contains editable vector paths.
The standard browser approach
The sequence uses only standard browser APIs. First, serialize the SVG to a string. Second, wrap the string in a Blob with the image/svg+xml type and create an object URL for it. Third, load that URL into an Image and wait for it to decode. Fourth, draw the image onto a canvas sized to the output dimensions. Fifth, export the canvas with toBlob or toDataURL.
async function svgToPng(svgElement, width, height) {
const svgText = new XMLSerializer().serializeToString(svgElement);
const blob = new Blob([svgText], { type: "image/svg+xml;charset=utf-8" });
const url = URL.createObjectURL(blob);
try {
const img = new Image();
img.src = url;
await img.decode();
const canvas = document.createElement("canvas");
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, width, height);
return await new Promise((resolve, reject) => {
canvas.toBlob(
(result) => (result ? resolve(result) : reject(new Error("Export failed"))),
"image/png"
);
});
} finally {
URL.revokeObjectURL(url);
}
}
The function returns a PNG Blob. You can offer it as a download, upload it, or turn it into an object URL for preview. If you start from an SVG string instead of an element on the page, skip the serialization step. In that case, make sure the root svg element declares the SVG namespace, because a standalone SVG loaded as an image will not render without it.
Details that change the output
- Intrinsic size: give the SVG a viewBox, and ideally width and height attributes. Without them, the browser may not know the artwork's proportions and can draw it at an unexpected size.
- Aspect ratio: if the canvas proportions differ from the viewBox proportions, drawImage stretches the artwork. Match the ratio, or calculate an offset to center it.
- Fonts: an SVG loaded through an image element cannot fetch external resources. Text set in a web font may fall back to a system font. Converting text to outlines in the master artwork, or embedding the font, avoids this.
- Linked images: the same restriction applies to bitmaps referenced by external URL. They need to be embedded inside the SVG to appear in the output.
- Background: PNG keeps transparency. JPEG does not, so fill the canvas with a background color first if you export to JPEG.
- Canvas security: if the canvas becomes tainted by cross-origin content, export calls fail. Building the SVG from same-origin markup through a Blob URL is the usual way to stay within these rules. Behavior has differed between browsers for some SVG features, such as foreignObject, so test the targets you support.
How this applies to favicons
Favicon work is a common reason to rasterize a logo. Many current browsers accept an SVG favicon directly, but sites often still ship raster fallbacks for platforms and contexts that expect PNG or ICO files. The canvas method covers the PNG part: call the function once per required size. Drawing directly at each target size usually gives cleaner results than scaling one large PNG down. Small sizes still need a design check, because fine strokes and detailed lettering in a full logo can blur at favicon scale. A simplified mark is often drawn for that purpose.
Canvas exports cover PNG, JPEG and, in some browsers, WebP. They cannot produce an ICO file. Creating an ICO means packing one or more PNG images into the ICO container in a separate step, either with a dedicated library or with a build tool.
Outside the browser
Node.js has no built-in canvas or SVG renderer, so server-side or build-time conversion depends on a rasterization library or a headless browser. Libraries such as sharp and resvg-js are commonly used for this. Their font handling, feature coverage and output fidelity differ from browser rendering and from each other. Compare their output against the reference artwork before you rely on one for production logo files.
Rights and file handling
Converting a file is a technical step and does not change what you are allowed to do with the artwork. Being able to download a logo's SVG does not grant permission to modify it, rasterize it for other uses, or use its fonts and trademark. Check the brand owner's guidelines or license before producing derived files for a logo you do not own. For your own logo, keep the vector master as the source of truth and regenerate raster files from it whenever the design changes.
Evidence gaps
This overview relies on general, documented browser behavior. No specific tools, benchmarks, browser support figures or required favicon dimensions were supplied, so none are stated here. Confirm current browser support and your target platforms' icon size requirements against up-to-date documentation before finalizing a favicon set.