Sitelet https://stateofpixel.com/

Catch UI regressions before they merge.

Every pull request gets a visual check. Your CI takes the screenshots, a person approves each change.

Start free with GitHubSee pricing

Free up to 10 GB. No card. Playwright, Storybook or any folder of PNGs.

#412Tighten pricing cards

pricing-cards8c41e0d#131vs #409 on main

Sign in/Error600

Changed1.51% / 3,393 px
600x375Waiting for review
4 of 5
Baseline #409
Baseline #409
New #412
New #412

Comments on Sign in/Error [600]

No comments yet.

stateofpixel/playwright 5 changes to reviewPending

Same review page as the app. Try the keys:j k movea approver reject1 2 3 4 viewsd diff overlay? all keys

Works with the tests you already have.

No token to copy on GitHub Actions. The first build on your default branch becomes the baseline.
  1. 1Install the GitHub AppPick the repositories. Each one becomes a project.
  2. 2Add the reporter or one CI stepPlaywright, Storybook or any folder of PNGs.
  3. 3Open a pull requestThe check links to the review page. Approve, and it turns green.

Using a coding agent? The quickstart has a prompt that sets it up for you.

playwright.config.ts
import { defineConfig } from "@playwright/test";

export default defineConfig({
  reporter: [["list"], ["stateofpixel/playwright"]],
});
tests/checkout.spec.ts
import { test } from "@playwright/test";
import { snapshot } from "stateofpixel/playwright";

test("empty cart", async ({ page }) => {
  await page.goto("/cart");
  await snapshot(page, "Checkout/Empty cart");
});

snapshot() waits for fonts, disables animations and hides the caret. The reporter uploads when the run ends, once per shard. Read the Playwright guide

Nothing to wait for.

The upload is one step in your CI, right after your tests. It hashes, sends what is new, compares and reports the check.

One pull request, one CI run

stateofpixel

One CLI step after your tests. Your runner does the work.

npx playwright testTakes the screenshots
npx stateofpixel upload
0 s0.5 s1 s1.5 s2 s

0.0 smedian upload on our own CI, from hashing to the check

  1. Hash every PNGSHA-256 of each screenshot, on your runner.
  2. Upload new imagesHashes we have seen get no upload.
  3. CompareThe CLI diffs each change against the baseline.
  4. Report the checkThe pull request gets a check with the review link.
stateofpixel 12 changes to reviewPending

Hosted rendering

Tools that take your build and render it in their own browsers.

Your CI stepSends the build
  1. Upload the build
  2. Wait in a queue
  3. Render in their browsers
  4. Compare
  5. Report the check

Access follows GitHub.

There are no invites and no seats. People can do what their role on the repository allows.
  • Remove someone from the repository and they lose access here too.
  • Private builds show only to people who can read the repository on GitHub.
Who can see and do what
Role on GitHubBuilds and baselinesApprove and rejectProject settingsPlan and billing
OwnerYesYesYesYes
AdminYesYesYesNo
WriteYesYesNoNo
ReadYesNoNoNo
  • OwnerBuilds and baselines, approve and reject, project settings, plan and billing
  • AdminBuilds and baselines, approve and reject, project settings
  • WriteBuilds and baselines, approve and reject
  • ReadBuilds and baselines

How it handles sharding, merges and outages.

Pick a case to see the CI step and what the check shows.

While CI runs

Sharded suites

Each shard uploads its part, and the check reports once, after the last one. Use --shard 2/4, or --shard auto with a finalize step.

.github/workflows/visual.yml
strategy:
  matrix:
    shard: [1, 2, 3, 4]
steps:
  - run: npx playwright test --shard ${{ matrix.shard }}/4
  - run: npx stateofpixel upload screenshots --shard ${{ matrix.shard }}/4
GitHub check
  • stateofpixel Waiting for screenshots (2 of 4 shards)Details
Sharding docs

Pay for storage, nothing else.

No plan charges for snapshots, seats or builds. 10 GB is free, which covers most teams. The Usage tab shows what each project stores.

Free

$0 /mo

No card needed. Enough for most teams.

  • 10 GB of stored screenshots
  • No charge for snapshots, builds or projects
  • Everyone with write access can review
  • Pull request images kept 60 days, adjustable from 7 to 365
Start free with GitHub

25 GB

$15 /mo

Billed monthly

  • 25 GB of stored screenshots
  • Everything in Free

100 GB

$100 /mo

Billed monthly

  • 100 GB of stored screenshots
  • Everything in Free

500 GB

$500 /mo

