ScreenshotNeo

BlogHow-to

How to Take a Puppeteer Screenshot of an SVG Web Page

Capture a rendered SVG with Puppeteer as a page, full-page image, clipped region, or transparent element screenshot—with reliable readiness checks.

By the ScreenshotNeo team4 October 20267 min read

Use Puppeteer’s page.screenshot() to save the rendered page, or select the SVG and call element.screenshot() to capture just the graphic. Set the viewport and capture extent deliberately. For a hosted page, navigate to its URL; for HTML you already have, use page.setContent(). The examples below save PNG files.

1. Install Puppeteer

Use a current Node.js installation and install Puppeteer in your project. The package downloads a compatible browser as part of its normal installation.

npm install puppeteer

Save the following as screenshot-svg.mjs. It captures an SVG element from a hosted page. Replace the URL and selector with the page and SVG you want to capture.

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch();
try {
  const page = await browser.newPage();
  await page.setViewport({ width: 1200, height: 800 });
  await page.goto('https://example.com/chart', { waitUntil: 'networkidle2' });

  const svg = await page.waitForSelector('svg');
  await svg.screenshot({ path: 'svg-element.png' });
} finally {
  await browser.close();
}

Run it with node screenshot-svg.mjs. Puppeteer’s screenshot guide documents page and element captures; its options reference covers extent, format, and background behavior. See the Puppeteer screenshots guide and ScreenshotOptions reference.

2. Choose what to capture

Capture the visible viewport

Once the page is ready, call page.screenshot() without fullPage. This captures the current viewport dimensions.

await page.screenshot({ path: 'svg-viewport.png' });

Capture the whole page

Set fullPage: true when the page is taller than the viewport and you need its full scrollable content. For an SVG inside a long page, this includes the surrounding page too; use an element capture if you only need the graphic.

await page.screenshot({ path: 'svg-full-page.png', fullPage: true });

Capture only the SVG

Wait for the SVG or a stable wrapper selector, then screenshot its element handle. The element screenshot operation scrolls the element into view as needed. If the application replaces or removes that node before capture, the handle can become detached; query it again after the page finishes rendering. See ElementHandle.screenshot().

const graphic = await page.waitForSelector('#chart svg');
await graphic.screenshot({ path: 'chart.png' });

Capture a specific rectangle

A clip is expressed in CSS pixels relative to the page. Use it when you want a fixed region of the viewport, rather than an element’s bounds. Choose coordinates and dimensions that fit the rendered content.

await page.screenshot({
  path: 'chart-region.png',
  clip: { x: 100, y: 120, width: 700, height: 450 }
});

3. Load the SVG from a URL or HTML

Use page.goto() for a URL that serves the page or builds the SVG in the browser. Pick a navigation wait condition that suits the site, then also wait for the application-specific signal that tells you the graphic is complete.

await page.goto('https://example.com/chart', { waitUntil: 'networkidle2' });
await page.waitForSelector('#chart svg');
// If the app exposes a reliable readiness flag, wait for that too.
await page.waitForFunction(() => window.chartReady === true);
const chart = await page.waitForSelector('#chart svg');
await chart.screenshot({ path: 'chart.png' });

The readiness flag above is an example: your page must actually define it. networkidle2 is a navigation condition, not proof that every font, animation, image, or application render is finished. Use a selector, application event, or other condition tied to the content you need. The official guide demonstrates navigation waits but does not define one universal SVG-ready condition.

Supply markup directly

When your script already has the HTML string, use page.setContent(). This example embeds an inline SVG and captures it. setContent() assigns the supplied markup to the page; it does not fetch a separate hosted page for you.

import puppeteer from 'puppeteer';

const html = `<!doctype html>
<html>
  <body>
    <svg xmlns="http://www.w3.org/2000/svg" width="640" height="360" viewBox="0 0 640 360">
      <rect width="640" height="360" fill="#eef4ff"/>
      <circle cx="320" cy="180" r="90" fill="#356ae6"/>
    </svg>
  </body>
</html>`;

const browser = await puppeteer.launch();
try {
  const page = await browser.newPage();
  await page.setViewport({ width: 800, height: 500 });
  await page.setContent(html);
  const svg = await page.waitForSelector('svg');
  await svg.screenshot({ path: 'inline-svg.png' });
} finally {
  await browser.close();
}

For the API details, see Puppeteer’s Page.setContent() reference.

4. Set dimensions, format, and background

