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

With Playwright, the core workflow is to launch a browser, open a page, navigate to a URL, wait for the state you need, capture the viewport or full page, and close the browser. The example below is a runnable Node.js script; the rest of the guide shows how to capture a specific element, handle interaction-driven navigation, and avoid common reliability problems.

Set up Playwright and run a first capture

Use Playwright when you need control over a real browser session: it can navigate pages, interact with them, and save screenshots from the rendered result. This example uses Node.js and writes a viewport screenshot to screenshot.png.

  1. Install Node.js, then create a project and install Playwright: npm init -y followed by npm install -D playwright.
  2. Install a browser managed by Playwright: npx playwright install chromium.
  3. Save the following as capture.mjs and run it with node capture.mjs.
import { chromium } from 'playwright';

const browser = await chromium.launch({ headless: true });
try {
  const context = await browser.newContext({
    viewport: { width: 1440, height: 900 },
  });
  const page = await context.newPage();

  const response = await page.goto('https://example.com', {
    waitUntil: 'load',
    timeout: 30_000,
  });

  if (!response) {
    throw new Error('Navigation did not return a main-document response');
  }
  if (!response.ok()) {
    throw new Error(`Page returned HTTP ${response.status()}`);
  }

  await page.screenshot({ path: 'screenshot.png' });
  await context.close();
} finally {
  await browser.close();
}

The URL should include its scheme, such as https://. The browser context holds page-level settings such as viewport size; closing the context and browser releases the session. Playwright’s official Page API documents navigation and screenshot options.

Navigate reliably and decide when a page is ready

page.goto() is appropriate for direct navigation. The waitUntil setting controls the lifecycle milestone Playwright waits for; it does not guarantee that every late-loading image, application request, animation, or third-party widget is finished. Choose a signal that matches what the screenshot needs, rather than adding an arbitrary long delay to every page.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • load waits for the page load event. This is a practical default for many pages, but does not mean all dynamic content is settled.
  • domcontentloaded waits for the document to be parsed, which can be faster when later resources do not matter to the capture.
  • networkidle waits for network activity to become idle, but can be unsuitable for sites that keep requests open or poll continuously.
  • For a particular application state, prefer waiting for a meaningful locator, such as a heading or results container: await page.getByRole('heading', { name: 'Dashboard' }).waitFor().

A valid navigation response may still have an HTTP error status. Playwright does not treat a 404 or 500 response as a navigation exception, so inspect the response when your workflow needs to fail on such statuses. A null response can occur when navigation does not produce a standard main-document response, so handle that possibility separately.

Wait for navigation caused by a click

When an action is expected to change the URL, wait for that URL explicitly instead of taking the screenshot immediately after the click. The URL wait and interaction should be coordinated so the listener is active before the action:

const destination = page.waitForURL('**/account', { timeout: 15_000 });
await page.getByRole('link', { name: 'Sign in' }).click();
await destination;
await page.screenshot({ path: 'account.png' });

Use a URL pattern appropriate to the site. If an interaction updates the page without changing the URL, wait for the resulting visible state instead—for example, a confirmation message becoming visible.

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

Choose the screenshot scope and output

Use the capture method that matches what you need to inspect or store. Playwright’s screenshot guide covers these modes and their options.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Capture How Best for
Visible viewport await page.screenshot({ path: 'view.png' }) A reproducible view at the current viewport dimensions.
Full page await page.screenshot({ path: 'full.png', fullPage: true }) A long page’s scrollable content in one image.
One element await page.locator('.receipt').screenshot({ path: 'receipt.png' }) A focused component, card, receipt, or other selected region.
Image bytes const bytes = await page.screenshot() Passing the image into a comparison, upload, or storage pipeline instead of writing it to disk.

A locator screenshot requires the target element to be present and actionable for capture. Prefer a stable selector or accessible locator over a brittle positional selector. If a match is missing, check that the page reached the intended state and that the selector describes the current markup.

Format, quality, and pixel scale

Screenshot output can be PNG, JPEG, or WebP; the file extension or an explicit type option determines the format. JPEG and WebP support a quality setting; quality is not relevant to lossless PNG output. When image size matters, choose the format and quality deliberately, then verify that downstream tools accept them.

Rank #3
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

The screenshot scale option distinguishes CSS pixels from device pixels. scale: 'css' produces one image pixel per CSS pixel; scale: 'device' follows the device scale factor and can create larger high-density output. This matters for visual comparison: changing scale changes the image dimensions and may change apparent sharpness.

Capture a defined viewport

Set the viewport when creating the browser context, before navigation, if layout dimensions matter. A 1440-by-900 viewport in the first example is a desktop-sized CSS viewport, not a promise that the page will render identically on every operating system or browser build. Mobile-size viewport changes can expose responsive behavior that a site handles differently; use a device profile or explicitly set viewport and screen settings when reproducing a mobile case.

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

