Skip to content

Playwright Plugin

The @pxdiff/playwright package integrates pxdiff into Playwright tests. Take screenshots during tests and get instant diff results against baselines.

Terminal window
npm install --save-dev @pxdiff/playwright

Peer dependency: @playwright/test >= 1.40

Create a global setup file that initializes the pxdiff session:

global-setup.ts
import { pxdiffSetup } from "@pxdiff/playwright/setup";
export default function setup(): void {
pxdiffSetup();
}

This generates a PXDIFF_SESSION_ID to group all screenshots from the test run into a single capture and diff. It won’t overwrite an existing value.

Extend Playwright’s test with pxdiff:

fixtures.ts
import { test as base } from "@playwright/test";
import { createPxdiffFixture } from "@pxdiff/playwright";
export const test = base.extend(
createPxdiffFixture({
suite: "my-app",
})
);
export { expect } from "@playwright/test";

Reference the global setup in your Playwright config:

playwright.config.ts
import { defineConfig } from "@playwright/test";
export default defineConfig({
globalSetup: "./global-setup.ts",
// ...
});
Terminal window
export PXDIFF_API_KEY=pxd_your_key_here

Use the toMatchPxdiff matcher on Page or Locator instances:

import { test, expect } from "./fixtures";
test("homepage visual regression", async ({ page }) => {
await page.goto("/");
// Full-page screenshot
await expect(page).toMatchPxdiff("homepage");
// Component screenshot
const header = page.locator("header");
await expect(header).toMatchPxdiff("header");
// With options
await expect(page).toMatchPxdiff("homepage-mobile", {
viewport: { width: 375, height: 812 },
ignoreSelectors: [".dynamic-timestamp"],
});
});

Creates a Playwright fixture that initializes pxdiff context for each test.

OptionTypeDefaultDescription
suitestring"playwright"Suite name for grouping snapshots
blockingbooleantrueWhether changed snapshots fail the test
apiUrlstringPXDIFF_API_URL or "https://pxdiff.com"API URL
git.branchstring(auto-detected)Git branch override
git.commitstring(auto-detected)Git commit override
localboolean(auto-detected)Local mode (from PXDIFF_LOCAL or absence of CI)
autoApproveboolean(auto-detected)From PXDIFF_AUTO_APPROVE

Custom matcher for visual regression assertions.

await expect(page).toMatchPxdiff("snapshot-name", options);
await expect(locator).toMatchPxdiff("component-name", options);
OptionTypeDefaultDescription
blockingboolean(from fixture)Override blocking mode for this snapshot
thresholdnumberCustom diff threshold (0–1)
viewportobject{ width, height } — set viewport before screenshot
fullPagebooleanfalseCapture full page instead of viewport
maskLocator[]Locators to mask before screenshot
ignoreSelectorsstring[]CSS selectors to hide via visibility: hidden
maxDiffPixelRationumberMax acceptable diff ratio (0–1). Pass if below this
animationsstring"disabled" to freeze animations
timeoutnumberScreenshot timeout in ms
waitForNetworkIdlebooleantrueWait for network idle before taking the screenshot
pathstring[]Display hierarchy path for tree grouping in review UI

Elements matching ignoreSelectors are hidden with visibility: hidden before the screenshot is taken. The CSS is cleaned up immediately after.

In addition, elements with data-pxdiff="ignore" or data-chromatic="ignore" attributes are always hidden:

<span data-pxdiff="ignore">Dynamic content here</span>

The matcher determines pass/fail as follows:

  • Pass: unchanged, new, auto-approved, within maxDiffPixelRatio, non-blocking mode, or CI mode (soft-fail)
  • Fail: changed snapshots exceeding the threshold in blocking mode

In CI mode (when PXDIFF_SESSION_ID is set and not local), the matcher always passes but includes diff information in the test annotations. The pxdiff GitHub check run reports the overall result.

Each toMatchPxdiff call attaches a pxdiff annotation to the test with the diff result. This makes results visible in Playwright’s HTML report.


The recommended approach for CI is to wrap your Playwright tests with pxdiff run:

.github/workflows/visual.yml
- name: Visual Regression
run: pxdiff run -- npx playwright test
env:
PXDIFF_API_KEY: ${{ secrets.PXDIFF_API_KEY }}

This creates a GitHub check run, groups all screenshots into one session, and reports results back to the PR.

You can also run Playwright tests without pxdiff run. Screenshots are still uploaded and diffed individually:

- name: Visual Tests
run: npx playwright test
env:
PXDIFF_API_KEY: ${{ secrets.PXDIFF_API_KEY }}

VariableDescription
PXDIFF_API_KEY(required) API authentication key
PXDIFF_API_URLAPI base URL (default: https://pxdiff.com)
PXDIFF_SESSION_IDSession ID for grouping (set by pxdiffSetup() or pxdiff run)
PXDIFF_LOCALSet to true for local development mode
PXDIFF_AUTO_APPROVESet to true to auto-approve all changes
PXDIFF_BRANCHOverride git branch detection
PXDIFF_COMMITOverride git commit detection