How to Run Visual Tests in Playwright With Applitools
Add Applitools Eyes visual checkpoints to a Playwright suite, configure baselines, review differences, and troubleshoot common setup issues.
To run visual tests in Playwright with Applitools, install the Eyes Playwright SDK, set APPLITOOLS_API_KEY outside source control, import Applitools’ Playwright test fixture, and call eyes.check() after navigating the page to a stable state. Eyes compares each captured checkpoint with a saved baseline; review every difference and accept it only when the UI change is intentional.
This guide uses the JavaScript/TypeScript Fixtures SDK. Applitools also lists Standard, Java, C#, and Python SDK variants; their setup and imports differ, so use the instructions for your chosen SDK. See Applitools’ SDK choices and Playwright integration guide.
1. Install and initialize the Playwright SDK
In a project that already uses Playwright, install the SDK and run its setup command:
npm install --save-dev @applitools/eyes-playwright
npx eyes-playwright setup
The setup command can add configuration and an example visual test. SDK commands and interfaces can change, so check the live integration guide and the version installed in your project if the setup output differs.
2. Configure the API key safely
Get the execution key from your Applitools account and provide it as an environment variable. Do not hardcode a real key in a test file, committed configuration, or logs.
# macOS or Linux shell
export APPLITOOLS_API_KEY="your-api-key"
# PowerShell
$env:APPLITOOLS_API_KEY = "your-api-key"
In CI, save the key in the provider’s protected secret store and expose it to the visual test job. Applitools recommends an environment variable over placing the key in project configuration. The key authorizes test runs; treat it as a credential. See Applitools’ API key instructions.
3. Add a visual checkpoint
Import test from the Applitools fixture package. The fixture provides eyes and manages the Eyes lifecycle and result collection for the test.
import { test, expect } from '@applitools/eyes-playwright/fixture';
test('homepage visual check', async ({ page, eyes }) => {
await page.goto('https://example.com');
// Keep functional checks for behavior; the visual checkpoint checks appearance.
await expect(page).toHaveTitle(/Example Domain/);
await eyes.check('Homepage', {
fully: true,
matchLevel: 'Strict',
});
});
Run it with your project’s usual Playwright command, for example npx playwright test. A visual checkpoint complements functional assertions; it does not prove that links, forms, authorization, or application logic behave correctly.
Applitools recommends meaningful names for eyes.check() calls so results are identifiable in the dashboard. Use names that describe the page and state, such as Checkout — payment form, rather than repeating a generic label.
4. Choose checkpoint scope and matching behavior
| Choice | Use it for | Example |
|---|---|---|
| Full page | Page composition, including content below the initial viewport | fully: true |
| Element region | A component whose appearance should be reviewed independently | region: await page.locator('nav').boundingBox() or the locator form supported by your SDK version |
| Match level | How visual differences are interpreted | matchLevel: 'Strict' in the documented full-page example |
The integration guide documents full-page and region checks, match levels, ignored and floating regions, and displacement handling. It uses Strict in its full-page example and Layout for a component example. Pick the behavior that catches the changes your team cares about, then confirm the exact option shape in the documentation for your installed SDK version.
For a component, the documented pattern is to pass a locator as the region:
await eyes.check('Primary navigation', {
region: page.locator('nav'),
matchLevel: 'Layout',
});
Use ignored regions only for genuinely variable content whose appearance is out of scope, such as a timestamp. Keep the exclusion tight: ignoring a large container can hide a real regression. Floating regions and displacement handling are additional controls for specific cases; do not add them without a known source of nondeterminism.
5. Make the page state reproducible
Drive the application into a meaningful state before capturing it. Wait for the relevant content, complete required interactions, and use normal Playwright assertions to confirm the intended state. If a page includes personalized or time-varying data, arrange stable test data where possible; if the variable area must remain, exclude only that area.
- Use a descriptive checkpoint name for each distinct page state.
- Choose full-page capture for page-level composition and a region for an isolated component.
- Capture after actions and assertions that establish the state under test.
- Avoid broad ignored regions that could conceal meaningful changes.
6. Review and disposition visual differences
Eyes compares the new checkpoint with its saved baseline and reports differences. Review each difference in the Eyes report or dashboard. Accept a difference when it reflects an intended UI change; acceptance updates the baseline used by later runs. Reject an unintended difference so it remains a failure to investigate. Baseline changes require authentication.
The integration offers a custom reporter that can add Eyes results to Playwright’s HTML report. Review results using the reporting path configured by your team; accepting or rejecting baseline changes still requires authentication. Do not accept a batch of changes without examining what changed.
Configuration choices for a team
When differences fail tests
The integration guide documents eyesConfig.failTestsOnDiff values of afterEach, afterAll, or false. This is a project policy decision: fail after each test, surface differences after the suite, or allow review without immediate failure. Verify the current option behavior and configuration location against the live SDK documentation before adopting it.
Page objects
For a larger suite, pass the Eyes instance into a page object and put a checkpoint in a page-level method. This can keep repeated page actions and checks together. For a small suite, calling eyes.check() in the test is often easier to follow.
Reporting and hosting
The documented architecture has the Playwright test and Eyes SDK capture checkpoints, send them to the Eyes Server, compare them with stored baselines, and return results for review. Applitools documents public cloud, dedicated cloud, and on-premises server configurations. Select the deployment that fits your requirements and verify its configuration and data handling directly; the deployment choice determines which hosting arrangement applies.
Troubleshooting
| Symptom | Likely cause | What to do |
|---|---|---|
| API key or authentication error | APPLITOOLS_API_KEY is unset, misspelled, unavailable to the process, or invalid |
Check the environment in the same shell or CI job running Playwright. Confirm the secret is exposed to that job and rotate a key if it was committed or disclosed. |
eyes is undefined or the fixture import fails |
The test imports Playwright’s default fixture, uses a mismatched SDK variant, or the package installation is incomplete | Import test from @applitools/eyes-playwright/fixture, confirm the package is installed, and consult docs for the installed version. |
| Setup command or option is not recognized | The guide, generated sample, or installed package version differs | Check the current integration guide and package version; adapt the command or option to that documented interface. |
| Visual differences appear on every run | The page state or data is unstable, or a dynamic region changes between captures | Stabilize test data and capture timing. If a specific area is intentionally variable, use a narrowly scoped ignored region. |
| Checkpoint misses content below the fold | The capture is limited to the viewport | Use full-page capture with fully: true for the documented full-page workflow. |
| Unexpected difference is accepted as a baseline | A reviewer approved a change without confirming intent | Review the current report and restore or re-establish the correct baseline according to your team’s authenticated baseline workflow. |
| Results do not appear where expected | Reporter or result collection configuration is missing or differs from the example | Confirm the fixture setup and reporter configuration against the current integration guide; inspect the configured Eyes report or dashboard. |
Performance, reliability, and cost considerations
Visual runs add checkpoint capture, upload, comparison, and review work to a functional test suite. Limit checkpoints to meaningful states rather than capturing after every action. Reuse stable setup where appropriate, but keep each checkpoint understandable and independently attributable in reports.
Reliability depends on reproducible page state, available credentials, correct SDK configuration, and access to the selected Eyes Server deployment. A failed or interrupted visual run should be investigated separately from an application behavior failure. The reviewed sources provide no named performance benchmark or false-positive rate, so estimate runtime and review effort using your own suite.
Applitools pricing was not established in the source material for this article. Check current vendor pricing and plan terms before budgeting; do not infer cost from the number of checkpoints alone.
Built-in Playwright screenshots and Applitools
Playwright’s screenshot assertions are useful when you want a Playwright-native snapshot workflow. Eyes adds an SDK and a baseline review/reporting workflow, with documented region and matching controls. Compare the options against your team’s desired review process, language support, rendering environments, and hosting requirements. Applitools positions Visual AI as a way to reduce noise from rendering differences such as anti-aliasing and font rendering; treat that as vendor positioning, not a guarantee that pixel-diff failures disappear. Neither approach replaces functional assertions.
Or skip the browser setup
If your goal is to capture a website image through an API, ScreenshotNeo offers a one-request screenshot API and MCP server. This does not replace Eyes’ visual baseline comparison and review workflow; it is an alternative for generating captures.
See the ScreenshotNeo API documentation for options and setup.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://example.com"},
timeout=90,
)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
const bytes = new Uint8Array(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', bytes));
ScreenshotNeo removes cookie banners, newsletter popups, and chat widgets before the shot. Bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Learn about ScreenshotNeo or sign up for 1,000 free screenshots a month with no card.
FAQ
Does a visual checkpoint test application behavior?
No. It checks the rendered appearance against a baseline. Keep functional assertions for behavior such as navigation, validation, and data submission.
Can I use a language other than TypeScript?
Yes. Applitools lists Java, C#, and Python variants as well as JavaScript/TypeScript options. Follow the setup for that language rather than reusing the fixture import shown here.
Should every visual difference be accepted?
No. Accept only changes that are intended. Acceptance changes the baseline for future comparisons.


