ScreenshotNeo

BlogHow-to

Take a Screenshot of a Webpage as WebP in Node.js with Playwright

Use Playwright’s page.screenshot() to save a webpage as WebP in Node.js, choose capture options, and troubleshoot common issues.

By the ScreenshotNeo team4 October 20267 min read

Use Playwright’s page.screenshot() with type: 'webp' to capture a webpage as WebP in Node.js. Set path: 'screenshot.webp' to save the image, or omit path to receive the encoded image bytes as a Buffer.

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch();
  try {
    const page = await browser.newPage();
    await page.goto('https://example.com');
    await page.screenshot({ path: 'screenshot.webp', type: 'webp' });
  } finally {
    await browser.close();
  }
})();

Install Playwright and its browser before running the example:

npm install playwright
npx playwright install chromium

Save the script as screenshot.js, then run node screenshot.js. The official Playwright Page API documents WebP screenshots and the options below.

1. Install and run the capture

The example uses CommonJS, which works in a default Node.js project. If your project uses ES modules, replace the first line with import { chromium } from 'playwright'; and keep the rest of the code inside an async function or top-level await.

For a production script, wait for the page state that suits the site. domcontentloaded waits for the initial HTML document to be parsed; it does not guarantee that client-rendered content, images, or API data are ready. load waits for the load event, while networkidle can be unsuitable for applications that keep network connections active. When a particular element indicates readiness, wait for that selector explicitly:

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch();
  try {
    const page = await browser.newPage({ viewport: { width: 1440, height: 900 } });
    await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
    await page.locator('main').waitFor({ state: 'visible' });
    await page.screenshot({ path: 'screenshot.webp', type: 'webp', quality: 85 });
  } finally {
    await browser.close();
  }
})();

Choose a readiness condition based on the page’s behavior. A fixed sleep may be useful for a known animation or delayed widget, but it can waste time on fast pages and still be too short on slow ones.

2. Choose WebP output options

Option What it does When to use it
type: 'webp' Encodes the screenshot as WebP. Set explicitly when the output format matters. Playwright also infers the format from a .webp path.
path Writes the screenshot to a file. Use a path ending in .webp for a saved image.
quality Sets WebP quality from 0 to 100. Use 100 for lossless output; lower values use lossy compression. Compare the results for your pages before choosing a setting.
fullPage Captures the full scrollable page instead of only the viewport. Use true for a long-page capture. This can create a much taller image.
scale Controls output pixel scale: 'css' or 'device'. 'css' gives one output pixel per CSS pixel. 'device' uses device pixels and is the default.
animations Controls whether animations are disabled during capture. Disable animations when you need repeatable captures.
style Applies a stylesheet to the page for the screenshot. Hide or adjust dynamic content for a capture or visual comparison.

For example, this captures the full page at CSS pixel scale, with lossy WebP quality 85:

await page.screenshot({
  path: 'full-page.webp',
  type: 'webp',
  quality: 85,
  fullPage: true,
  scale: 'css',
  animations: 'disabled'
});

The documented quality range is 0–100. Quality 100 produces lossless WebP; lower values use lossy compression. Do not assume a fixed size reduction against PNG: output size depends on the page and the selected quality.

3. Save the screenshot or use its Buffer

With a path, Playwright writes the encoded image to disk. Without one, page.screenshot() resolves to a Node.js Buffer. A Buffer is useful when sending the result to object storage, attaching it to a report, or passing it to another image-processing step.

const imageBuffer = await page.screenshot({ type: 'webp', quality: 90 });

// Example: write the returned WebP bytes to a file.
const fs = require('node:fs/promises');
await fs.writeFile('from-buffer.webp', imageBuffer);

When using a Buffer, keep type: 'webp' explicit so the encoded format is clear to later code. If you need a data URL for an HTML document, convert the bytes with imageBuffer.toString('base64') and prefix them with data:image/webp;base64,.

4. Capture a single element

When only a card, chart, or other component is needed, use a locator’s screenshot method rather than capturing the whole page. Playwright scrolls the element into view first.

const card = page.locator('[data-testid="product-card"]');
await card.screenshot({ path: 'product-card.webp', type: 'webp', quality: 90 });

For a scrollable container, the screenshot includes only the content currently scrolled into view. It does not automatically capture every item inside that container. If the target is a full-page document, use page.screenshot({ fullPage: true, ... }) instead.

