ScreenshotNeo

BlogComparisons

Selenium Screenshot Versus Playwright Screenshot for Website Testing

Both tools capture screenshots, but Playwright Test adds built-in visual assertions. Compare capture, baselines, stability, and when Selenium still fits.

By the ScreenshotNeo team4 October 202610 min read

Both Selenium and Playwright can capture page and element screenshots. For website screenshot regression testing, the main difference is the comparison workflow: Playwright Test documents built-in visual assertions with reference images, while Selenium’s screenshot documentation covers capture and leaves baseline comparison to a separately chosen tool or workflow.

Choose Playwright Test when you want screenshot assertions integrated into the test runner. Selenium remains a practical choice when your team already relies on WebDriver or Selenium Grid and is prepared to add image comparison separately. This is a workflow recommendation based on documented features, not a speed or image-quality benchmark.

1. What is different: capturing an image versus testing it

A screenshot is an artifact. A visual regression test adds a reference image, a comparison rule, and a way to review changes. Both frameworks can produce the artifact; Playwright Test also documents the reference-and-assert workflow.

Need Selenium Playwright
Capture a page WebDriver screenshot APIs; the JavaScript API returns a Base64-encoded PNG and describes capture as best effort. page.screenshot() saves an image or returns a buffer, with format and capture options.
Capture an element WebElement screenshot captures the visible region within the element’s bounding rectangle. A locator can capture its element.
Capture the full page Support depends on binding and browser implementation. Selenium’s JavaScript API describes a best-effort preference beginning with the entire page; this is not a universal guarantee. fullPage: true captures the full scrollable page.
Compare against a baseline The cited screenshot docs describe capture, not a built-in baseline assertion. Add a separate image-diff workflow if needed. Playwright Test provides expect(page).toHaveScreenshot(); the first run creates a reference and later runs compare against it.
Run across machines Selenium Grid is documented for running tests across machines and platforms. Snapshot names can include browser and platform project details; maintain references for the combinations you run.

Sources: Selenium screenshot examples, Selenium JavaScript WebDriver API, Playwright screenshots, Playwright visual comparisons, and Selenium overview.

2. Playwright: capture and assert a screenshot

The following JavaScript example uses Playwright Test. Save it as tests/home.visual.spec.js; install the test runner with npm init playwright@latest if the project does not already use it. Run with npx playwright test. The first run creates the approved reference image; inspect and commit that image through your normal review process. Later runs compare against it.

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

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

Use networkidle only when it represents a meaningful settled state for your site. Pages with analytics, polling, or persistent connections may never become idle; in those cases wait for the actual page condition, such as a heading or loaded component.

Page, full-page, and element captures

For a standalone page capture without an assertion, use page.screenshot(). A locator screenshot is useful when only a component matters. Full-page capture can make long pages useful as artifacts, although very tall pages may be slower and more memory intensive.

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: 'viewport.png' });
  await page.screenshot({ path: 'full-page.png', fullPage: true });
  await page.locator('main').screenshot({ path: 'main.png' });

  await browser.close();
})();

Install the library with npm install playwright and its browser binaries with npx playwright install. The assertion example needs @playwright/test; the standalone example uses the Playwright library.

Stabilize Playwright visual assertions

  • Wait for a meaningful ready condition: a visible element, completed data load, or explicit application signal.
  • Use the assertion’s options for masks, animation handling, style overrides, and diff tolerance when appropriate. A stylesheet can hide or adjust volatile elements.
  • Set pixel-difference tolerances narrowly. Broad tolerances can hide real regressions.
  • Review changed references before updating them. A changed baseline is a code review decision, not proof that the change is correct.

The assertion waits for two consecutive identical screenshots before comparing, which helps with some transient rendering, but does not make dynamic content or environment differences disappear. See the PageAssertions API for the current assertion options.

3. Selenium: capture a page or element

