Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Use Playwright’s screenshot assertions against deterministic Storybook stories, commit the reference images, and run the same browser setup in CI. The essential assertion is await expect(page).toHaveScreenshot() (or the locator equivalent): the first run creates a reference image, and later runs fail when the rendered story differs beyond your configured tolerance.
This guide shows a native Playwright implementation, the storybook-addon-playwright route, stability controls, CI setup, troubleshooting, and how the local approach compares with Chromatic. It also explains where ScreenshotNeo can remove browser-capture plumbing when you need a clean screenshot of a reachable page rather than repository-managed visual baselines.
What Storybook screenshot tests actually verify
A Storybook story is a reusable description of one component state: its props, decorators, theme, and supplied data. Treat that story as the test case. The screenshot assertion answers one narrow question: does this rendered state still look the same? It can expose shifted layout, changed colors, incorrect dimensions, missing fonts, contrast-related appearance changes, and other visual regressions.
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Clear out junk files and repair common Windows errors3Scan for outdated or missing drivers - takes under a minuteThat scope matters. A pixel comparison does not prove that a button submits a form, that keyboard focus works, that an API response is correct, or that all accessibility rules pass. Keep interaction tests, accessibility checks, markup assertions, and full end-to-end tests alongside visual tests rather than replacing them.
Choose a local implementation
Native Playwright Test
Playwright Test gives you direct control over browser projects, URLs, fixtures, snapshot paths, and assertions. It is the most flexible choice when your team already runs Playwright or needs custom setup such as authentication, request interception, or several viewport projects.
storybook-addon-playwright
The addon is designed to run visual checks for stories in multiple browsers, wait for Storybook to render, capture images, and keep them in a __screenshots__ folder beside the story. Its current compatibility page lists Storybook ^10, Playwright ~1.59, and Node.js >=24.15.0; verify those constraints against the package version you install because they can change.
The addon targets Component Story Format (CSF). It does not provide its addon UI in a static Storybook build, and framework compatibility has caveats, so check those conditions before adopting it. You can use its toMatchScreenshots, runImageDiff, and getScreenshots helpers from Vitest, Jest, or custom assertions.
Free tools Windows power users keep installed
One-click scans. No signup required.
Build a native Playwright test step by step
1. Install Playwright and a browser
From the repository containing Storybook:
npm install --save-dev @playwright/test
npx playwright install
In a Linux CI runner, install the operating-system dependencies as well:
npx playwright install --with-deps chromium
Keep the browser version, operating system, and fonts consistent between the machine that creates references and the machine that reviews them.
2. Configure the Storybook server and snapshots
Create playwright.config.ts. The configuration below starts Storybook for the test run, fixes the viewport and color scheme, and separates snapshots by browser project.
import { defineConfig } from '@playwright/test';
export default defineConfig({
testDir: './tests/visual',
snapshotPathTemplate: '{testDir}/__screenshots__/{projectName}/{arg}{ext}',
use: {
baseURL: 'http://127.0.0.1:6006',
viewport: { width: 1280, height: 800 },
colorScheme: 'light',
deviceScaleFactor: 1
},
webServer: {
command: 'npm run storybook -- --ci --port 6006',
url: 'http://127.0.0.1:6006',
reuseExistingServer: !process.env.CI
},
projects: [
{ name: 'chromium', use: { browserName: 'chromium' } }
]
});
The snapshotPathTemplate keeps references in a predictable, reviewable directory. Add Firefox or WebKit as separate projects only when you intend to maintain separate baselines; a browser change should not silently overwrite another browser’s images.
3. Write a story-level screenshot test
Storybook’s iframe URL identifies a story by its component and story IDs. For a story exported as Primary from Button.stories.tsx, the URL commonly looks like this:
import { test, expect } from '@playwright/test';
test('Button primary story', async ({ page }) => {
await page.goto('/iframe.html?id=button--primary&viewMode=story');
await page.locator('#storybook-root').waitFor();
await expect(page).toHaveScreenshot('button-primary.png', {
animations: 'disabled',
maxDiffPixels: 100
});
});
Use the story’s actual ID from your Storybook URLs or index. Waiting for #storybook-root confirms that the canvas exists; it does not guarantee that a story’s asynchronous data has finished loading, so add a more specific readiness check when necessary.
4. Create and review the baseline
Run the test once:
npx playwright test tests/visual/button.spec.ts
On that first execution, Playwright writes the reference image. Commit the resulting snapshot directory to version control. On subsequent runs, Playwright waits for two consecutive screenshots to be identical before comparing them, which helps avoid capturing during layout movement.
Now make a deliberate visual change, such as changing the button’s background color, and run the test again. Playwright reports the mismatch and writes comparison artifacts for inspection. Review whether the difference is intentional. If it is, update the reference explicitly:
npx playwright test --update-snapshots
Do not use that flag as an automatic repair step in CI. The code change and the approved baseline update should be reviewed together.
Cover responsive and themed variants without mixing baselines
A responsive component needs more than one viewport. Define each important viewport as a named project or as a separately named test so a desktop change cannot replace a mobile reference.
projects: [
{
name: 'chromium-desktop',
use: {
browserName: 'chromium',
viewport: { width: 1280, height: 800 },
colorScheme: 'light'
}
},
{
name: 'chromium-mobile',
use: {
browserName: 'chromium',
viewport: { width: 390, height: 844 },
colorScheme: 'light',
deviceScaleFactor: 2
}
}
]
Apply the same principle to dark mode, locale, timezone, and reduced-motion settings. A changed environment is a new visual condition, not an interchangeable baseline. Hosted Storybook services can also model viewport, theme, locale, and media-feature variants; confirm the provider’s current matrix before depending on it.
Make captures deterministic
Control the rendering environment
- Generate and compare images on the same operating-system family, browser build, font set, and device scale factor.
- Pin browser versions in CI and avoid committing a developer-machine baseline that CI cannot reproduce.
- Set viewport, color scheme, locale, timezone, and other media features deliberately.
Remove time and data noise
- Freeze clocks where timestamps appear.
- Replace random IDs and generated content with fixed values.
- Intercept network calls or provide stable fixtures instead of live, changing responses.
- Wait for a story-specific selector, not merely the initial document load, when data arrives asynchronously.
Handle motion and fonts
Playwright disables animations for screenshot assertions by default, but application-level transitions, video, canvas animation, and delayed font loading can still change pixels. Prefer a test stylesheet or a screenshot-only style injection that freezes motion. Wait for the fonts your component requires, and make sure the same font files are available in every environment.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Use the Storybook Playwright addon instead
Install the addon version that matches your Storybook and Playwright versions, then follow its framework-specific setup. It can start or connect to a Storybook development server, wait for the rendered story, and place images in __screenshots__ next to the story. Missing references are generated with:
npx storybook-addon-playwright generate stories/Button.stories.playwright.json
Existing references fail when they no longer match. The addon waits for #storybook-root by default; for a story that needs an additional readiness condition, use its beforeScreenshot hook to wait for an explicit selector. Because the addon is intended for CSF and its UI does not operate in a static Storybook build, treat those as setup checks rather than assumptions.
Run visual tests in CI
A pull-request job should install the exact dependencies, install the pinned browser, start Storybook through the Playwright web server configuration, and run the tests. A minimal GitHub Actions job is:
name: visual-tests
on: [pull_request]
jobs:
screenshot:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 24
cache: npm
- run: npm ci
- run: npx playwright install --with-deps chromium
- run: npx playwright test
Keep baseline updates in the same pull request as the UI change. Require a reviewer to inspect the diff, especially when many files change at once. A broad rewrite can indicate a missing font, an altered browser image, or a broken Storybook fixture rather than a legitimate redesign.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Local Playwright versus Chromatic
Chromatic is Storybook’s named hosted option. Its Storybook addon sends stories to Chromatic for snapshotting; changed stories are highlighted for review, and accepted changes become new baselines. Its Playwright integration extends Playwright’s test and expect utilities, uploads a page archive containing DOM, styles, and assets during an end-to-end test, and performs the pixel diff in its cloud environment.
| Decision point | Local Playwright or addon | Chromatic |
|---|---|---|
| Execution | Your workstation or CI browser, started and maintained by your team | Hosted browser execution and rendering |
| Baseline ownership | Image files committed with the repository | Cloud-indexed snapshots associated with commits |
| Browser coverage | Browsers you install, pin, and update | Provider’s available browser matrix; verify current coverage |
| Review and debugging | Git diffs, local artifacts, and your existing tooling | Hosted visual diffs, archives, and collaboration features |
| Determinism | You control OS, fonts, browser, data, and power-state variables | A standardized service environment reduces local variation |
| Cost and governance | Your CI minutes, storage, maintenance, and retention policy | Service usage, retention, account controls, and vendor terms |
Choose local testing when repository-owned images, offline debugging, or custom browser control matter most. Choose Chromatic when hosted review, cloud baselines, and provider-managed execution justify the service dependency. Browser matrices and billing are service details that can change, so verify them before committing to a plan.
Rank #4
Troubleshoot common failures
The test captures a blank or incomplete canvas
Confirm that the Storybook server is reachable at the configured URL and that the story ID is correct. Wait for a story-specific element after #storybook-root, and ensure mocked data is available before taking the screenshot.
Every pixel changes in CI
Compare browser versions, operating-system images, fonts, viewport, device scale factor, and color scheme. Regenerate references inside the same pinned CI image you will use for comparison; do not mix host and CI baselines.
Recommended Free Tools
The test is flaky around transitions
Disable CSS and JavaScript-driven motion for the test, replace animated media with a fixed frame, and wait for fonts and asynchronous content. Playwright’s animation handling cannot stabilize application data that changes between renders.
Only one browser’s images are overwritten
Give projects distinct names and include the project in the snapshot path. Keep desktop, mobile, dark, and light variants in separate namespaces.
The addon command cannot find a baseline file
Check that the path points to a CSF story and that the addon version supports your Storybook and Playwright versions. A static build or unsupported framework integration can prevent the addon UI or hooks from working as expected.
A large diff appears after a harmless dependency update
Inspect the first changed pixels for font substitution, browser rendering changes, or altered default styles. Review the dependency update and its references together; do not approve a blanket snapshot refresh without identifying the cause.
Performance, reliability, and cost decisions
Screenshot suites scale with the number of stories, browser projects, viewports, and retries. Start with one representative, deterministic story, then add states that protect real visual risk. Reuse a single Storybook server per test run, avoid unnecessary full-page captures, and parallelize only when the environment and snapshot paths are isolated.
Best Value
Reference images are code-review artifacts: they consume repository storage and require deliberate updates. Hosted services move storage and review out of Git but add service usage, retention, and governance considerations. Neither model removes the need to control fonts, data, and browser versions.
Or skip the browser setup
ScreenshotNeo is useful when you need a clean screenshot or PDF of a reachable Storybook deployment, documentation page, or other URL without maintaining a capture browser. It accepts the consent banner like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. It is a capture service, not a replacement for repository-managed Playwright baseline assertions.
See the ScreenshotNeo API documentation for all options. A one-call image request is:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
The same request in Python:
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
And in Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
The free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 screenshots, and every feature is available on every plan. Create a free ScreenshotNeo account to try it.
Frequently Asked Questions
Can visual tests use authenticated Storybook stories?
Yes. Configure Playwright’s context with a storage state, cookie, custom header, or request fixture before navigating to the story. Keep that state deterministic and avoid using a live account whose data changes between runs.
How can a team review a redesign without losing the old reference?
Open the redesign as a normal pull request, inspect the changed images, and update references only in that pull request after approval. The commit history then records both the implementation and the accepted visual state.
Is it safe to run screenshot projects in parallel?
It is safe when each project has isolated browser settings, stable fixtures, and a snapshot path containing the project name. Parallel workers should not mutate shared test data or write the same reference file.
Quick Recap
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.

