ScreenshotNeo

BlogHow-to

How to Use the Applitools Playwright SDK for Visual Testing

Add Applitools Eyes visual checkpoints to Playwright, configure baselines and reports, and troubleshoot common setup and comparison issues.

By the ScreenshotNeo team4 October 202610 min read

To add Applitools Eyes visual testing to a JavaScript or TypeScript Playwright project, install @applitools/eyes-playwright, provide an APPLITOOLS_API_KEY, and use the package’s Playwright fixture. Navigate to a stable page state and call eyes.check() to create a visual checkpoint. Eyes compares that checkpoint with a saved baseline so you can review and accept intended UI changes or reject regressions.

This guide covers the JavaScript/TypeScript Fixtures integration. Applitools also lists Standard JavaScript/TypeScript, Java, C#, and Python SDK variants; their imports and setup may differ. Use the SDK variant that matches your project rather than copying fixture imports into another language. See the Applitools Playwright integration guide and its SDK directory for the applicable variant.

1. Install and initialize the Playwright SDK

From the root of an existing Playwright project, install the SDK and run its setup command:

npm install --save-dev @applitools/eyes-playwright
npx eyes-playwright setup

The setup CLI guides configuration and can add a demo visual test. Review the generated files and imports against your existing playwright.config.ts, test layout, and package manager conventions. The commands above follow Applitools’ updated JavaScript/TypeScript setup workflow described in its updated SDK setup article.

Set the API key

Set APPLITOOLS_API_KEY in your shell or CI secret store. Do not put a real key in committed source code or a checked-in config file.

# macOS or Linux shell
export APPLITOOLS_API_KEY="YOUR_API_KEY"

# PowerShell
$env:APPLITOOLS_API_KEY="YOUR_API_KEY"

Applitools recommends the environment-variable approach to avoid hardcoding the credential; consult its API key documentation for key setup details. In CI, add the key as a protected secret and expose it only to jobs that need to run visual tests.

2. Add your first visual checkpoint

Import test from the Applitools fixture package. The fixture supplies an eyes object to the test and manages the Eyes lifecycle and result collection.

import { test } from '@applitools/eyes-playwright/fixture';

test('Homepage visual check', async ({ page, eyes }) => {
  await page.goto('https://example.com');

  await eyes.check('Homepage', {
    fully: true,
    matchLevel: 'Strict',
  });
});

Replace the URL with your application and give each checkpoint a stable, descriptive name. Run the test with your normal Playwright command, for example npx playwright test. The first run establishes or proposes a baseline in the Eyes service; subsequent runs compare against saved baselines. Review the result before accepting a baseline update.

Make the page state deterministic

Navigate to the state you intend to validate before taking the checkpoint. Wait for application-specific readiness, dismiss or configure consent dialogs as appropriate to the test, and control test data that changes the page. A fixed delay is often less reliable than waiting for a known element or state.

import { expect } from '@playwright/test';
import { test } from '@applitools/eyes-playwright/fixture';

test('Account page after loading', async ({ page, eyes }) => {
  await page.goto('https://example.com/account');
  await expect(page.getByRole('heading', { name: 'Account' })).toBeVisible();
  await page.locator('[data-testid="loading-indicator"]').waitFor({ state: 'hidden' });

  await eyes.check('Account page ready', { fully: true });
});

Use selectors and assertions that match your application. If a loading indicator is not rendered on every run, choose a readiness condition that is consistently present rather than waiting for an element that may never exist.

3. Configure Playwright reporting and Eyes defaults

Applitools’ integration guide shows eyesConfig under Playwright’s use settings and an Applitools reporter. Merge these settings into your existing configuration rather than replacing your browser projects, timeouts, or other reporters.

import { defineConfig } from '@playwright/test';
import { EyesFixture } from '@applitools/eyes-playwright/fixture';

export default defineConfig<EyesFixture>({
  reporter: [
    ['list'],
    ['@applitools/eyes-playwright/reporter'],
  ],
  use: {
    eyesConfig: {
      appName: 'Storefront',
      failTestsOnDiff: 'afterEach',
    },
  },
});

