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

You can use Playwright’s Python package with pytest to capture browser screenshots, but Python pytest does not provide Playwright Test’s built-in toHaveScreenshot() matcher. For visual regression checks, add a Python pytest plugin with a snapshot assertion or write a comparison fixture that saves and compares images. Keep browser rendering conditions consistent and review every baseline before accepting it.

What visual snapshots mean in pytest and Playwright

A visual snapshot is an image captured from a rendered page or element and compared with an approved baseline. It can catch changes to layout, colors, typography, spacing, missing images, and other visible details. It complements functional assertions; it does not prove that a page behaves correctly or that its content is accessible.

There are two separate pieces in a Python workflow:

  • Browser automation: Playwright drives Chromium, Firefox, or WebKit, navigates to a page, and captures a screenshot.
  • Image comparison: a pytest plugin or your own fixture decides whether that screenshot differs from the expected image and reports the result.

Playwright’s toHaveScreenshot() assertion is documented for Playwright Test, the JavaScript/TypeScript test runner. Its documentation says the assertion waits for two consecutive screenshots to match before comparing against the expectation; it also explicitly limits screenshot assertions to that runner. It is not a built-in Python pytest matcher. See the Playwright PageAssertions API.

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

Install Playwright’s pytest integration

The official Python package includes a pytest plugin that supplies browser and page fixtures. From a project virtual environment, install the package and the browser binaries you intend to run:

python -m pip install pytest-playwright
python -m playwright install chromium

Use firefox or webkit instead of chromium if that is your target browser. On Linux CI, Playwright also documents installing browser system dependencies with python -m playwright install --with-deps chromium. Check the current Pytest Plugin Reference for runner options and setup details.

Save a basic browser test as test_page.py:

from pathlib import Path


def test_homepage_has_title(page):
    page.goto("https://example.com")
    assert page.title()


def test_homepage_screenshot(page):
    page.goto("https://example.com")
    Path("artifacts").mkdir(exist_ok=True)
    page.screenshot(path="artifacts/homepage.png", full_page=True)

The page fixture is supplied by the Playwright pytest plugin. Run tests with python -m pytest. The screenshot test above only creates an image; it does not compare that image with a baseline. This distinction is important: capture is built into the browser automation workflow, while visual assertion behavior comes from a plugin or your own code.

Choose browser and execution options

The plugin provides pytest command-line options for browser selection, headed mode, device emulation, and screenshot, video, or trace artifacts on failures. For example, run Chromium in a visible browser window with:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
python -m pytest --browser chromium --headed

Use the options documented for your installed plugin version rather than assuming flags from a different Playwright runner. In particular, Playwright Test configuration examples and Python pytest options are not interchangeable.

Add visual comparison to Python pytest

A Python visual test needs to store or locate an expected image, capture the current result, compare the two, and expose a useful failure. A plugin can provide that assertion workflow. Alternatively, a project can own the comparison fixture, but then the team also owns image-diff selection, tolerance rules, baseline naming, update mechanics, and artifact handling.

Evaluate pytest visual snapshot plugins

Two PyPI projects describe pytest integrations for Playwright screenshots. Their package pages are maintainer-provided descriptions, not independent audits of quality or maintenance. Confirm the latest release, compatibility, and behavior before adopting either in a production test suite.

Package Declared compatibility and described workflow What to verify
pytest-playwright-visual-snapshot PyPI lists version 0.5.1, uploaded 2026-02-05, and a Python minimum of 3.11. Its description includes an assert_snapshot fixture, masking, and snapshot review behavior. Check the current release, Python support, snapshot storage and update process, mask semantics, and available mismatch artifacts.
pytest-playwright-visual The PyPI page describes version 2.1.2 and Python >=3.8. Its described workflow passes page.screenshot() to its fixture. Check the current release, accepted image format, naming and directory behavior, baseline updates, diff output, and CI integration.

The different declared Python support ranges can affect which package is usable in a given project, but they do not establish that one tool is more reliable. Before choosing, compare how each handles the following:

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.
  • Whether an assertion accepts a page, locator, or screenshot bytes.
  • How snapshots are named and whether browser or operating-system variants are separated.
  • Whether dynamic regions can be masked or excluded.
  • How baseline updates are triggered and reviewed.
  • Whether a mismatch provides expected, actual, and diff images.
  • Whether local and CI runs use the same rendering environment.
  • Which image-diff implementation and configuration surface the package depends on.

Pytest maintains a general plugin list, but a listing alone should not replace checking the package’s current documentation, release history, and fit with your project.

Use a plugin assertion in a test

Follow the selected package’s current README or documentation for installation, fixture configuration, and the exact assertion signature. For example, the pytest-playwright-visual-snapshot page describes an assert_snapshot fixture, while pytest-playwright-visual describes passing the result of page.screenshot() to its fixture. These are package-specific APIs, not APIs supplied by Playwright’s Python page fixture.

Keep a test focused on the behavior and rendered state you intend to protect. Navigate to a deterministic route, wait for the page’s relevant content, and call the chosen plugin’s assertion. Avoid copying a JavaScript expect(page).toHaveScreenshot() example into a Python test: that syntax belongs to Playwright Test.

