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

Run visual regression tests in GitHub Actions by installing the same locked project dependencies and compatible Playwright browsers you use for local testing, running screenshot assertions on pull requests, and uploading reports even when tests fail. A reliable workflow also controls the rendering environment and treats baseline updates as reviewed code changes—not as a way to dismiss unexpected diffs.

How do I run visual regression tests in GitHub Actions?

For a JavaScript or TypeScript project using Playwright, add a workflow under .github/workflows/ that checks out the pull request, sets up Node, installs dependencies from the lockfile, installs Playwright’s browsers and Linux dependencies, runs the tests, and saves the report and failure evidence. Start with pull-request checks; add branch pushes or deployed-preview checks if they match how your team ships.

1. Add a pull-request workflow

Create .github/workflows/visual-tests.yml. This baseline example assumes the repository has a working npm test-independent Playwright test suite configured to start or connect to the application. It uses GitHub’s current ubuntu-latest runner label and common setup actions; review action versions and Playwright compatibility when adopting or updating it.

name: Visual tests

on:
  pull_request:
  push:
    branches: [main]

jobs:
  visual-tests:
    name: Playwright visual tests
    runs-on: ubuntu-latest
    timeout-minutes: 30
    steps:
      - name: Check out repository
        uses: actions/checkout@v4

      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 22
          cache: npm

      - name: Install locked dependencies
        run: npm ci

      - name: Install Playwright browsers and system dependencies
        run: npx playwright install --with-deps

      - name: Run Playwright tests
        run: npx playwright test

      - name: Upload Playwright report and test results
        if: ${{ !cancelled() }}
        uses: actions/upload-artifact@v4
        with:
          name: playwright-report-${{ github.run_id }}
          path: |
            playwright-report/
            test-results/
          if-no-files-found: ignore
          retention-days: 30

Choose a Node version supported by your project, and commit the corresponding lockfile. The cache: npm setting caches npm data; it does not replace npm ci or make dependency versions deterministic by itself. Configure Playwright’s reporter to produce playwright-report/ if you want the HTML report there. The official Playwright workflow example installs with npm ci, installs browsers with npx playwright install --with-deps, runs npx playwright test, then uploads its report as an artifact. Its example uses 30-day retention; choose a period that fits your repository’s evidence-retention needs. Playwright CI documentation

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

2. Make the app available to the browser

The workflow must test an application that is actually running. One common arrangement is to configure the Playwright project to launch the app with its webServer option; another is to start the server in a workflow step and wait for it before running tests. The exact command depends on your app’s build and start scripts, so use the same build mode and relevant environment configuration your tests expect. If the job tests a deployed preview instead, pass that deployment’s URL as the test base URL rather than starting a second app in CI.

3. Write screenshot assertions for meaningful states

Playwright’s screenshot assertions compare a rendered page or element with an expected image. A simple page-level test can look like this; adapt the route, test setup, and baseline review process to the installed Playwright version and project:

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

test('homepage visual appearance', async ({ page }) => {
  await page.goto('/');
  await expect(page).toHaveScreenshot('homepage.png');
});

Capture representative screens and states that matter to users: for example, a navigation menu in its open state, a pricing table, or a form’s validation state. A single screenshot does not prove every interaction or viewport is correct; choose assertions that protect the parts of the interface most likely to regress. Consult the Playwright visual comparisons guide for the exact syntax, options, and baseline-update behavior supported by your installed version.

How do I compare Playwright screenshots in CI reliably?

A screenshot diff is meaningful only when changes reflect the page rather than uncontrolled differences in the machine rendering it. Browser version, operating system, fonts, device scale, viewport, and loaded content can all affect pixels. Keep the project dependencies and browser assumptions consistent, and create or update baselines in the same supported browser environment used by CI.

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

Stabilize what the test renders

  • Use fixed viewports and device settings for each assertion.
  • Keep browser and Playwright versions aligned with the CI image and local baseline process.
  • Control dynamic content such as timestamps, rotating promotions, and user-specific data when they are not the subject of the test.
  • Prevent uncontrolled animation or transitions from producing arbitrary capture frames; choose a project-appropriate strategy rather than masking large parts of the interface.
  • Wait for the page state the assertion is meant to protect, rather than capturing immediately after navigation if the relevant content has not appeared.