The integration guide describes appName, batch, and failTestsOnDiff as configuration points. Its example uses 'afterEach'; the documented alternatives for failTestsOnDiff are 'afterEach', 'afterAll', and false. Choose when visual differences should fail the Playwright run based on your review workflow. See the configuration and reporter documentation for the current integration details.

The enhanced report presents Eyes results alongside Playwright reporting. Baseline changes still need deliberate review and authentication to accept or reject them. The exact review flow depends on the installed integration and report setup.

4. Choose checkpoint scope and matching options

Start with the smallest region that proves the behavior you care about. A full-page checkpoint catches broad page changes, while a region checkpoint keeps unrelated page content out of a focused component test.

Setting Use Practical note
fully: true Capture the full page, including content beyond the viewport. Useful for long pages; ensure lazy-loaded content has rendered before capture.
region Limit the checkpoint to an element or region. Use a stable locator and verify the element exists in the intended state.
matchLevel Choose the comparison behavior, such as 'Strict' or 'Layout'. Use the mode appropriate to the assertion; verify accepted values in the SDK documentation for your version.
ignoreRegions Exclude known volatile areas, such as timestamps or rotating content. Keep exclusions narrow so meaningful regressions remain visible.
floatingRegions Mark content that may move while its appearance remains relevant. Use for genuinely position-variable elements, not as a blanket way to hide layout changes.
IgnoreDisplacements Suppress differences caused by elements shifting position. Check the spelling and option shape supported by your installed SDK version.

Example: check a navigation element and ignore a changing promotional area elsewhere on the page.

test('Navigation visual check', async ({ page, eyes }) => {
  await page.goto('https://example.com');
  const navigation = page.locator('nav[aria-label="Primary"]');
  await navigation.waitFor({ state: 'visible' });

  await eyes.check('Primary navigation', {
    region: navigation,
    matchLevel: 'Strict',
    ignoreRegions: [page.locator('[data-testid="rotating-promo"]')],
  });
});

The documented integration supports full-page capture, a target region, match level, ignored regions, floating regions, and displacement handling. Option names and accepted values are SDK-specific; check the integration docs before adopting an option not shown in your installed package’s examples.

Viewport-only versus full-page checks

Without full-page capture, a checkpoint focuses on the visible page area according to the SDK’s target behavior. Use fully: true when below-the-fold content is part of the requirement. Full-page capture can take longer on very long documents, and content that loads only after scrolling may need to be triggered or awaited in the test first.

5. Review baselines and organize a growing suite

  1. Run the visual test against the intended environment and test data.
  2. Inspect the checkpoint and its differences in the Eyes results/report.
  3. Accept the change only if it is an intentional design update; otherwise fix the application or test setup.
  4. Keep checkpoint names meaningful and consistent so results can be identified across runs.
  5. Group related tests into an application and batch strategy that fits your team’s review process.

Eyes compares captured checkpoints with saved baselines through its service. Accepting a change updates the baseline used by later runs, so baseline approval is a source-of-truth change, not just a way to silence a failing test. See the Eyes system overview for the capture, comparison, and review flow.

As the suite grows, encapsulate repeated checkpoints in page objects or fixtures when that makes the test easier to understand. Keep visual checks for appearance and retain ordinary Playwright assertions for conditions such as text, navigation, or application state that need explicit programmatic validation.

6. Use other Applitools SDK variants carefully

This walkthrough uses JavaScript/TypeScript Playwright Fixtures. The SDK directory also lists TypeScript Standard, Java, C#, and Python options. Fixture-managed lifecycle and imports are particular to the fixture path; do not assume the sample’s import { test }, injected eyes, reporter configuration, or CLI setup applies unchanged to another language or the Standard API. Open the documentation for the selected SDK and follow its lifecycle model. The updated SDK article describes backward compatibility and a gradual migration approach for existing users.

7. Or skip the browser setup

If you need a screenshot asset rather than an Applitools baseline comparison inside a Playwright test, ScreenshotNeo is a website screenshot API and MCP server. It does not replace Eyes checkpoint assertions; it provides screenshot and PDF capture through one GET request.

cURL:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

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)

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}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await Bun.write('shot.webp', res);

