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

To turn HTML containing SVG into a PNG, JPEG, or WebP, either reconstruct the page in the browser with a DOM-to-canvas library such as html2canvas, or capture it with a real browser using Playwright. Choose html2canvas for an in-page, client-side export when its CSS and image-origin limits fit. Choose browser capture when you need the browser’s rendered output or server-side generation. SVG embedding mode, external resources, and browser security rules can affect either route, so test the actual markup in the target browser.

Choose the right conversion method

The key decision is whether you need a canvas reconstructed from DOM data or an image of the page as the browser rendered it. Those are different outputs, not merely two ways to run the same screenshot operation.

Method Best fit Main limitation
html2canvas Client-side export from a page already open in a visitor’s browser Rebuilds a representation from DOM information; CSS support is limited to what the library implements, and cross-origin resources can be unavailable.
Playwright screenshot Server-side image generation or a capture where the browser’s actual rendering matters Requires a browser automation setup and control of page loading, viewport, and capture options.
SVG with a foreignObject A specialized client-side technique to wrap serialized HTML in SVG and draw it to a canvas Experimental and sensitive to browser and SVG image-embedding restrictions; not a universal fallback.

html2canvas explicitly says its output is based on DOM information rather than an actual screenshot, and may not match the real page exactly (html2canvas documentation). Its FAQ also notes that each CSS property must be implemented for it to render correctly (html2canvas FAQ). Use a real browser screenshot if fidelity to the browser’s rendered page is the priority.

Convert the page in the browser with html2canvas

This approach runs in the visitor’s browser, where the page’s DOM is available. It is suitable when the export can be a DOM-based reconstruction and the relevant styles and resources are supported. Install or load html2canvas using the method appropriate to your app, then capture the element that contains the content you want.

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

Capture an element as PNG

import html2canvas from 'html2canvas';

const element = document.querySelector('#export-area');
if (!element) throw new Error('Could not find #export-area');

const canvas = await html2canvas(element, {
  backgroundColor: '#ffffff',
  useCORS: true
});

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

The example assumes a browser environment and an element with the ID export-area. If you want a transparent background, set backgroundColor: null and verify the result in the browsers you support. The useCORS option can allow eligible cross-origin images to be requested with CORS; it does not override the remote server’s policy.

Wait for content and fonts before capturing

Capture only after content that affects the export has loaded. For example, wait for the page’s fonts and relevant images before calling html2canvas:

await document.fonts.ready;

const images = [...document.querySelectorAll('#export-area img')];
await Promise.all(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 });
  });
}));

This wait prevents the capture from racing resources, but it cannot make a blocked resource available or add CSS support to html2canvas. If your page inserts content asynchronously, wait for that application-specific work as well.

Export other raster formats

Canvas can encode supported raster formats through toDataURL. For JPEG, supply a background color because JPEG does not preserve transparency:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
const jpeg = canvas.toDataURL('image/jpeg', 0.92);

The quality argument applies to formats that support lossy quality settings. For a Blob rather than a large data URL, use canvas.toBlob() and create a temporary object URL for download. Check the returned Blob: browsers may fall back to PNG for an unsupported requested format.

Understand cross-origin image behavior

Browsers restrict reading canvas pixels when content from another origin is drawn without the required permission. html2canvas’s FAQ explains that remote images may be omitted, or the resulting canvas may be tainted so it cannot be read. For a cross-origin image, use useCORS: true only when the image server sends an appropriate CORS response header, or serve the resource through a same-origin proxy you control. Setting allowTaint does not make a tainted canvas readable (html2canvas FAQ).

Capture rendered HTML with Playwright

Playwright takes a screenshot through an automated browser. This is the more appropriate route for server-side generation or when the browser’s actual rendering is what you intend to preserve. Its Page API documents screenshot output paths and scale options; confirm option behavior against the Playwright version installed in your project (Playwright Page screenshot API).

Runnable Node.js example

Install Playwright and its browser for your environment, then save the following as an ES module. Replace the URL with the page you control or have permission to capture.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import { chromium } from 'playwright';

const browser = await chromium.launch();
try {
  const page = await browser.newPage({
    viewport: { width: 1440, height: 1000 },
    deviceScaleFactor: 1
  });

  await page.goto('http://127.0.0.1:3000', { waitUntil: 'networkidle' });
  await page.evaluate(() => document.fonts.ready);

  await page.screenshot({
    path: 'capture.png',
    fullPage: true,
    type: 'png',
    scale: 'css'
  });
} finally {
  await browser.close();
}

Run the page locally or point page.goto at the target URL. fullPage: true captures the whole page rather than just the viewport. For a viewport-only capture, omit it. To capture one element, locate it with a locator and call its screenshot method, for example await page.locator('#export-area').screenshot({ path: 'element.png' }). For JPEG output, use a .jpg path or specify the supported screenshot type and verify the installed version’s API.

Set dimensions and pixel scale deliberately

The viewport defines the CSS layout being rendered; device scale affects the relationship between CSS pixels and output pixels. Playwright’s screenshot API exposes a scale option for controlling that relationship. Select dimensions that match your intended output, and inspect the saved image’s actual pixel dimensions rather than assuming they follow the CSS viewport one-to-one. Large full-page captures can consume substantial memory and may encounter browser or platform limits.

When page readiness needs more than network idle

Network idle is useful but does not guarantee every image, animation, or application-specific render has settled. If the target has a known readiness condition, wait for it explicitly:

