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

Use Playwright’s Page API: launch a browser, open a page, navigate to the URL, call page.screenshot(), then close the browser. This complete Node.js example saves a PNG:

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

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

Run it after installing Playwright and its browser binaries according to the current Playwright setup documentation. The example uses Chromium; replace chromium with firefox or webkit when you need another engine.

What the basic screenshot call does

page.screenshot() captures the currently visible viewport unless you request a full-page image. Supplying path writes the result to disk; omitting it returns a Node.js Buffer. The output format is inferred from the filename extension and is PNG by default.

Save a viewport screenshot

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

(async () => {
  const browser = await chromium.launch();
  const page = await browser.newPage({ viewport: { width: 1440, height: 900 } });
  await page.goto('https://example.com');
  await page.screenshot({ path: 'artifacts/home.png' });
  await browser.close();
})();

The path is relative to the process’s current working directory. Create the artifacts directory first, or write to an existing absolute path.

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

Return a Buffer instead of creating a file

const screenshot = await page.screenshot();
console.log(`Captured ${screenshot.length} bytes`);

A buffer is useful when you need to upload the image, attach it to a report, or transform it in memory.

Install and run a small Node.js script

  1. Create a project directory and initialize a package:

    mkdir playwright-shot
    cd playwright-shot
    npm init -y
  2. Install Playwright:

    npm install playwright
  3. Install the browser engine you intend to use with the current Playwright browser-install command. The exact command and supported Node.js versions can change, so use the current official setup guidance for your release.

  4. Save the first example as capture.js and run:

    node capture.js

If the script completes, screenshot.png appears in the directory from which you ran node.

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

Take a full-page screenshot

Set fullPage: true to capture the page’s complete scrollable height rather than only the viewport:

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

(async () => {
  const browser = await chromium.launch();
  const page = await browser.newPage({ viewport: { width: 1366, height: 768 } });
  await page.goto('https://example.com', { waitUntil: 'networkidle' });
  await page.screenshot({
    path: 'artifacts/full-page.png',
    fullPage: true
  });
  await browser.close();
})();

Full-page capture is based on the rendered document. Content that appears only after scrolling, or images loaded by a page’s lazy-loading code, may require you to scroll or wait for a specific element before capturing.

Choose image format, quality and pixel scale

PNG, JPEG and WebP

await page.screenshot({ path: 'page.jpeg', type: 'jpeg', quality: 80 });
await page.screenshot({ path: 'page.webp', type: 'webp', quality: 80 });

Playwright supports PNG, JPEG and WebP. PNG is the default. The quality option applies to JPEG and WebP, not PNG. You can also let the filename extension determine the format.

Rank #2
Sale
HTML and CSS: Design and Build Websites
  • HTML CSS Design and Build Web Sites
  • Comes with secure packaging
  • It can be a gift option

CSS pixels versus device pixels

await page.screenshot({ path: 'css-scale.png', scale: 'css' });
await page.screenshot({ path: 'device-scale.png', scale: 'device' });

scale: 'css' produces one output pixel per CSS pixel. scale: 'device' uses device pixels and is the Page API default, so a high-DPI context can produce a larger image.

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

Transparent background

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

omitBackground: true removes the default page background where transparency is supported. It does not apply to JPEG, which has no alpha channel; use PNG or WebP for a transparent result.

Capture one element instead of the page

Use a locator when you need a header, chart, card or other component. Locator screenshots wait for the target to be actionable and scroll it into view:

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

(async () => {
  const browser = await chromium.launch();
  const page = await browser.newPage();
  await page.goto('https://example.com');
  await page.locator('header').screenshot({ path: 'artifacts/header.png' });
  await browser.close();
})();

Prefer locator APIs over the discouraged ElementHandle screenshot API. The selector must match an element that exists in the rendered page. If an overlay covers it, the captured pixels can differ from what you expect. For a scrollable container, the screenshot contains the content currently visible inside that container, not every item hidden in its own scroll area.

Freeze animation for repeatable images

await page.screenshot({
  path: 'artifacts/stable.png',
  animations: 'disabled'
});

await page.locator('.hero').screenshot({
  path: 'artifacts/hero.png',
  animations: 'disabled',
  style: `* { caret-color: transparent !important; }`
});

Disabling CSS and Web Animations reduces movement while the screenshot is taken. Locator screenshots also support temporary screenshot-specific CSS through the style option.

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

Wait for the page you actually want to capture

Navigation completing does not always mean that application data, fonts or images are ready. Wait for a meaningful selector or an application-specific condition:

await page.goto('https://example.com/dashboard');
await page.locator('[data-testid="dashboard"]')
  .waitFor({ state: 'visible' });
await page.screenshot({ path: 'artifacts/dashboard.png', fullPage: true });

For pages where network activity eventually settles, waitUntil: 'networkidle' can help, but it should not replace a selector-based readiness check on applications that keep analytics or live connections open. A fixed delay can be used when no better signal exists:

await page.goto('https://example.com');
await page.waitForTimeout(1500);
await page.screenshot({ path: 'artifacts/after-delay.png' });

Use delays sparingly: they make runs slower and can still be too short or unnecessarily long.

Set viewport, device and page state

Viewport dimensions affect responsive layouts. Set them when a screenshot must be reproducible:

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
const page = await browser.newPage({
  viewport: { width: 390, height: 844 },
  deviceScaleFactor: 2
});

For authenticated pages, create a context with the required storage state or set cookies before navigation. For a dark-mode capture, use the context’s color-scheme setting:

const context = await browser.newContext({
  viewport: { width: 1440, height: 900 },
  colorScheme: 'dark'
});
const page = await context.newPage();

Keep these state choices in code so a later run can reproduce the same pixels.

Use screenshots in Playwright Test

Ordinary Page API screenshots are appropriate for documentation, monitoring and ad-hoc artifacts. Playwright Test has separate features for failure evidence and visual comparisons.

Capture only when a test fails

// playwright.config.js
module.exports = {
  use: {
    screenshot: 'only-on-failure'
  }
};

Documented modes also include off, on and on-first-failure. These settings belong in Playwright Test configuration; they are not required for a standalone script.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

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

Compare against a visual baseline

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

test('home page matches its baseline', async ({ page }) => {
  await page.goto('https://example.com');
  await expect(page).toHaveScreenshot('home.png');
});

toHaveScreenshot waits for two consecutive screenshots to be the same before comparing with the expected image. That stabilization behavior makes it different from simply writing one screenshot file.

Rank #4
Sale
Web Design with HTML, CSS, JavaScript and jQuery Set
  • Brand: Wiley
  • Set of 2 Volumes
  • A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers

Attach a buffer to test output

const screenshot = await page.screenshot();
await testInfo.attach('screenshot', {
  body: screenshot,
  contentType: 'image/png'
});

Playwright copies the attachment to a reporter-accessible location. Use this when a custom test step needs an image without creating a separately managed artifact path.

Common failures and fixes

“Executable doesn’t exist” or browser launch failure

The Playwright package is present but the selected browser binary is not installed, or the binary is unavailable in the execution environment. Install the browser required by your Playwright release and verify that the process has permission to launch it.

“Timeout exceeded” during navigation

The site may be slow, blocked, waiting on a never-ending request, or inaccessible from the runner. Confirm the URL, inspect the page response, and wait for a concrete selector instead of requiring network idle. Increase a narrowly scoped timeout only after identifying the slow operation.

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

The screenshot is blank or shows a consent dialog

Capture occurs exactly as the browser sees the page. Wait for the main content, handle the site’s consent flow when permitted, and hide or close an overlay before calling screenshot. A bot challenge or login wall cannot be bypassed merely by changing screenshot options.

The element locator matches nothing

Check the selector against the rendered DOM, wait for the component to appear, and account for frames or shadow DOM. If the element is inside an iframe, obtain the frame locator first.

Images or fonts are missing

Wait for the relevant image or component, and ensure the page has completed the requests needed for rendering. A long fixed delay is less reliable than waiting for a selector or a page-specific readiness signal.

The full-page image is unexpectedly large

Full-page mode includes the entire scrollable document. Reduce the viewport width only if that matches your intended layout, use JPEG or WebP with an appropriate quality value, or capture a specific locator instead.

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

Output differs between machines

Differences can come from browser engine, installed fonts, viewport, device scale, color scheme, animation, time, locale or remote data. Pin those inputs where possible, disable animations, and use a consistent browser environment for visual assertions.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Performance, reliability and cost considerations

  • Reuse a browser: for many URLs, launch one browser and create or reuse contexts rather than launching a new process for every image.
  • Limit page work: block unnecessary resources only when doing so will not change the visual result you need.
  • Control concurrency: too many simultaneous pages can exhaust CPU, memory or file descriptors and cause timeouts.
  • Write deterministic paths: include a unique name or test identifier when parallel jobs could overwrite files.
  • Close resources: use try/finally so the browser closes even when navigation or capture throws.
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: 'artifacts/example.png' });
  } finally {
    await browser.close();
  }
})();

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server when you want one HTTP request instead of managing Playwright browsers. It accepts cookie and consent banners like a visitor, removes more than 60 known consent platforms plus newsletter popups and chat widgets before capture, and lets you turn each cleanup step off. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed; each response identifies the result with X-Page-Verdict and X-Billed headers.

Basic cURL request (see the ScreenshotNeo documentation for all options):

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

The same request in Python:

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)

And in Node.js:

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(`HTTP ${res.status}`);
const data = Buffer.from(await res.arrayBuffer());
require('fs').writeFileSync('shot.webp', data);

ScreenshotNeo also supports full-page and element capture, dark mode, device presets, retina scale, PDFs, custom CSS and JavaScript, clicks, selector or network-idle waits, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, chosen cache TTLs, signed image links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, a usage API and an OpenAPI specification. Its parameter names are compatible with those used by other screenshot APIs, which can simplify migration. An MCP server provides take_screenshot, get_page_info and capture_pdf tools for Claude, Cursor and other MCP clients.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Plan Included screenshots Price
Free 1,000 per month $0; no card
Starter 3,000 $5
Growth 15,000 $15
Pro 60,000 $39
Scale 250,000 $99
Business 1,000,000 $249

Yearly billing gives two months free, and every feature is available on every plan. Sign up for the free plan to get 1,000 screenshots a month without a card.

Frequently Asked Questions

Can I capture a screenshot without saving it to disk?

Yes. Omit the path option; page.screenshot() returns a Buffer that you can upload, attach to a report or process in memory.

What is the difference between a full-page screenshot and an element screenshot?

fullPage: true captures the document’s complete scrollable page. A locator screenshot captures one matched element after scrolling it into view.

Should I use Page screenshots or Playwright Test screenshots?

Use the Page API for application code and standalone capture. Use Playwright Test’s screenshot settings and toHaveScreenshot for failure artifacts and visual regression checks.

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

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.