Playwright Screenshot Testing with Selenium: Key Differences
Playwright Test can capture and compare screenshot baselines in its test runner. Selenium captures screenshots; visual regression requires a comparison workflow around it.
Playwright Test has a built-in screenshot assertion that creates reference images and compares later captures against them. Selenium WebDriver can capture page and element screenshots, but the cited Selenium screenshot APIs describe capture rather than a built-in baseline comparison assertion. For Selenium visual regression, add comparison logic or a separate visual-testing tool.
That difference is about workflow integration, not whether Selenium can be extended. Both can produce screenshots. Playwright makes the baseline-and-assertion loop part of its test runner; with Selenium, you choose and maintain the comparison layer.
1. The key differences
| Area | Playwright Test | Selenium WebDriver |
|---|---|---|
| Capture | Page screenshots and screenshot assertions are available. | Driver and, in supported bindings, element screenshots are available. |
| Baseline workflow | The first run creates a reference image; later runs compare against it. | The cited screenshot APIs document capture. Add a baseline and comparison component for visual regression. |
| Stabilization | Screenshot assertions retry until consecutive captures match. Screenshot options can disable animations and control caret rendering; stylesheets can hide or alter volatile areas. | The cited capture APIs do not establish an equivalent built-in stabilization or masking workflow. Use your comparison layer and test setup. |
| Diff controls | Supports controls such as maxDiffPixels and a color-difference threshold. |
Diff thresholds and image handling depend on the comparison component you add. |
| Environment | Baselines are environment-sensitive; keep browser, operating system, and rendering conditions consistent. | Output depends on browser support and the active browsing context. Screenshot behavior can vary between implementations. |
Playwright’s screenshot assertion is available through the Playwright Test runner. It is not a universal guarantee that screenshots are stable or that every meaningful visual defect will be detected. Your team still owns environment consistency, thresholds, volatile regions, and review of baseline changes.
2. Choose based on the workflow you need
- Choose Playwright Test when integrated screenshot assertions and baseline management fit your test runner and browser strategy.
- Choose Selenium when WebDriver fits your existing language, browser, or test infrastructure, and you are prepared to select and maintain a comparison workflow.
- For either framework, decide how to control dynamic content, where baselines are generated, who reviews changes, and whether baselines need to be separate by browser or platform.
Do not assume one baseline will compare cleanly across operating systems or browser versions. Fonts, rasterization, headless mode, hardware, and other rendering details can change pixels. Playwright specifically warns that host OS, browser version, settings, hardware, power source, and headless mode can affect rendering. Keep baseline creation and comparison on a consistent environment, or maintain environment-specific references.
3. Playwright: runnable screenshot assertion
Install Playwright Test and its browser binaries in a Node.js project:
npm init -y
npm install --save-dev @playwright/test
npx playwright install
Create tests/landing.spec.js:
const { test, expect } = require('@playwright/test');
test('landing page matches its visual baseline', async ({ page }) => {
await page.goto('https://example.com');
await expect(page).toHaveScreenshot('landing.png');
});
Run it with:
npx playwright test
On the first run, Playwright writes the reference screenshot. Review and commit that image with the test. Later runs capture the page and compare it with the reference. When a UI change is intentional, regenerate snapshots explicitly and review the resulting image diff before accepting it:
npx playwright test --update-snapshots
Example with a pixel-difference allowance:
await expect(page).toHaveScreenshot('landing.png', {
maxDiffPixels: 100,
});
Use a tolerance only after examining the diffs. A loose threshold can hide a real regression. For dynamic regions, prefer controlling the page data or masking/hiding the specific volatile area with a screenshot stylesheet. For example, a stylesheet can hide a timestamp or rotating advertisement:
await expect(page).toHaveScreenshot('landing.png', {
stylePath: './visual-test.css',
});
/* visual-test.css */
.live-timestamp,
.rotating-ad {
visibility: hidden !important;
}
Use the screenshot assertion’s animation and caret controls when these cause unwanted pixel differences. The assertion disables animations by default; consult the API options for the precise behavior and settings for your installed Playwright version.
4. Selenium: capture plus a comparison layer
Selenium’s screenshot API captures the current browser view. The following Python example is runnable after installing Selenium and a browser driver supported by your environment:
python -m pip install selenium
from selenium import webdriver
options = webdriver.ChromeOptions()
options.add_argument('--headless')
driver = webdriver.Chrome(options=options)
try:
driver.get('https://example.com')
if not driver.save_screenshot('landing.png'):
raise RuntimeError('The browser did not save the screenshot')
finally:
driver.quit()
This saves a new image; it does not by itself establish a golden-image lifecycle or assert that the image matches a stored reference. Add a comparison step or use a visual-testing component compatible with your Selenium setup. Keep that component responsible for storing baselines, computing diffs, setting thresholds, and reporting failures.
Selenium’s JavaScript binding also exposes screenshot capture. In a project configured with Selenium and a compatible browser driver:
const { Builder } = require('selenium-webdriver');
const chrome = require('selenium-webdriver/chrome');
const fs = require('node:fs/promises');
(async () => {
const options = new chrome.Options().addArguments('--headless');
const driver = await new Builder()
.forBrowser('chrome')
.setChromeOptions(options)
.build();
try {
await driver.get('https://example.com');
const image = await driver.takeScreenshot();
await fs.writeFile('landing.png', Buffer.from(image, 'base64'));
} finally {
await driver.quit();
}
})();
For element screenshots, check that the binding and browser you use support the operation. Screenshot support and conformance can vary; the Selenium API describes best-effort behavior for some non-conformant implementations.
5. Keep screenshots stable and useful
- Control test data. Use fixed accounts, seeded records, and deterministic content where possible.
- Wait for the page state you mean to test. Wait for a meaningful selector or application-ready condition instead of an arbitrary short delay.
- Handle motion and blinking UI. Disable animations or use the framework’s screenshot controls. Hide only known volatile elements.
- Fix the capture environment. Pin browser versions and run baseline generation and comparison with the same OS, fonts, viewport, device scale, and headless configuration.
- Review baseline updates. Treat regenerated references as code changes: inspect the diff, understand the cause, and commit intentional changes.
- Set thresholds narrowly. Start strict, inspect recurring noise, then allow only the variation your application can tolerate.
Playwright waits for two consecutive page screenshots to match before evaluating the screenshot assertion. This helps with settling pages, but it cannot make genuinely changing content deterministic. Control the source of variation when possible.
6. Performance, reliability, and maintenance
- Runtime: Screenshot capture and image comparison add work to a test run. Capture only states that protect important UI behavior, and avoid redundant full-page snapshots.
- Reliability: Environment drift and dynamic content are common sources of noisy diffs. Pin dependencies and browser versions, stabilize data, and keep execution conditions consistent.
- Review cost: Baselines need ownership. Unreviewed snapshot updates can turn the assertion into a record of whatever happened to render, rather than a useful regression check.
- Selenium integration cost: A separate comparison layer gives you flexibility, but your team must operate its baseline storage, diff reporting, thresholds, and maintenance.
- Threshold cost: Higher tolerance may reduce false alarms but can also let small defects pass. Check representative diffs before choosing limits.
The research sources provide no benchmark comparing execution speed or image quality between the frameworks. Choose from your test architecture and measure your own suite if runtime is a deciding factor.
7. Troubleshooting
| Symptom | Likely cause | What to do |
|---|---|---|
| First Playwright run creates a new screenshot | No reference exists yet. | Review the generated image and commit it as the intended baseline. |
| Playwright fails with a large diff after a browser or OS update | Rendering environment changed. | Restore the pinned environment or deliberately review and update the environment-specific baseline. |
| Intermittent pixel diffs | Animations, blinking carets, asynchronous content, timestamps, or other volatile UI. | Wait for an explicit ready state, control test data, use screenshot options, or hide only the changing region with a stylesheet. |
| Snapshot update unexpectedly accepts a visual change | Baseline regeneration was treated as routine. | Inspect generated images and diffs before committing snapshot updates. |
| Selenium saves an image but the test does not detect visual changes | Capture was implemented without a comparison assertion. | Add a baseline comparison component and make its diff result fail the test when it exceeds the chosen tolerance. |
| Screenshot is missing or unsupported for an element | Binding or browser support differs. | Check the API support for your language binding and browser; capture the page as a fallback if appropriate. |
| Headless and headed images differ | Headless mode can affect rendering. | Generate and compare baselines in the same mode used in CI. |
8. Or skip the browser setup
For a one-off page capture or an image outside a test-runner workflow, ScreenshotNeo is a screenshot API and MCP server. One GET request returns PNG, JPEG, WebP, or PDF output. It is #1 to try for screenshot APIs because it removes consent clutter before capture, bills only clean shots, and its paid plans start at $5.
See the ScreenshotNeo API documentation for options and response details. Example using cURL:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
Python:
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://example.com"},
timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
const image = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', image));
- Cookie banners, popups, and chat widgets are removed before the shot; each cleanup step can be turned off.
- Bot checks, blank pages, timeouts, failed loads, and cache hits are never billed. The response includes page-verdict and billing headers.
- An MCP server gives AI agents tools to take screenshots, inspect page information, and capture PDFs.
- 1,000 screenshots a month are free with no card. Paid plans start at $5 for 3,000; every feature is on every plan.
Sign up for 1,000 free screenshots a month, with no card required.
9. FAQ
Does Selenium do visual regression testing automatically?
The cited Selenium screenshot APIs document image capture, not an integrated baseline-comparison assertion. Add a comparison layer to build that workflow.
Does Playwright compare screenshots outside Playwright Test?
The documented screenshot assertion belongs to the Playwright Test runner. A plain screenshot capture is separate from that assertion workflow.
Can I share one screenshot baseline across browsers and operating systems?
Do not assume so. Rendering varies by browser and platform; use consistent environments or separate references when the output differs.
Should I increase the diff threshold to stop flaky tests?
First identify and control the source of variation. Raise a threshold only after reviewing diffs and deciding which pixel changes are acceptable.
