Home / Guides / Updating Playwright snapshots
playwright --update-snapshots, without the wrong-OS trap
--update-snapshots rewrites the screenshots your toHaveScreenshot assertions compare against. Run it on the wrong machine and CI fails on images that look fine. Here is what each mode writes, and three workflows that keep CI green.
What the flag writes
This guide calls the stored screenshots goldens. Playwright's docs call them snapshots. The flag takes a mode. These are from Playwright's CLI reference and TestConfig reference, checked October 2026:
| You run | Mode | What it writes |
|---|---|---|
| npx playwright test | default | Missing goldens only, and the tests that wrote them fail. |
| --update-snapshots | changed | Goldens that no longer match, plus missing ones. A bare flag means this mode. -u is the short form. |
| --update-snapshots=all | all | The golden of every assertion that runs, whether it matched or not. |
| --update-snapshots=missing | missing | Missing goldens only. Tests that only wrote one pass. |
| --update-snapshots=none | none | Nothing. |
updateSnapshots in playwright.config.ts sets the same modes. The flag also updates toMatchSnapshot and toMatchAriaSnapshot expectations, not only screenshots.
Use the narrowest run that covers your change. Each of these rewrites less than the whole suite:
npx playwright test tests/checkout.spec.ts --update-snapshots npx playwright test --grep "checkout" --update-snapshots npx playwright test --project=chromium --update-snapshots
Prefer changed over all. A golden that still matches has nothing to update, and rewriting it only adds noise to the commit.
Look before you update
The flag accepts whatever the page renders now, including a bug. Run the tests without it first, and read the failures:
npx playwright test npx playwright show-report
The HTML report shows each failed screenshot as expected, actual and diff. Update only when every diff is a change you meant. After the update, GitHub's pull-request view can compare the old and new PNGs side by side, so reviewers can check them too.
Stale files are never removed
Rename a test, or delete one, and its goldens stay in the folder. No mode removes them. Playwright closed the request to add that, #16582, as not planned in August 2026. To clean up, delete the snapshot folders and write them again. Do it in the same environment as CI, as described below:
find tests -type d -name '*-snapshots' -prune -exec rm -rf {} +
npx playwright test --update-snapshots=missing
git status
Files that git status now lists as deleted were orphans.
The wrong-OS trap
Playwright puts the operating system in each golden's file name. A golden written on a Mac and one written by a Linux CI runner are different files:
tests/checkout.spec.ts-snapshots/payment-form-chromium-darwin.png ← your Mac writes this tests/checkout.spec.ts-snapshots/payment-form-chromium-linux.png ← CI reads this
So an update on a laptop fails in one of three ways:
- Wrong file. You commit a -darwin golden. CI looks for -linux, finds none, and fails. The pull request now carries an image nothing reads.
- Right file, wrong pixels. If you removed {platform} from snapshotPathTemplate so every machine shares one file, your Mac overwrites the Linux golden. CI then fails on font smoothing and anti-aliasing at the edges of every word.
- Right OS, wrong CPU. Docker on Apple silicon runs the arm64 build of a Linux image. GitHub's standard runners are x64. Issue #13873 reports rendering differences between the two. Playwright closed it as not planned on 2026-05-12.
Goldens are only valid in the environment that wrote them. Write them in the environment CI runs in.
A Playwright upgrade can change rendering too, because each release ships new browser builds. Update goldens in the same pull request that bumps @playwright/test.
Workflow 1: update in the CI image, on your machine
Run your CI job in Playwright's Docker image, pinned to the version in your package.json. Playwright's CI docs show the setup:
jobs:
test:
runs-on: ubuntu-latest
container:
image: mcr.microsoft.com/playwright:v1.64.0-noble
options: --user 1001
Then update with the same image, from a bash shell in your repository:
docker run --rm --ipc=host --platform linux/amd64 \ -v "$PWD":/work -v /work/node_modules -w /work \ mcr.microsoft.com/playwright:v1.64.0-noble \ bash -c "npm ci && npx playwright test --update-snapshots"
- The tag must match @playwright/test. With another version, Playwright cannot find its browsers in the image.
- --platform linux/amd64 matches GitHub's x64 runners. On Apple silicon it runs under emulation, so it is slow, but the pixels match.
- -v /work/node_modules gives the container its own node_modules. Packages with native binaries, such as esbuild, then install for Linux and leave your machine's copy alone.
Workflow 2: let CI write them
If nobody should run Docker by hand, let a workflow you start yourself update the goldens and commit them to your branch. It runs on the same runner and setup as your tests:
name: update-snapshots
on:
workflow_dispatch:
jobs:
update:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: lts/*
- run: npm ci
- run: npx playwright install --with-deps
- run: npx playwright test --update-snapshots
- name: Commit updated goldens
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add -- '*-snapshots/*'
git diff --cached --quiet || git commit -m "Update Playwright goldens"
git push origin HEAD
Start it on your pull request's branch, from the Actions tab or with the GitHub CLI:
gh workflow run update-snapshots.yml --ref my-branch
- Use the same environment as your test job. If your tests run in a container, add the same container: here.
- Change the git add path if you set snapshotPathTemplate to put goldens somewhere else.
- The new commit does not start your other workflows. GitHub does not run workflows for pushes made with the job's own token. Push any commit yourself afterwards, or push with a GitHub App token, to get fresh checks on the pull request.
- Run it on pull-request branches only. It pushes to whatever branch you start it on.
Workflow 3: no goldens to update
Both workflows above still keep PNGs in git and still need someone to run an update. The other option is to stop committing goldens. Capture with page.screenshot(), and let the previous build be the baseline. With Screenery the loop looks like this:
- A pull request's build pushes its screenshots to @pr-12. Each PNG is graded against the same screenshot on the branch it merges into, or @latest.
- A comment on the pull request counts what changed and shows the changed screenshots first. With alertAbove set, the biggest changes are listed at the top. See Pull-request comments.
- Merging accepts the change. The build on the default branch moves @latest, and the next pull request is compared with it. See How @latest moves.
Only CI takes screenshots, so no laptop's OS or CPU is ever involved. There is no update step and no PNG to commit. It costs you three things:
- A changed screenshot fails the job only if you set failAbove, a percentage of changed pixels, or keep a committed diff-baseline folder. Otherwise a person reads the comment and decides. See Graded changes.
- There is no approve button that updates a baseline. Merging is the approval.
- Pull requests from forks get no OIDC token, so they publish nothing until they merge. See Fork pull requests.
If you keep your goldens, Screenery can still publish them from the default branch. Then @latest shows exactly what your tests accept. See Playwright goldens and Argos folders. The full workflow is in Playwright screenshots in GitHub Actions.
Next
- Playwright visual testing: toHaveScreenshot options, masks, and why goldens break across machines.
- Playwright screenshots in GitHub Actions: a complete workflow, and artifacts compared with published URLs.
- The visual-diff gate: a committed baseline with graded changes.