These are implementation practices, not a universal masking recipe. Masking or hiding too much can conceal a real regression, so keep exclusions narrow and explain why each is needed.

Use a consistent runtime or container

Playwright recommends containers as one way to keep the environment consistent for screenshot and visual-regression tests. Its CI guide includes versioned container image examples, but image tags and GitHub runner images change. Select an image compatible with the Playwright version in the project instead of copying an old tag without checking compatibility. Playwright CI guide

Browser binary caching is not automatically a useful speedup. Playwright says caching browser binaries is not recommended because restoring them can take about as long as downloading them, while Linux system dependencies still need to be installed. If measurement shows a cache helps your own workflow, key it to the Playwright version and retain the required system-dependency installation.

How should I update screenshot baselines?

Update an expected screenshot only after deciding the visual difference is intended. A baseline is part of the test’s expected behavior; replacing it just because CI is red can turn a genuine UI regression into an accepted change.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  1. Open the failed workflow artifact and inspect the actual image, expected image, and diff produced by the test run.
  2. Check whether the difference is a deliberate design or content change, or instead a rendering-environment or test-stability issue.
  3. If the product change is intended, regenerate the affected baseline using the documented procedure for the project’s installed Playwright version and the same browser environment used in CI.
  4. Review the updated image files alongside the code change, then commit them with a clear explanation of the intended visual change.
  5. Run the workflow again and confirm the new baseline passes without unrelated image changes.

Baseline-update commands and options can evolve between Playwright releases. Use the visual-comparisons documentation for your installed version rather than relying on a command copied from another version.

How do I preserve useful failure evidence?

Upload artifacts even if a test step fails. In the workflow above, if: ${{ !cancelled() }} lets the upload step run after a failure but not after the overall job is cancelled. Keep the paths aligned with the report and output directories configured by your Playwright project; include screenshots, traces, or other test results if your configuration writes them there. GitHub artifacts are attached to the workflow run, so reviewers can inspect the evidence without regenerating a failing state locally.

Use a retention period appropriate to your review and compliance needs. Avoid uploading secrets or sensitive test data in reports. If the expected directory is absent, artifact upload can otherwise obscure the original failure; if-no-files-found: ignore in the example prevents a missing report from turning the upload step itself into another failure.

Which GitHub Actions trigger should run visual tests?

Pull requests

A pull_request trigger provides feedback before a proposed change is merged and is the natural place for a required visual-test check. Give the job a recognizable name so developers can find it among branch-protection checks.

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

Pushes to an integration branch

A push trigger on a branch such as main can check integrated changes as well. The example includes both a pull-request trigger and a push to main; omit or adjust either trigger to match the team’s merge and release process.

Successful deployments

If the browser test should exercise a deployed preview rather than a locally started build, Playwright documents a deployment_status workflow pattern that filters for successful deployments and exposes the deployment target URL as PLAYWRIGHT_TEST_BASE_URL. This lets a test job target the deployed site. Use the deployment event and URL handling appropriate to your environment; do not assume a preview exists for every pull request. Playwright CI guide

How can a large Playwright suite stay fast without losing coverage?

Playwright supports sharding tests across jobs and merging reports, which can help distribute a large suite. The extra jobs and report-merging configuration add workflow complexity, so adopt them when suite duration warrants it and keep the browser environment consistent across shards.

Playwright also documents --only-changed as an early-feedback option, but it is a dependency-graph heuristic and may miss tests. Playwright’s guidance is explicit: “This is a heuristic and might miss tests, so it’s important that you always run the full test suite after the preliminary test run.” Use changed-test selection only as an initial signal, then keep a full suite run as the merge-quality gate. Playwright CI documentation on running a subset of tests

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

Should I use native Playwright snapshots or a hosted visual-testing service?

Native Playwright comparisons keep screenshot assertions and expected images in the repository’s normal test workflow. Hosted services can add centralized review interfaces and service-managed comparison history, but bring accounts, credentials, configuration, and plan limits to manage. The sources establish product features, not a neutral benchmark or current prices, so verify current plans, supported versions, and limits before choosing.