When a custom comparison fixture makes sense

A custom fixture is reasonable when you need a narrowly controlled comparison policy and are prepared to maintain it. At minimum, define where approved images live, how names encode route and viewport, the image-diff library and thresholds, the exact baseline-update command, and where failure artifacts go. Make baseline changes visible in code review; silently overwriting expected images on ordinary test runs turns a regression test into a screenshot generator.

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

Make screenshots reproducible

Visual tests are sensitive to their rendering environment. Playwright warns that “Browser rendering can vary based on the host OS, version, settings, hardware, power source (battery vs. power adapter), headless mode, and other factors.” This is why a screenshot difference is evidence of a rendered difference, not automatically proof that the application code is at fault. See Playwright’s visual comparison guidance.

Control the inputs that affect pixels

  • Use a consistent environment: generate and compare baselines with the same operating-system image, browser version, browser settings, and headless or headed mode.
  • Fix viewport and scale: use the same viewport dimensions and device scale factor for baseline creation and comparison.
  • Wait for a meaningful ready state: wait for a stable selector or application signal, not an arbitrary short delay, when content loads asynchronously.
  • Stabilize dynamic content: use test data, fixed clocks, deterministic animation behavior, and masking or exclusion for genuinely variable regions if your tool supports it.
  • Control fonts and assets: ensure the same fonts and image resources are available in local and CI environments.

Record the browser and operating-system expectations alongside the test setup. If the environment changes, review resulting baseline differences as a deliberate migration rather than accepting a large batch of image updates without inspection.

Choose between pixels and accessibility structure

Use screenshot snapshots when the question is whether the rendered appearance changed. Use Playwright Python’s ARIA snapshots when you want to examine or assert the accessibility tree’s structure in YAML. ARIA snapshots do not compare screenshot pixels and are not a visual-regression substitute. See Snapshot testing | Playwright Python.

Review and update baselines safely

  1. Create a baseline intentionally. Run the test in the agreed environment and inspect the captured page before accepting the image as expected behavior.
  2. Keep the baseline reviewable. Store expected images in version control or a team artifact workflow where changes can be reviewed with the related code.
  3. Inspect failures before updating. Compare expected, actual, and diff images if the chosen tool produces them. Determine whether the change is intended, an application defect, or environmental noise.
  4. Update only for an approved UI change. Use the plugin’s documented update mechanism or your project’s explicit update command. Avoid automatic baseline replacement on a normal CI test run.
  5. Commit the change with context. Include the reason for the visual change and review image diffs alongside code changes so a baseline update does not conceal an unintended regression.

Update flags and review flows vary by plugin and release; consult the exact package documentation rather than relying on a command copied from another tool.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshoot common visual-test failures

  • “Fixture ‘page’ not found” or pytest does not recognize Playwright fixtures: install pytest-playwright in the same Python environment used to run pytest, then verify with python -m pip show pytest-playwright and run python -m pytest from that environment.
  • Browser executable is missing: install the browser for the selected project with python -m playwright install chromium; on Linux CI, install required system dependencies as documented by Playwright.
  • A test captures an image but never fails on visual changes: page.screenshot() only captures bytes or writes an image. Add a visual assertion plugin or implement a comparison fixture.
  • Python reports that toHaveScreenshot or expect(page) is unavailable: that matcher is for Playwright Test, not the Python pytest plugin. Use a Python integration or your own comparator.
  • Snapshots differ only in CI: compare operating system, browser build, viewport, device scale factor, font availability, headless mode, and dynamic content. Align environments before changing baselines.
  • Differences move between runs: wait on application readiness, make test data deterministic, and identify clocks, animation, ads, rotating content, or network-loaded widgets that change the captured pixels.
  • Masking hides too much or too little: review the masked region and selector carefully. Mask only content that is inherently variable; otherwise a mask can hide a real layout or rendering regression.
  • A plugin cannot find or update its expected image: confirm its configured baseline directory, snapshot naming rules, working directory, and documented update procedure. Plugin conventions differ.

Or skip the browser setup

If you need a screenshot of a URL rather than an in-suite browser test, ScreenshotNeo is a website screenshot API and MCP server. One GET request returns an image or PDF; the following cURL example saves a WebP screenshot:

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

For other clients, the equivalent Python and Node.js requests are:

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://example.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

See the ScreenshotNeo documentation for API options. Before a capture, it accepts cookie or consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets; those steps can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and responses include X-Page-Verdict and X-Billed headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf for AI agents and MCP clients. The free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots.

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

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

Frequently Asked Questions

Can I compare only one element instead of a full page?

Yes. Playwright can capture a locator with its screenshot API, and some Python visual plugins accept a locator or screenshot bytes. Check the chosen plugin’s documented assertion signature.

Are ARIA snapshots a form of visual regression testing?

No. They represent accessible structure in YAML; screenshot comparisons test rendered pixels.

Should every screenshot difference fail a test?

That depends on the comparator and project policy. The threshold and any masking should be explicit and reviewed, rather than treating every pixel change as a defect or ignoring large changes.

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.

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