await page.goto('http://127.0.0.1:3000');
await page.locator('#export-area').waitFor({ state: 'visible' });
await page.evaluate(() => document.fonts.ready);
await page.locator('#export-area').screenshot({ path: 'element.png' });

For lazy-loaded images, scroll the relevant content into view or otherwise trigger the page’s loading behavior before capturing. Avoid waiting indefinitely on third-party requests that never settle; use a specific selector or application signal where possible.

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

Account for how the SVG is embedded

“SVG in HTML” can mean inline <svg> markup, an external SVG loaded through <img>, an SVG document opened directly, or HTML nested inside an SVG <foreignObject>. These contexts do not have identical resource or security behavior.

MDN describes restrictions for SVG used as an image, including disabled scripting and unavailable external resources in that context; directly viewed SVG documents and SVG embedded with elements such as <iframe>, <object>, or <embed> have different contexts (MDN: SVG as an image). Check whether the SVG depends on external fonts, stylesheets, images, or scripts, and test that exact embedding mode in the target browser.

Use the foreignObject-to-canvas technique cautiously

A client-side alternative is to serialize HTML into an SVG that contains a <foreignObject>, load that SVG as an image, and draw the image onto a canvas. The html2canvas source includes an experimental renderer based on this general pattern (html2canvas foreignObject renderer). Treat this as an implementation technique to test rather than a guarantee of cross-browser conversion.

SVG conformance text notes that in secure animated image mode, content within foreignObject has scripts, interactivity, and external file references disabled (W3C SVG conformance). Thus, wrapping a page in SVG and loading it as an image can change what is allowed to render. It is not interchangeable with capturing the original live page in a browser.

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

Troubleshoot missing, blank, or inaccurate output

  • A remote image is missing: Check whether it is cross-origin and whether its server returns an appropriate CORS header. In html2canvas, try useCORS when the server permits it, or use a same-origin proxy. A browser screenshot may display an image that client-side canvas code still cannot read.
  • An SVG is missing or incomplete: Identify its embedding mode and dependencies. Inline SVG, an external SVG in an image element, and SVG content inside foreignObject have different resource and security behavior.
  • Styles or layout differ: html2canvas only renders CSS properties it implements. Check its documented support and simplify unsupported effects, or switch to a real browser screenshot when matching browser output matters.
  • The canvas is blank or clipped: Check the requested capture dimensions and target browser’s canvas dimension or area limits. Limits vary by browser and platform, and can produce partial or blank output (html2canvas FAQ).
  • Fonts look wrong: Wait for document.fonts.ready and confirm the intended font actually loaded. A capture cannot reproduce a font that failed to load or is inaccessible.
  • Lazy images are absent: Trigger their loading before capture, for example by scrolling the page or element into view, then wait for the image load state.
  • html2canvas fails on a server: It expects browser globals such as window and document. Use browser automation such as Playwright for server-side rendering, as the project FAQ recommends.
  • A Playwright capture is premature: Wait for a page-specific selector or readiness signal instead of assuming navigation alone means the content is finished.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Plan for quality, performance, and recurring captures

There is no general speed ranking established for these approaches. Performance depends on page complexity, dimensions, loaded resources, browser, and runtime environment, so measure your own target rather than assuming one method is faster.

  • Output size: Larger viewports and full-page captures require more pixels and memory. Capture only the required element or region when possible.
  • Repeatability: Fix the viewport, device scale, fonts, and page state. Dynamic content, animation, and remote resources can change between runs.
  • Privacy: A client-side capture keeps processing in the visitor’s browser; server-side automation loads the page in your infrastructure. Consider what page data and credentials the capture process can access.
  • Dependencies: html2canvas avoids managing a server browser but has its own supported-rendering constraints. Playwright requires browser installation and lifecycle management.
  • Verification: Inspect dimensions and visual completeness, especially for external images, fonts, SVG references, and long pages.

Or skip the browser setup

For a server-side screenshot without installing and managing a browser, ScreenshotNeo accepts a URL in one GET request and returns an image or PDF. It can remove cookie/consent banners, newsletter popups, and chat widgets before capture; those steps can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and responses identify page verdict and billing status in headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for AI agents.

For a page that is already hosted at a URL, the cURL call is:

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

Replace the example URL with your target and supply your API key. The request returns a capture; its exact output depends on the URL and configured request parameters. See the ScreenshotNeo API documentation for options. This is URL-based browser capture, not a replacement for html2canvas when your input exists only as an unhosted DOM in a visitor’s browser.

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

The free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. Sign up for free ScreenshotNeo access.

Make the final choice

Use html2canvas when client-side export is convenient and a DOM-based reconstruction is acceptable. Use Playwright when server-side capture or the rendered browser page is the requirement. Whichever route you choose, validate the exact SVG embedding mode, external assets, fonts, dimensions, and output in the browser you intend to support.

Frequently Asked Questions

Can html2canvas capture an SVG inside an HTML page?

It can render supported DOM and SVG content, but the result depends on the SVG embedding mode, CSS support, and access to referenced resources. Test the actual page rather than assuming every SVG is equivalent.

Does html2canvas make a true screenshot?

No. It reconstructs a representation from DOM information instead of capturing the browser’s rendered pixels.

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

Can I use html2canvas directly in Node.js?

Not as a standalone server renderer: it expects browser globals such as window and document. Use browser automation for server-side capture.

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.