This runnable Python example uses Selenium 4 bindings, installed with python -m pip install selenium. It saves both a page screenshot and an element screenshot. Selenium Manager can manage supported browser drivers when the browser is installed.

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

options = webdriver.ChromeOptions()
options.add_argument('--headless=new')
driver = webdriver.Chrome(options=options)

try:
    driver.set_window_size(1440, 900)
    driver.get('https://example.com')
    WebDriverWait(driver, 15).until(
        EC.visibility_of_element_located((By.CSS_SELECTOR, 'main'))
    )
    driver.save_screenshot('page.png')
    driver.find_element(By.CSS_SELECTOR, 'main').screenshot('main.png')
finally:
    driver.quit()

These calls capture screenshots; they do not create or compare approved visual baselines. To make this a regression test, save a known-good image, compare new captures using a separately selected image-diff tool or service, and define how diffs are reviewed and accepted. Select comparison behavior and thresholds based on the project’s needs; the Selenium screenshot docs do not prescribe a particular comparator.

Selenium documents WebDriver as using browser-vendor automation APIs. Its JavaScript screenshot API describes a best-effort capture preference, starting with the entire page, then the current window, visible current frame, and display containing the browser. Other bindings and drivers can differ, so verify full-page behavior for the exact combination you run. See the API details and official examples.

4. Make screenshot tests deterministic

Visual comparisons are sensitive to rendering inputs. Playwright specifically warns that operating system, browser version, settings, hardware, power source, headless mode, and other factors can change rendering. Generate baselines and run tests in the same environment wherever possible. This applies to Selenium plus an external comparator as well.

  • Pin the environment: use a consistent operating system image, browser version, viewport, device scale factor, and headless configuration.
  • Wait for page state: wait for the element or application state under test instead of relying on a fixed sleep. A delay can help with a known animation or delayed widget, but it is not a readiness guarantee.
  • Control variable data: use stable test accounts and fixtures, fixed content where practical, and predictable timestamps. Exclude genuinely irrelevant dynamic regions with masks or a stylesheet, and document what is excluded.
  • Handle motion deliberately: disable or finish animations if motion itself is not the subject of the test. Keep animation behavior when it is part of what you need to verify.
  • Keep fonts and assets available: late font swaps or missing images can change layout and produce misleading diffs.
  • Separate browser/platform baselines: do not assume one image is a portable golden across different rendering environments.

Playwright’s documentation recommends keeping test and baseline environments consistent. Its visual comparison guide covers environmental variation and snapshot handling: Visual comparisons.

5. Choose by workflow and infrastructure

  1. Pick Playwright Test if visual regression assertions should live directly in the runner, and the team can manage references for its browser and platform matrix.
  2. Pick Selenium if the suite already depends on WebDriver bindings or Selenium Grid’s cross-machine execution, and the team is comfortable selecting and maintaining a separate image-comparison layer.
  3. Write down capture scope for each test: viewport, whole page, clipped region, or element. Confirm full-page support for the Selenium browser and binding in use.
  4. Define review policy: who inspects a diff, which threshold applies, and how a legitimate UI change updates the reference.
  5. Use both when it fits: framework choice can follow the existing test architecture. The comparison here does not establish that either framework is faster or produces inherently better screenshots.

Selenium Grid is intended for distributing test execution across machines and platforms; see the Selenium overview. Playwright snapshot names and browser projects require baseline management across the target matrix; see Playwright’s guide.

6. Or skip the browser setup

If you need a screenshot artifact from a URL without managing a browser session, ScreenshotNeo is a website screenshot API and MCP server. This comparison’s primary recommendation for integrated test assertions remains Playwright Test; ScreenshotNeo is an alternative for URL-to-image capture when you want an API or AI-agent workflow. It does not replace a visual baseline assertion in your test runner.

One GET request returns an image or PDF. This example saves the returned bytes; the endpoint’s response format can be selected for PNG, JPEG, WebP, or PDF as documented.

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

