Run Playwright visual tests in GitHub Actions by installing the project’s dependencies and matching browser binaries, running npx playwright test with a stable CI configuration, and uploading the HTML report even when a test fails. Commit reviewed screenshot baselines and keep the CI rendering environment consistent with the one used to create them.
Set up a basic GitHub Actions workflow
This workflow runs on pushes and pull requests, installs Node dependencies and Playwright’s browsers with Linux system dependencies, runs the tests, and uploads the HTML report unless the workflow is cancelled. The action version shown is an example; check the current Playwright documentation and your repository’s dependency versions before adopting or updating workflow actions.
name: Playwright tests
on:
push:
pull_request:
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- name: Install dependencies
run: npm ci
- name: Install Playwright browsers
run: npx playwright install --with-deps
- name: Run Playwright tests
run: npx playwright test
- name: Upload Playwright report
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v4
with:
name: playwright-report
path: playwright-report/
retention-days: 30
The 30-day retention setting is a documentation example, not a requirement. Set retention to match your repository’s policy and debugging needs. Playwright’s documented CI setup and artifact workflow are at Continuous Integration | Playwright.
Keep CI workers predictable
In playwright.config.ts, Playwright recommends one worker in CI to prioritize stability and reproducibility:
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →#1 Best Overall
import { defineConfig } from '@playwright/test';
export default defineConfig({
workers: process.env.CI ? 1 : undefined,
});
Start with one worker when diagnosing flaky visual comparisons. On capable self-hosted runners you can increase parallelism, but more workers do not fix inconsistent rendering. Larger suites can instead be divided into shards, with each shard producing a report that a later job merges.
Use a container when environment consistency matters
Playwright documents containerized CI as an option for controlling the operating environment across operating systems. If you choose that route, use a Playwright container tag that matches the Playwright version in the project, and verify the currently supported tag in the CI documentation. A container can reduce environment differences; it does not remove the need to keep browser versions and screenshot settings consistent.
Create and maintain screenshot baselines
Use Playwright Test’s toHaveScreenshot() assertion to compare a page against a stored reference:
import { test, expect } from '@playwright/test';
test('home page visual appearance', async ({ page }) => {
await page.goto('/');
await expect(page).toHaveScreenshot();
});
On its first run, Playwright creates the reference screenshot. Later runs compare the page with that baseline and fail when the difference exceeds the configured comparison rules. The generated snapshot directory is kept next to the test file; commit the baseline files and review changes to them like other code changes. Playwright’s guidance on baselines and comparison options is in Visual comparisons | Playwright.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsMake baseline updates deliberate
- Run the visual test in the same browser and environment used by CI.
- For an intentional UI change, run
npx playwright test --update-snapshots. - Inspect the changed image files and the corresponding code change before committing the new baselines.
Playwright-generated snapshot names account for test, browser or project, and platform context. Different browsers and platforms can render differently, so do not assume a baseline made on one platform is interchangeable with another.
Reduce rendering noise without hiding regressions
Rendering can vary with host operating system, browser version, settings, hardware, power source, and headless mode. Keep the baseline-generation environment aligned with CI, and make the page state deterministic where possible. For known volatile areas, Playwright supports a stylePath stylesheet; it also documents maxDiffPixels and a configurable threshold. Use narrowly scoped styles or tolerances: broad allowances may conceal changes that should fail a test.
Find reports and diagnose failures
After a run, open the GitHub Actions workflow run and download the playwright-report artifact. Because the upload step uses if: ${{ !cancelled() }}, the report is retained after a failed test unless the workflow was cancelled. The report helps identify failures; traces can add the action sequence and page state needed to understand them.
Playwright’s trace viewer can show action screenshots and image comparisons, including the expected image, actual image, and difference. Use it when a report shows that a screenshot assertion failed but does not make the triggering action or state clear. See Trace viewer | Playwright.
Recommended Free Tools
Protect uploaded diagnostics
Reports, traces, and screenshots can contain application data. Playwright advises uploading them only to trusted artifact stores or encrypting them before upload; restrict access and choose retention periods appropriate to the data. See Setting up CI | Playwright.
Rank #4
Scale out with sharded tests
A single job is easier to maintain. When the suite needs distribution, Playwright supports running shards and merging their blob reports into one HTML report. This adds artifact handling and a dependent merge job, so use it when the shorter distributed run is worth the extra workflow complexity.
The documented pattern is to upload a blob report from every test shard, then have a merge job depend on the shard jobs, download their artifacts, and run:
npx playwright merge-reports --reporter html
Upload the resulting HTML report as its own artifact. Playwright’s sharding guide shows the workflow pattern and artifact handling: Sharding | Playwright. Set retention separately for intermediate shard reports and the combined report according to your team’s needs.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Best Value
Or skip the browser setup
If you need a screenshot from a URL rather than a Playwright visual-regression test, ScreenshotNeo is a website screenshot API and MCP server. It is not a replacement for committed Playwright baselines or test assertions; it is an alternative for requesting captures without installing and maintaining a browser runner.
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 request options. Before capture, it accepts cookie or consent banners and removes 60+ known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing status. Its MCP server offers take_screenshot, get_page_info, and capture_pdf for AI agents and other MCP clients. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots.
Sign up for 1,000 free screenshots a month, no card required.
Quick Recap
Troubleshooting screenshot tests in CI
- Passes locally, fails in CI: compare the host OS, browser version, headless mode, settings, and page state. Generate or update baselines in the same environment as CI.
- Unexpected baseline changes: check whether the change is intentional, and inspect the image diff before using
--update-snapshots. Avoid accepting regenerated files without review. - Flaky or inconsistent visual results: begin with one CI worker, stabilize dynamic content and timing, and avoid relying on uncontrolled page state. Use targeted
stylePathrules or comparison thresholds only for understood sources of noise. - No report artifact after a failure: confirm the upload step follows the test step, its path is
playwright-report/, and its condition isif: ${{ !cancelled() }}. A cancelled workflow will skip this upload condition. - Sharded jobs produce no combined report: verify each shard uploads its blob report, the merge job depends on all shard jobs and downloads their artifacts, and the merge command runs with the HTML reporter.
- Diagnostics expose sensitive data: limit artifact access and retention, or encrypt report and trace files before uploading them.
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.




