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

Use your browser test framework’s screenshot API: Playwright Test’s toHaveScreenshot() for capture plus visual comparison, Cypress’s cy.screenshot() for images and failure artifacts, or Selenium WebDriver’s screenshot methods for saved image files. First make the page or component reach a known state; then capture the scope you need. A screenshot used to debug a failed test is not automatically a visual regression test: comparison against an approved baseline is a separate step in Cypress and Selenium workflows.

Choose the screenshot you need

Automated browser tests can save the browser-rendered UI without a physical screen-capture device. Pick the capture scope and purpose before adding a screenshot call; each answers a different question.

Goal Capture Useful for
Diagnose a failed test Failure screenshot or viewport Seeing what the user-facing page looked like when the assertion failed.
Inspect a component Element or clipped region Checking a focused UI area without unrelated page changes.
See the current screen Viewport Capturing what is visible without scrolling.
Inspect page layout Full page Reviewing long-page structure; stitching can have fixed/sticky-element quirks.
Detect unintended visual change Screenshot compared with a reviewed baseline Visual regression testing. Capture alone does not establish whether a difference is acceptable.

For comparison tests, prefer the smallest scope that covers the intended change. A component-level baseline usually limits unrelated noise; a full-page baseline is appropriate when page-wide layout is what you are validating.

Capture and compare screenshots with Playwright

Playwright Test includes screenshot assertions, so a single assertion can capture and compare a page with a reference image. The first run creates the reference; subsequent runs compare against it. The assertion waits for two consecutive screenshots to match before comparing. The documented API is for the Playwright Test runner.

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

Page screenshot with a visual assertion

import { test, expect } from '@playwright/test';

test('page visual state', async ({ page }) => {
  await page.goto('https://example.com');
  await expect(page).toHaveScreenshot('page.png');
});

Run the test with your usual Playwright Test command. On the first run, inspect the generated reference and commit it only if it represents the intended design. Later runs report visual differences against that image. PNG is the default; using a filename ending in .webp selects WebP.

Wait for the intended state

Navigation completing does not necessarily mean the UI is ready for a meaningful image. Assert for the state under test—for example, the expected heading or loaded component—before the screenshot assertion. Prefer a state assertion over an arbitrary sleep: fixed delays can be too short on a slow run and waste time on a fast one.

Playwright’s screenshot assertion disables animations by default and can hide the caret. Its options also allow clipping and diff tolerance. Use those controls narrowly: tolerance should absorb insignificant rendering noise, not mask a real layout or styling change. Consult the Playwright visual comparisons documentation for current options and baseline behavior.

Update references deliberately

When a design change is expected, regenerate references with npx playwright test --update-snapshots. Review the diff before committing; wholesale acceptance can turn a real regression into the new baseline. Playwright warns that rendering can vary with host operating system, browser version, settings, hardware, power source, and headless mode. Create and compare baselines in the same environment whenever possible.

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

Capture screenshots with Cypress

Cypress provides cy.screenshot() for manual captures. Under cypress run, Cypress also captures screenshots automatically when tests fail; this automatic failure capture does not happen in cypress open. The default screenshot directory is cypress/screenshots. Failure capture can be disabled with screenshotOnRunFailure: false.

Manual capture after an assertion

describe('product page', () => {
  it('shows the loaded product details', () => {
    cy.visit('/products/example');
    cy.contains('Example product').should('be.visible');
    cy.screenshot('product-ready');
  });
});

This captures evidence after the relevant state is verified. You can also capture on a failure via Cypress’s run-mode behavior rather than adding manual screenshots to every test. See Cypress screenshot command documentation for command details.

Choose viewport, full-page, or runner capture

Cypress screenshot configuration covers a viewport image, a full-page image, or a runner capture that includes the Cypress browser view. A viewport capture records what is currently visible. A full-page capture scrolls and stitches images; fixed or sticky elements can therefore appear more than once. A runner capture is useful when the test runner context itself matters. Check the current Cypress configuration documentation for the applicable setting names.

Use a plugin or service for visual diffs

cy.screenshot() saves an image; it does not itself compare that image to a baseline. Visual regression requires a separate plugin or service. A local workflow stores reference images with the project and handles comparison and rendering consistency in the team’s environment. A managed workflow may provide hosted rendering, baseline management, dashboards, or review steps; exact features and costs vary by provider. Cypress’s visual testing guidance discusses local approaches and integrations including Chromatic, Percy, and Sauce Labs Visual.

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.

Before capturing, control API data with fixtures or another repeatable source. If a page contains content that cannot be stabilized, mask only the narrow dynamic region. A broad mask can conceal the very regression the test should detect.

Capture screenshots with Selenium WebDriver

Selenium WebDriver can capture the current browsing context and save a PNG. Method names depend on the language binding; element screenshots are also available in documented bindings. Confirm whether your chosen driver and method capture the window, visible frame, or a particular element rather than assuming identical full-page behavior across bindings.

Python example

from selenium import webdriver

 driver = webdriver.Chrome()
try:
    driver.get("https://example.com")
    driver.save_screenshot("page.png")
finally:
    driver.quit()

Remove the single leading space before driver = if copying this block into Python; the executable form is:

from selenium import webdriver

driver = webdriver.Chrome()
try:
    driver.get("https://example.com")
    driver.save_screenshot("page.png")
finally:
    driver.quit()

JavaScript example

const { Builder } = require('selenium-webdriver');
const fs = require('node:fs');

(async () => {
  const driver = await new Builder().forBrowser('chrome').build();
  try {
    await driver.get('https://example.com');
    const image = await driver.takeScreenshot();
    fs.writeFileSync('page.png', image, 'base64');
  } finally {
    await driver.quit();
  }
})();