Approach Where comparisons live Review and operations Best fit
Playwright native snapshots Assertions and baseline files live with the project tests and repository. Review diffs in the normal development workflow; the team maintains baselines and browser setup. Teams that want visual checks inside existing Playwright tests without a hosted service prerequisite.
Chromatic with Playwright Chromatic documents cloud-side snapshot comparison and automatic indexing against commits. Chromatic describes interactive review and service-side parallelization. Its GitHub Actions integration requires a project token stored as a repository secret. Teams that want a dedicated hosted review workflow and accept service configuration and credential management.
Percy with Playwright Percy’s official integration repository describes sending Playwright screenshot assertions to Percy for comparison. Use the vendor’s current product documentation to confirm workflow, compatibility, and plan details. Teams already evaluating BrowserStack’s visual-testing offering.

Chromatic’s GitHub Actions example checks out full Git history, installs dependencies, and runs chromaui/action; the project token belongs in GitHub Actions secrets, never in committed workflow code. Its documentation says linked Git-provider projects can receive pull-request status checks. These are vendor-described capabilities, not independently tested comparative results. Check the current Chromatic documentation for configuration, plans, supported versions, and handling of pull requests from forks. Chromatic Playwright documentation Chromatic GitHub Actions documentation Chromatic CI documentation

Percy’s official Playwright integration repository describes routing Playwright screenshot assertions through Percy and uploading snapshots for comparison. Verify its current compatibility and product details in the integration documentation. Percy Playwright integration

When deciding, compare where history is stored, whether reviewers need a separate interface, who owns tokens and accounts, how parallel work is configured, how easily a failure can be reproduced locally, and current usage limits and cost. No neutral price comparison or performance benchmark is established here.

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.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Common GitHub Actions visual-testing failures and fixes

CI reports a screenshot mismatch that does not reproduce locally

Check browser version, operating system or container, fonts, viewport, device scale, and dynamic page content. Recreate the baseline in the same environment as CI before changing expected images. A different renderer can create pixel changes unrelated to the code under review.

Playwright cannot launch a browser in Linux

Confirm the browser binaries and OS packages were installed for the Playwright version in the lockfile. The documented CI setup uses npx playwright install --with-deps; if you use a container, verify it is compatible with that Playwright release.

The test captures a blank or incomplete page

Ensure the app server is available and the test targets the correct local or deployment URL. Wait for the relevant page or element state before taking the screenshot, and inspect logs for failed navigation, missing environment variables, or a server that exited early.

The workflow passes but visual tests did not run

Check the workflow trigger, job conditions, Playwright test discovery configuration, and whether the test command selects the intended projects and files. A successful workflow is not evidence that screenshot assertions ran unless the test report confirms them.

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

Artifact upload says no files were found

Make the upload paths match the configured reporter and test-output directories. The example tolerates missing files so the upload step does not replace the original failure, but correct the paths if evidence should be retained.

A hosted visual service does not report a pull-request result

Check that its project token is configured as a repository secret, the repository and project are linked as required, and the workflow has access to the necessary pull-request context. Review fork-pull-request access separately; do not expose a secret to an untrusted contribution just to make the check run.

Or skip the browser setup

For an API-based capture rather than a Playwright assertion suite, ScreenshotNeo can return a screenshot with one GET request. It accepts cookie banners like a visitor and removes 60+ known consent platforms, newsletter popups, and chat widgets before capture; each cleanup step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, 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 per month without a card; paid plans start at $5 for 3,000. See the ScreenshotNeo API documentation.

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

ScreenshotNeo is a capture API, not a replacement for Playwright’s in-repository assertions and baseline-review workflow. ScreenshotNeo offers those separate capture features and may suit jobs that need clean screenshot output from a URL. Sign up for 1,000 free 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 run Playwright visual tests on pull requests from forks?

A workflow that needs a repository secret for a hosted service should not expose that secret to an untrusted fork contribution. Check the service’s supported fork workflow and repository permissions before enabling it.

Do GitHub Actions artifacts update screenshot baselines automatically?

No. Artifacts preserve run output for inspection; expected baselines should be updated intentionally in the repository after reviewing the visual change.

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.