See the ScreenshotNeo API documentation for authentication and options. The API also has Python and Node.js examples:

import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
open("shot.webp", "wb").write(r.content)
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}`);
await require('node:fs/promises').writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));

ScreenshotNeo removes known cookie and consent banners, newsletter popups, and chat widgets before capture; each cleanup step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, with response headers indicating the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for AI agents. The free plan includes 1,000 screenshots each month with no card; paid plans start at $5 for 3,000 shots. Every feature is available on every plan. Get a free ScreenshotNeo account.

7. Troubleshooting screenshot tests

Symptom Likely cause What to do
Playwright assertion fails on first run No reference image exists yet. Inspect the generated reference in the expected environment, approve it through review, and commit it as the baseline.
Diffs vary between local and CI Different OS, browser, headless settings, fonts, hardware, or device scale factor. Run baseline generation and comparison in a consistent environment, and keep browser/platform references separate as needed.
Screenshot captures a spinner or incomplete content Navigation completion was mistaken for application readiness. Wait for the specific content or state required by the test. Avoid arbitrary sleeps as the only synchronization.
Playwright never reaches network idle Polling, analytics, or another persistent request keeps the network active. Wait for the relevant element or application signal instead of network idle.
Only part of a long page is captured in Selenium Full-page behavior is binding- and driver-dependent. Check the exact API and implementation support. If necessary, use a supported full-page method or capture the required regions explicitly.
Element screenshot is clipped or missing The element is outside the viewport, covered, not rendered, or the selector resolves unexpectedly. Wait for visibility, confirm the locator/selector, and bring the element into a stable visible state before capture.
Font or image causes a one-off mismatch Asset loading completed after the capture, or an asset differs in CI. Wait for the relevant asset or component state and ensure fonts and test assets are available in the runner.
Small antialiasing differences create noisy failures Rendering varies across platform or hardware, or threshold is too strict for the chosen environment. First align the environment. If a tolerance is still needed, set it narrowly and check that meaningful changes remain detectable.
Baseline update hides a real regression References were accepted without inspecting the visual change. Review the diff and intended UI change before updating the approved reference.

8. Performance, reliability, and cost considerations

The reviewed documentation does not provide a comparative speed benchmark, so framework choice should not be based on an assumed winner. Capture cost and runtime depend on page complexity, full-page size, waits, browser startup, and whether sessions are reused. Full-page captures and broad cross-browser matrices create more images to store and review.

  • Keep checks focused: prefer component captures when the behavior is local; reserve full-page shots for layout that spans the page.
  • Reuse browser infrastructure sensibly: avoid unnecessary launches, but isolate tests enough to prevent state leakage.
  • Budget review effort: every baseline adds maintenance and needs an owner. A noisy suite can consume time without improving confidence.
  • Plan for retries carefully: retries can expose intermittent failures, but accepting the last passing screenshot without diagnosis can mask instability.
  • For hosted URL capture: ScreenshotNeo prices are Free 1,000/month, Starter $5 for 3,000, Growth $15 for 15,000, Pro $39 for 60,000, Scale $99 for 250,000, and Business $249 for 1,000,000; yearly billing gives two months free. Only clean shots are billed, and response headers report the verdict and billing state.

9. Frequently asked questions

Does Playwright replace Selenium for every screenshot test?

No. The useful distinction here is the documented built-in assertion workflow. Existing WebDriver and Grid investments can make Selenium the better fit for a particular team.

Can Selenium do visual regression testing?

Yes, by pairing its captures with an image comparison workflow. The Selenium documentation cited here does not describe a built-in baseline assertion.

Does Playwright’s screenshot assertion guarantee identical pixels?

No. It compares rendered captures, while environment and dynamic-content differences can still affect the result. Keep environments consistent and control volatile content.

Should I baseline a full page or a component?

Use the smallest capture scope that covers the behavior you want to protect. A component image is easier to diagnose; full-page images cover interactions among distant sections.

Sources