In these Selenium examples, first confirm the page or component is ready before saving the image. The Python binding uses save_screenshot; JavaScript exposes takeScreenshot(), which returns Base64 data that the example writes as a PNG. Selenium’s documented bindings differ, so check the official Selenium screenshot documentation for your language and element/window capture behavior.

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

Or skip the browser setup

If you need an image of a public page rather than an in-test browser state, ScreenshotNeo is a website screenshot API and MCP server. It cannot replace a test framework’s access to your test session, fixtures, or assertions, but it can capture a URL in one request. The API accepts parameters used by other screenshot APIs, which can make switching easier. The API documentation lists the request options.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
  • It accepts cookie/consent banners as a visitor and removes 60+ known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off.
  • Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed; response headers identify the page verdict and billing status.
  • Its MCP server offers 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. Every feature is on every plan.

Sign up for ScreenshotNeo’s free plan to get 1,000 screenshots a month with no card.

Make screenshot tests stable and useful

Control when the image is taken

Wait for an observable application condition: a result list loaded, a dialog visible, or a loading indicator gone. Then capture. A screenshot taken during a transition can fail intermittently even when the product is correct.

Make test data repeatable

Stub API responses or otherwise provide stable data. Randomized ordering, changing prices, timestamps, rotating promotions, and user-specific content can alter pixels for reasons unrelated to code changes. If a region must remain dynamic, mask or hide that region precisely rather than masking large sections of the page.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #4
Sale
Go Web Programming
  • This refurbished product is tested and certified to look and work like new. The refurbishing process includes functionality testing, basic cleaning, inspection, and repackaging. The product ships with all relevant accessories, and may arrive in a generic box

Keep rendering conditions aligned

For baseline comparisons, keep the browser version, operating system, fonts, viewport, device scale, and headless settings consistent. Small differences in font rendering or layout can create pixel diffs. Playwright explicitly notes that host OS, version, settings, hardware, power source, and headless mode can affect rendering; use a consistent environment for both reference generation and comparison.

Choose capture scope and storage intentionally

  • Use element or clipped captures for component-level changes.
  • Use a viewport image when the visible screen is the subject.
  • Use full-page capture for page layout, while checking for stitching artifacts around sticky and fixed elements.
  • Save failure screenshots as CI artifacts so a failed run can be diagnosed without rerunning locally.
  • Keep comparison baselines versioned and review their changes as code changes, not disposable outputs.

Choose a visual regression workflow

If the goal is only to understand why an assertion failed, framework-native screenshots may be sufficient. If the goal is to detect visual changes, decide who owns the baseline, where rendering occurs, how reviewers approve changes, and what data leaves your infrastructure.

Decision Local comparison Managed visual testing
Baseline ownership Images live with the project; the team updates and reviews them. Provider workflow may manage baselines and approvals.
Rendering coverage Typically the browser and environment configured by the team. May include hosted rendering across browsers or viewport widths; verify provider specifics.
Data location Comparison can stay within team infrastructure. Assess what pages, images, or artifacts are sent to or rendered by the provider.
Review CI artifact and diff review. May include dashboards and pull-request review features.
Operations and cost Team maintains rendering setup and baseline updates. Potentially less workflow maintenance, usually with service costs; verify current terms.

Cypress describes local plugins as free and commercial services as paid subscriptions, but that general distinction does not establish the current price or exact features of any individual provider. Confirm those details with the provider before adopting it.

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

Troubleshoot common screenshot-test failures

The screenshot changes on every run

Likely causes: dynamic text or data, an animation, a blinking caret, or inconsistent browser rendering. Fix: wait for the intended state, use stable fixtures, disable or control motion where supported, narrowly mask unavoidable dynamic content, and pin the comparison environment.

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

The image is blank or captured too early

Likely cause: navigation completed before the application rendered its target state. Fix: assert the expected content or component is visible before calling the screenshot API; do not rely on a guessed delay as the only readiness check.

Cypress has no failure screenshot

Likely causes: the test ran in cypress open rather than cypress run, or screenshotOnRunFailure is disabled. Fix: use run mode for automatic failure captures and check the configured screenshot directory, defaulting to cypress/screenshots.

Cypress full-page images repeat a sticky header

Cause: full-page capture scrolls and stitches sections. Fix: compare a viewport or targeted element if that answers the test question, or account for the stitching behavior when using a full-page image.

A screenshot exists, but no visual diff is reported

Cause: image capture and image comparison are separate capabilities. Fix: add a Cypress plugin or visual-testing integration, or choose a framework assertion such as Playwright Test’s toHaveScreenshot() that performs comparison.

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

Selenium returns data but no PNG file appears

Cause: some bindings return Base64 image data rather than writing a file. Fix: decode or write that data using the binding’s documented format; verify the driver method and output path.

A changed design causes a wall of failed snapshots

Cause: a legitimate UI change differs from approved references, or a shared rendering change altered many images. Fix: inspect representative diffs, determine whether the change is expected, then update only the appropriate baselines using the framework’s documented process. Avoid automatically accepting every changed image.

Frequently Asked Questions

Does Playwright’s screenshot assertion work with every Playwright setup?

The documented `toHaveScreenshot()` visual assertion is for the Playwright Test runner.

Can Cypress compare screenshots by itself?

No. `cy.screenshot()` captures an image; visual comparison requires a plugin or service.

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

Do Selenium screenshot methods always capture a full page?

No. Capture scope and full-page behavior depend on the binding and driver; check the documented method for the binding you use.

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.