Make captures useful for testing and debugging

Control animation and dynamic content

Animations, rotating banners, timestamps, live data, and delayed widgets can make captures inconsistent. Playwright screenshot options can disable animations and mask selected locators when those elements are irrelevant to a visual check. Masking is useful for volatile content, but avoid masking the very region you are trying to verify.

For a component that appears asynchronously, wait for that component rather than assuming a fixed sleep will always be long enough. Fixed delays can waste time on fast runs and still be too short on slow ones. If the site has a meaningful loading indicator, wait for it to disappear or for the final result to become visible.

Keep visual comparisons reproducible

Playwright Test’s toHaveScreenshot assertion waits for consecutive screenshots to stabilize before comparing with an expectation. That helps reduce transient noise, but it cannot make different environments identical. Operating system, browser version, rendering settings, hardware, power conditions, and headless mode can all affect pixels. Keep those variables consistent between baseline creation and later runs, and investigate environment changes before treating every image difference as an application regression.

A screenshot shows appearance, not the full structure or accessibility of a page. For questions about headings, roles, labels, or interaction semantics, use DOM inspection or an accessibility snapshot rather than treating the image as a substitute.

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

Run captures at scale without making the script fragile

For a single diagnostic capture, a simple script is usually enough. For repeated captures, make each run explicit and observable:

  • Use a timeout appropriate to the site and fail clearly when navigation or a required element does not arrive.
  • Record the URL, response status, viewport, browser version, and capture time alongside the image if the output will be compared later.
  • Give files deterministic names when they are test artifacts, and separate screenshots from unrelated output.
  • Close contexts and browsers in cleanup code, including when navigation or capture throws an error.
  • Keep authentication state and cookies isolated to the context that needs them; do not reuse sensitive sessions indiscriminately.

Full-page captures can be substantially taller than viewport captures, and device-pixel scaling can increase pixel dimensions further. Large images take more storage and can make visual comparisons slower. Capture only the region and resolution the task requires.

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

Troubleshooting common capture failures

Symptom Likely cause What to try
Browser executable missing The Playwright package is installed but its browser was not installed. Run npx playwright install chromium in the project environment, then rerun the script.
Navigation times out The site is slow, blocked, or never reaches the selected lifecycle milestone. Check the URL and network access; choose a suitable waitUntil value and wait for the specific content required instead of waiting for unrelated activity to stop.
Screenshot contains an error page Navigation completed with an HTTP 4xx or 5xx response; completion alone is not success. Inspect response.status() and decide whether the workflow should save or reject that result.
Screenshot is blank or incomplete The capture happened before the relevant content appeared, or the page rendered differently in the chosen viewport. Wait for a meaningful locator, verify viewport settings, and inspect the page before capturing.
Click screenshot shows the old page The click triggered navigation or a state change that had not finished. Wait for the resulting URL with page.waitForURL, or wait for the new state’s locator to appear.
Element screenshot fails The locator does not resolve to a visible, capturable element. Confirm the selector, wait for the element, and check whether it is hidden or outside the expected state.
Images differ between runs Rendering conditions or volatile content changed. Pin the environment and browser version, stabilize dynamic regions, and use animation handling or masks only where appropriate.

Or skip the browser setup

If you need a screenshot from a URL without maintaining browser automation, ScreenshotNeo provides a GET-based screenshot API. Its options include viewport or full-page captures, element selection, device presets, PDF output, custom CSS and JavaScript, waits, headers and cookies, and caching. The parameter names used by other screenshot APIs also work, which can make migration easier. See the ScreenshotNeo API documentation.

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

ScreenshotNeo accepts cookie or consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, with the response identifying the page verdict and billing status in headers. An MCP server provides take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. The Free plan includes 1,000 screenshots per month without a card; paid plans start at $5 for 3,000, and every feature is available on every plan.

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

Create a free ScreenshotNeo account to try 1,000 screenshots a month with no card.

When Puppeteer may fit instead

Puppeteer also provides a page screenshot API, including byte or base64 output depending on options; its official Page.screenshot() reference describes the method. The documentation covered here does not establish a complete feature-by-feature comparison between Puppeteer and Playwright, so choose based on your existing language, browser automation workflow, and integration needs rather than assuming one is universally better.

Frequently Asked Questions

Does a successful screenshot prove that a page is accessible?

No. A screenshot records rendered appearance; use DOM or accessibility inspection to evaluate structure, labels, and interaction semantics.

Can I use a screenshot as data in another program instead of saving a file?

Yes. In Playwright, omit the screenshot path and use the returned image bytes in your own processing or storage code.

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.