Billed monthly

  • 500 GB of stored screenshots
  • Everything in Free

Need more than 500 GB? Write to hello@stateofpixel.com.

Price it for your suite.

Move the sliders. Every tool here bills for this many screenshots a month, except stateofpixel.

Screenshots a month360,000

stateofpixelFree, 5.5 GB stored$0 /mo
ArgosPro $100 + 325,000 extra at $4 per 1,000$1,400 /mo
ChromaticPro $399 + 275,000 extra at $8 per 1,000$2,599 /mo
PercyDesktop 25k $549 + 335,000 extra at $36 per 1,000$12,609 /mo

$16,800 a year less than the cheapest of them.

Screenshots are stories x viewports x browsers x builds. For stateofpixel, 5% of screenshots change per build at 80 KB each, and pull request images are kept 60 days. The cheapest list plan for each tool, before tax, from Argos pricing, Chromatic pricing, Percy pricing on 27 September 2026. Argos charges $0.0015 for extra Storybook screenshots. TurboSnap can lower Chromatic's count. Percy prices are month to month; yearly billing is lower.

What leaves your CI.

stateofpixel never receives your source code. It stores the screenshots your CI uploads, and access to them follows your permissions on GitHub.
Your CIStays here
  • Source codeNever sent, and never run on our side.
  • Tests and browsersScreenshots render in your own CI, so they match what your tests see.
  • SecretsOn GitHub Actions the CLI signs in with OIDC, so there is no secret to store.
npx stateofpixel uploadSends
  • The screenshots your tests wrote, up to 4 MB each. An unchanged screenshot costs one hash, not an upload.

  • The file path becomes the snapshot name. Each upload is checked against its hash.

  • The CLI diffs changed snapshots on your machine before the upload, with odiff or pixelmatch.

  • Metadata your tests attach, up to 4 KB per snapshot. It is shown on the build page and never changes how snapshots match.

  • Commit, commit message, branch, base branch, pull request number and up to 100 ancestor commits, to find the baseline.

  • A link from the build back to the CI run.

stateofpixelDoes with it
  • Stores each image oncePer account, keyed by its SHA-256 hash.
  • Signs private image linksThey expire after one to two hours.
  • Follows GitHub accessPrivate builds show only to people who can read the repository.
  • Sets the checkThe commit status links to the review page.

Outages and billing

OutagesThe upload step prints a warning and exits 0, so your pipeline keeps going. Pass --strict if you want it to fail instead.
BillingPlans are fixed, with no overage. 14 days after the storage limit, new images are not stored and the check passes with a note.

Talk to VaibhavA 30 minute call, for anything this page does not answer.

Book a call

Other questions

Commit statuses write, to set the check. Pull requests read and write, where read finds the PR number, base branch and squash merges, and write is not used for now. Contents read, which GitHub requires for the compare API we use to find the baseline commit. Metadata read, which every app has. Email addresses read, so you can sign in with GitHub. The app also asks for Checks write and Actions read, which it does not use for now.

Anyone with write access to the repository on GitHub. There are no seats, so the whole team can review.

Anything that writes PNG files: Playwright, Cypress, BackstopJS or native app screenshots. The CLI captures Storybook stories on its own. The file path becomes the snapshot name.

Screenshots render in your own CI, so they match what your tests see. The CLI ignores anti-aliasing by default and has a color threshold. A snapshot that flips back and forth on main is marked as looking flaky, with a link to the fixes. For stable renders, run capture in the Playwright Docker image and disable animations.

No. stateofpixel is GitHub only. Other CI providers work with a project token, as long as the repository is on GitHub.

Yes. The CLI, the server and the web app are MIT licensed, with their source at github.com/VaibhavAcharya/stateofpixel.

10 GB of stored screenshots. Snapshots, builds, projects and reviewers are not charged. No card needed. Pull request images are kept 60 days by default.

Cancel at the next billing date and the plan stays until the end of the billing period. Then the account moves to the Free plan with 10 GB of storage.

Coming from another tool?

Switch in one pull request. Your first build on the default branch becomes the baseline. The moving guide has the details.

Start free.
Pay when you pass 10 GB.

  • No card to start
  • No charge for screenshots, builds or reviewers
  • One upload step in your workflow
Start free with GitHubRead the quickstart

Open source, MIT.

.github/workflows/visual.yml
on:
  push:
    branches: [main]
  pull_request:

permissions:
  contents: read
  id-token: write

jobs:
  visual:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
        with:
          fetch-depth: 0
      - run: npx playwright test
      - run: npx stateofpixel upload screenshots