See the ScreenshotNeo API documentation for request options. Cookie banners, newsletter popups, and chat widgets are removed before capture; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers report the page verdict and billing status. ScreenshotNeo also has an MCP server for AI agents, with tools for screenshots, page information, and PDF capture. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots. Create a free ScreenshotNeo account.

8. Troubleshooting

Symptom Likely cause What to do
Authentication or API-key error APPLITOOLS_API_KEY is unset, misspelled, unavailable to the CI process, or invalid. Confirm the variable is set in the same shell/job that launches Playwright. Check secret injection and key validity; avoid printing the secret into logs.
Cannot resolve @applitools/eyes-playwright/fixture The package is missing, dependency installation failed, or code is using the wrong SDK variant. Install the dependency in the workspace that runs the test, check the lockfile/install output, and confirm the Fixtures SDK is intended.
eyes is missing from test arguments The test imported Playwright’s default test instead of the Applitools fixture test. Import test from @applitools/eyes-playwright/fixture for this fixture workflow.
Checkpoint captures a loader, skeleton, or incomplete page The test takes the checkpoint before the application reaches a stable state. Wait for an application-specific ready signal or for the loading element to disappear before calling eyes.check().
Diffs change between runs Dynamic content, animation, time-dependent data, fonts, or environment differences affect rendering. Stabilize test data and environment; wait for animations or loading to settle; narrowly ignore content that is intentionally variable.
Full-page checkpoint misses content Lazy-loaded sections have not been triggered, or the target is not configured for full-page capture. Scroll or otherwise trigger lazy content, wait for it to render, and set fully: true.
Element-region check fails or captures the wrong part Locator is ambiguous, not visible, or points to a changing node. Use a unique stable locator, wait for visibility, and verify the page state before capture.
Playwright test passes despite a visual difference failTestsOnDiff is disabled or configured to report differences at a different lifecycle point. Review eyesConfig.failTestsOnDiff and choose 'afterEach', 'afterAll', or false according to the desired workflow.
Baseline approval is unavailable in the report The report requires authentication for baseline changes, or the run is being viewed without the necessary account access. Authenticate with the appropriate Applitools account and review the result in the configured report or Eyes test manager.
Configuration examples do not match installed types SDK versions or variants differ from the documentation snippet. Check the installed package version and consult the docs for that SDK variant. Do not copy fixture settings into the Standard API without confirming support.

9. Performance, reliability, and cost considerations

Performance

  • Every checkpoint adds capture and service-comparison work to the test run. Focus checkpoints on meaningful page states and avoid duplicate captures of unchanged screens.
  • Full-page capture can require more rendering and image processing than a focused region, especially on long pages.
  • Waiting for a real readiness condition improves reliability without relying on arbitrary long sleeps.
  • Keep ignored regions limited. Broad exclusions can reduce review noise while also hiding real visual regressions.

Reliability

  • Use the same intended browser, viewport, fonts, locale, and test data for comparable runs.
  • Make animations and time-sensitive content deterministic where possible; wait for asynchronous UI updates before capture.
  • Protect the API key in environment secrets and limit access to trusted CI contexts.
  • Treat baseline updates as reviewed changes. A mistaken acceptance can make an unwanted state the expected result.

Cost

The supplied Applitools research does not establish current plan prices, quotas, or billing rules, so this guide does not quote them. Check Applitools’ current account and pricing information for the terms that apply to your usage. Estimate workload from the number of tests, checkpoints per test, and environments or configurations included in each run; then monitor usage and failures in your account.

10. Frequently asked questions

Does Applitools replace Playwright assertions?

No. Use Eyes for appearance comparisons and Playwright assertions for explicit behavioral or data conditions that need programmatic checks.

Does the first run automatically approve the baseline?

The first run establishes or proposes a baseline for review. Review the captured state and approve it through the configured Eyes workflow before treating it as expected.

Can I use this exact code with Python or Java?

No. This sample is for JavaScript/TypeScript Playwright Fixtures. Select the matching language SDK and follow its documentation.

Can ScreenshotNeo run an Applitools visual regression test?

No. ScreenshotNeo captures screenshots and PDFs; the code above does not create or compare Applitools baselines. Use the Applitools SDK for visual testing within Playwright.