5. Use WebP for visual regression tests

For a test snapshot rather than an ordinary image file, Playwright Test can compare a WebP snapshot with expect(page).toHaveScreenshot('landing.webp'). This requires the Playwright Test runner. Playwright documents WebP snapshots as lossless, and the assertion waits for two consecutive screenshots to match before comparing them.

const { test, expect } = require('@playwright/test');

test('landing page stays visually consistent', async ({ page }) => {
  await page.goto('https://example.com');
  await expect(page).toHaveScreenshot('landing.webp');
});

Install the test runner with npm install --save-dev @playwright/test, install the browser with npx playwright install chromium, and run the test with npx playwright test. Review and commit approved snapshots in the same way as other test artifacts.

Rendering may vary with the operating system, browser version, settings, hardware, power source, and headless mode. Generate and compare snapshots in a consistent environment, and control animations or other dynamic page elements where needed. See the Playwright visual comparisons documentation.

6. Make captures more reliable

  • Wait for meaningful content. Prefer a selector or application-specific readiness condition when the screenshot depends on client-rendered data.
  • Set the viewport. Use a fixed width and height when captures need consistent layout.
  • Control motion. Disable animations or apply a stylesheet to prevent changing elements from shifting between captures.
  • Close the browser. Put browser.close() in a finally block so it runs after success or failure.
  • Keep environments aligned for visual tests. Browser and operating-system differences can change rendered pixels.
  • Use full-page capture selectively. Very long pages create tall images and can take more resources to encode and store.

7. Troubleshooting

Symptom Likely cause Fix
Executable doesn't exist or browser launch fails The Playwright browser binary has not been installed for this environment. Run npx playwright install chromium. In a constrained Linux environment, consult Playwright’s browser installation guidance for required system dependencies.
The file is PNG or the downstream service rejects it The format was inferred from a different path extension, or the code did not set the intended type. Use a .webp path and set type: 'webp' explicitly.
The screenshot is blank or missing page content The capture ran before the relevant content appeared, or the page did not finish loading successfully. Check navigation errors and wait for the content selector or application-specific readiness condition before capturing.
The output is larger than expected Lossless quality 100, device-pixel scaling, a large viewport, or a very tall full-page capture can produce larger files. Try a lower lossy quality, use scale: 'css' if appropriate, or capture only the required region. Measure output on representative pages.
Visual test snapshots differ between runs Dynamic content or rendering environment differences can affect pixels. Keep browser and operating-system settings consistent; disable animations and hide or stabilize changing content.
Element capture omits part of a long container Locator screenshots include the currently visible scrolled content of a scrollable container. Capture the page or adjust the container and capture the needed portions deliberately.

8. Performance, reliability, and cost

Playwright captures require a browser process, so browser startup and page loading are part of the work. For repeated captures in one process, reuse a browser and create or close pages as needed instead of launching a new browser for every URL. Always close the browser when the job ends.

Full-page captures, high device-pixel output, and lossless encoding can increase image dimensions, memory use, file size, and storage or transfer costs. Lower lossy quality can reduce output size, but the exact result depends on page content. Benchmark the choices on representative pages when size or processing time matters; the source material does not establish a universal compression ratio or speed gain.

Self-hosted Playwright has no per-screenshot API charge, but your infrastructure still pays for compute, browser dependencies, maintenance, and storage or transfer. For reliability, handle navigation failures and timeouts, wait on page-specific readiness, and ensure cleanup runs in error paths.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server for developers. A single GET request returns an image or PDF; its API accepts the parameter names used by other screenshot APIs, which can make switching easier. See the ScreenshotNeo site and API documentation.

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}`);
const fs = require('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));

Use an API key from your account and consult the ScreenshotNeo docs for format and other request options. Cookie banners, popups, and chat widgets are removed before the shot; 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 a month with no card, and paid plans start at $5 for 3,000 screenshots.

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

FAQ

Does Playwright support WebP screenshots in Node.js?

Yes. Use page.screenshot({ type: 'webp' }), or provide a path ending in .webp.

Is WebP quality 100 lossless?

Yes. Playwright documents quality 100 as lossless; lower quality values use lossy compression.

Can I get WebP bytes without writing a file?

Yes. Omit path; the screenshot call returns a Promise that resolves to a Buffer.

Can Playwright Test use WebP snapshots?

Yes. Use a .webp snapshot name with toHaveScreenshot() in Playwright Test.