Need Setting Notes
Control responsive layout page.setViewport({ width, height }) Set before navigation when the site’s layout depends on viewport size.
Capture below the fold fullPage: true Captures the page’s full scrollable extent, not just the SVG.
Capture a region clip: { x, y, width, height } Coordinates and size are in CSS pixels.
Use a transparent default background omitBackground: true Does not remove a background explicitly painted by the SVG or page CSS.
Choose an output type type: 'png', 'jpeg', or 'webp' PNG is the documented default; file extension can also determine the type.

To request a transparent page background, use PNG and omitBackground. The SVG or its CSS may still paint an opaque background, such as a full-size rectangle. Remove or change that drawing or style if you need transparency in those areas too.

await page.screenshot({
  path: 'chart-transparent.png',
  omitBackground: true
});

For a format without alpha transparency, do not expect transparent pixels to be preserved. Consult the Page.screenshot() method and options reference for supported screenshot settings.

5. Make captures repeatable

  1. Keep the browser setup consistent. Use the same Puppeteer and browser versions, viewport, and device scale configuration for comparisons.
  2. Wait for the graphic’s real ready state. A visible <svg> node may still be changing because data, fonts, or animations are incomplete.
  3. Control the page inputs. Keep the URL, data, relevant assets, and page state stable between captures.
  4. Decide how animation should behave. If an SVG animates, capture only after the intended frame is reached, using an application signal or a controlled test state.
  5. Close the browser in a finally block. This releases the browser process even when navigation or capture fails.

Puppeteer’s cited documentation does not promise pixel-identical output across browser versions, operating systems, or font environments. For visual comparisons, treat the browser, fonts, viewport, input page, and timing as part of the capture setup.

6. Common errors and fixes

Symptom Likely cause What to do
waitForSelector('svg') times out The page has no inline SVG, the selector is wrong, or the app has not rendered it. Inspect the page DOM and use the actual SVG or wrapper selector. Wait for the app’s render condition if creation is delayed.
Screenshot is blank or missing chart details Capture happened before data or rendering completed, or the graphic is outside the selected clip. Wait for an app-specific ready signal; check the element bounds, viewport, and clip coordinates.
Element screenshot reports a detached node The page replaced the selected element after Puppeteer found it. Wait for the final render, then call waitForSelector() again and capture the new handle.
Transparent option still looks opaque The SVG or CSS paints its own background. Remove or adjust the background element/style; omitBackground only omits the default page background.
Output dimensions are unexpected Responsive layout, viewport size, full-page extent, or element bounds differ from what was assumed. Set the viewport explicitly and choose viewport, full-page, clip, or element capture intentionally.
Browser fails to launch in deployment The runtime lacks required browser dependencies or is configured differently from local development. Check Puppeteer’s launch error and deployment environment, install the required dependencies, and use a compatible browser/runtime configuration.
Capture intermittently misses a font or external asset Navigation finished before the resource or page-specific rendering did. Wait for the relevant resource or app readiness condition instead of assuming a generic network wait is sufficient.

7. Performance, reliability, and cost

Launching a browser for every single image adds startup work. For repeated captures in one process, keep a browser open and create or reuse pages carefully, while closing pages when finished. A full-page capture or a large SVG can require more memory and image processing than a viewport or element capture. Set only the dimensions and extent you need.

Navigation and application waits affect latency. An unbounded or overly broad wait can leave a job waiting on unrelated network activity; a wait that is too early can produce incomplete output. Use a bounded timeout appropriate to your service and an app-specific condition where possible. For production capture jobs, handle navigation failures, timeouts, and browser process exits, and retry only when the failure is transient. Keep retries bounded so a permanently unavailable page does not consume worker capacity.

Puppeteer itself is software you run, so operating cost depends on your compute, browser runtime, and workload. Account for browser process memory, concurrency, and deployment maintenance. If you need a hosted one-call API instead of managing browser setup, ScreenshotNeo’s product details and configuration are at ScreenshotNeo and its API docs.

8. Or skip the browser setup

ScreenshotNeo takes a screenshot from one GET request. This example captures a page that contains an SVG and saves the returned image bytes as WebP:

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

See the ScreenshotNeo API documentation for the request options. Cookie banners, popups, and chat widgets are removed before the shot. Bot checks, blank pages, and failed loads are never billed. An MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000.

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

FAQ

Can Puppeteer screenshot an external SVG file directly?

Navigate to a page that displays the SVG, or create HTML that embeds it, then capture the rendered page or element. The screenshot APIs capture browser-rendered content.

Why is the saved file PNG when my SVG is vector?

A screenshot is a raster image of the browser rendering. Puppeteer’s screenshot output defaults to PNG; the original SVG markup remains vector data.

Will networkidle2 always mean my SVG is ready?

No. It is a navigation wait condition, not a universal signal for application rendering, fonts, or animation completion. Wait for the condition your page uses to indicate readiness.