Applitools Eyes Cross-Browser Testing on Safari and Chrome
Add Applitools Eyes visual checkpoints to your existing tests, cover Safari and Chrome, and manage browser-specific baselines without losing human review.
To test a website in Safari and Chrome with Applitools Eyes, keep your existing browser automation tests, add Eyes visual checkpoints at important UI states, and configure the browser environments you want Eyes to render. Eyes compares each checkpoint with an accepted baseline and reports visual differences for review. By default, Safari and Chrome are separate environments with separate baselines. Review changes before accepting them as the new reference.
This guide uses the Selenium Java SDK for a concrete browser-target example and then shows how the Playwright integration fits into an existing test suite. The API and fixture details differ by SDK, so use the current setup instructions for your language and framework.
1. What cross-browser visual testing with Eyes does
Functional tests check behavior: a button submits, a page loads, or a user can sign in. Visual checkpoints add a check for how the interface appears at those states. The test suite drives the application; the Eyes SDK captures a checkpoint and sends it to the Eyes server; the server compares it with the baseline and returns differences and a result link for review. The reviewer can report a bug, accept an intentional change, and save approved updates as the baseline for later runs. See Applitools’ system overview and visual UI testing overview.
A first run in a new environment establishes a baseline. Later runs compare against it. Baselines are normally associated with the application, test, operating system, viewport, and browser. That means a Safari checkpoint and a Chrome checkpoint ordinarily have different accepted references. This is useful when you want to detect regressions within each browser without treating browser rendering differences as application regressions. See the baseline explanation.
2. Choose the browser and baseline strategy
| Goal | Setup | Review implication |
|---|---|---|
| Verify the accepted appearance in both browsers | Use separate Safari and Chrome environments and their respective baselines. | Review each browser’s differences independently; an approved Chrome change does not automatically approve the Safari appearance. |
| Compare different environments to a shared reference | Configure a Baseline Environment Name where supported by your SDK and current Eyes configuration. | Expect environment-specific rendering differences. Applitools’ older cross-environment guidance recommends Layout match level; confirm current SDK syntax and behavior before adopting it. |
| Render many browser/device combinations through a cloud service | Consider Ultrafast Grid with a supported existing test framework. | Choose targets based on your product’s actual support matrix and review effort. Vendor performance claims are not independent benchmarks. |
The cross-environment recommendation comes from Applitools’ 2021 cross-environment help article; because that guidance is older, verify the current SDK documentation before using a shared baseline. Applitools describes Ultrafast Grid as a cloud rendering option that works with existing Playwright, Cypress, Selenium, and Appium suites. Select local execution or cloud rendering according to the browser coverage, environment control, and review workflow you need.
3. Set up Selenium Java targets for Chrome and Safari
The documented Selenium Java quickstart configures desktop browser targets through Eyes’ Configuration. This sample shows only the target setup; place it in your existing Eyes initialization and retain your project’s normal driver and test lifecycle.
import com.applitools.eyes.BatchInfo;
import com.applitools.eyes.MatchLevel;
import com.applitools.eyes.RectangleSize;
import com.applitools.eyes.selenium.Configuration;
import com.applitools.eyes.selenium.Eyes;
import com.applitools.eyes.visualgrid.model.BrowserType;
import com.applitools.eyes.visualgrid.model.DesktopBrowserInfo;
import com.applitools.eyes.visualgrid.services.RunnerOptions;
import com.applitools.eyes.visualgrid.services.VisualGridRunner;
// Configure once for the visual test run.
VisualGridRunner runner = new VisualGridRunner(new RunnerOptions().testConcurrency(2));
Eyes eyes = new Eyes(runner);
Configuration config = eyes.getConfiguration();
config.setApiKey(System.getenv("APPLITOOLS_API_KEY"));
config.setBatch(new BatchInfo("Safari and Chrome regression"));
config.addBrowsers(
new DesktopBrowserInfo(1280, 800, BrowserType.CHROME),
new DesktopBrowserInfo(1280, 800, BrowserType.SAFARI)
);
config.setMatchLevel(MatchLevel.STRICT);
eyes.setConfiguration(config);
// Use the driver and test flow required by your chosen execution mode.
eyes.open(driver, "Example App", "Checkout page", new RectangleSize(1280, 800));
driver.get("https://example.com/checkout");
eyes.check(Target.window().fully().withName("Checkout page"));
eyes.close();
// In your suite teardown, collect and report results, then close resources.
// runner.getAllTestResults(false);
The browser target dimensions are examples; choose a viewport your product supports and keep it consistent across runs. A visual grid runner can render the configured targets from the test checkpoint. The driver used to navigate the application and the target render environments are related parts of the SDK configuration, but should not be assumed interchangeable across all Eyes modes. Consult the Selenium Java quickstart for the complete setup, imports, driver lifecycle, and current syntax.
For local Selenium Java Chrome setup specifically, Applitools’ quickstart says the ChromeDriver major version must match the Chrome major version. Keep that advice scoped to the documented local setup; Safari driver setup depends on the framework and execution environment. Do not assume the same driver installation steps apply to every SDK.
Execution and result handling
- Install and configure the Eyes Selenium Java SDK following its current quickstart, and provide an API key through the documented environment variable.
- Keep the existing functional path that loads the page and prepares a deterministic state. Add a visual checkpoint after the state is ready.
- Configure Safari and Chrome targets at the dimensions you intend to support. Avoid changing browser, viewport, test name, or test state casually because those can change which baseline is selected.
- Run the test and open the Eyes result link. Inspect browser-specific diffs; approve only changes that are intended and correct.
- Save approved changes so future runs compare against the reviewed baseline. Keep the review step in the team’s release workflow.
4. Integrate Eyes with Playwright
For Playwright, Applitools documents an enhanced test fixture imported from @applitools/eyes-playwright/fixture. The fixture supplies an eyes object to the test. Keep Playwright responsible for exercising the application and use the Eyes checkpoint for the visual assertion.
// tests/checkout.spec.ts
import { test } from '@applitools/eyes-playwright/fixture';
test('checkout page visual checkpoint', async ({ page, eyes }) => {
await page.goto('https://example.com/checkout');
await page.getByRole('heading', { name: 'Checkout' }).waitFor();
await eyes.check('Checkout page', { fully: true });
});
Applitools’ current Playwright integration guide also documents global eyesConfig options such as appName, batch, and failTestsOnDiff. The latter supports 'afterEach', 'afterAll', or false in the documented fixture configuration. Browser projects and their viewport settings remain part of your Playwright configuration; follow the Eyes SDK instructions for browser target rendering and baseline setup rather than transplanting Java configuration syntax into TypeScript.
// playwright.config.ts (relevant configuration)
import { defineConfig } from '@playwright/test';
import { EyesFixture } from '@applitools/eyes-playwright/fixture';
export default defineConfig<EyesFixture>({
use: {
eyesConfig: {
appName: 'Example App',
failTestsOnDiff: 'afterEach',
},
},
projects: [
{ name: 'chromium', use: { browserName: 'chromium', viewport: { width: 1280, height: 800 } } },
{ name: 'webkit', use: { browserName: 'webkit', viewport: { width: 1280, height: 800 } } },
],
});
Playwright’s WebKit project is a browser-engine target and is not automatically identical to every installed Safari version on a user’s device. If your requirement is specifically testing Safari, choose an execution setup that actually provides the Safari environment you intend to support, and verify the current Eyes and framework documentation for that setup. The fixture example above demonstrates integration; it does not by itself guarantee that a Safari target has been configured.
5. Make screenshots stable enough to compare
- Wait for meaningful readiness. Wait for a page-specific selector or application state before checkpointing. Fixed sleeps can waste time and still miss slow content.
- Control dynamic content. Freeze clocks or test data when your application allows it; hide or regionally handle timestamps, rotating promotions, maps, and other content that should not determine pass/fail.
- Keep the viewport deliberate. A viewport change can alter wrapping, breakpoints, and page length. Treat it as a coverage change and review the resulting baseline impact.
- Use full-page capture selectively. Full-page checks cover below-the-fold content but can be more sensitive to lazy loading and long-page layout. Ensure the page has loaded the content you expect.
- Choose match level for the question. Strict is appropriate when the rendered appearance should closely match. Layout matching can be useful for cross-environment comparisons where pixel-level rendering differences are expected, but can be less sensitive to cosmetic changes. Confirm available match levels and behavior in the SDK you use.
- Name checkpoints consistently. Stable test and checkpoint names help you find the intended baseline and review results.
- Review special regions intentionally. If a dynamic area is not the subject of the test, use the SDK’s supported region or match options rather than repeatedly approving noise.
6. Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| ChromeDriver fails during local Chrome startup | The Chrome and ChromeDriver major versions differ, or the driver is not on PATH. | For the documented local Selenium Java setup, align their major versions and make sure the driver executable is discoverable. |
| Safari and Chrome both show new or unexpected baselines | The test name, app name, OS, viewport, browser target, or baseline environment changed. | Check the environment identity and target configuration. Confirm whether separate per-browser references or an intentional shared baseline is desired. |
| Differences appear on every run | The page may not be stable: asynchronous content, animation, random data, time-dependent UI, or inconsistent readiness. | Wait for a deterministic state, control variable data, and exclude only regions that are not relevant to the assertion. |
Playwright test cannot access eyes |
The test imports Playwright’s standard test instead of the Applitools fixture, or the SDK setup is incomplete. |
Use test from @applitools/eyes-playwright/fixture and follow the current integration guide. |
| Visual differences do not fail the test when expected | The configured failTestsOnDiff behavior or runner result handling may defer failure or disable it. |
Check the chosen fixture setting and the SDK’s documented result collection behavior; use a setting that matches your CI policy. |
| Cross-browser comparison reports rendering diffs | Safari and Chrome render fonts, controls, or layout details differently, or a shared baseline is configured. | Use per-browser baselines for browser-specific acceptance, or deliberately configure cross-environment comparison and an appropriate match strategy after reviewing current guidance. |
| Checkpoint is blank or incomplete | The application had not reached its ready state, a navigation failed, or deferred content had not loaded. | Assert a page-specific ready condition before capture and check the functional test’s navigation and network errors. |
7. Performance, reliability, and cost considerations
Visual tests add capture, upload, comparison, and review work to the functional suite. The exact runtime and service cost depend on the SDK, runner mode, concurrency, configured targets, and account terms; the cited technical material does not establish a general benchmark or price. Start with the highest-value flows and a small browser/viewport matrix, then add targets based on supported customer environments and actual defects you need to catch.
Cloud rendering can broaden browser coverage without requiring each target browser to run on the same local machine, while local browser runs give direct control over the local environment. Neither choice removes the need for a reproducible application state or reviewed baseline changes. If tests run in CI, keep API keys in the CI secret store, group related tests in batches, and make result review part of the change workflow. Treat browser support, viewport coverage, execution mode, and baseline review workload as one testing design decision.
8. Use ScreenshotNeo when you need a clean page capture
Eyes is for visual regression checks across test runs. If your immediate task is simply to capture a page as an image or PDF without setting up and maintaining browser automation, ScreenshotNeo is the screenshot API alternative to try first. It is a website screenshot API and MCP server from Yorker Media; a GET request returns PNG, JPEG, WebP, or PDF. It complements a visual testing suite rather than providing the Eyes baseline review workflow.
Or skip the browser setup
One GET request can capture the page. See the ScreenshotNeo API documentation for request options.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
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)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
- Cookie and consent banners are accepted like a visitor and removed, along with known newsletter popups and chat widgets; each step can be turned off.
- Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed. Response headers report the page verdict and billing status.
- An MCP server provides
take_screenshot,get_page_info, andcapture_pdftools for Claude, Cursor, and other MCP clients. - The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots. Every feature is on every plan.
Create a free ScreenshotNeo account for 1,000 screenshots a month with no card.
9. Frequently asked questions
Does adding Eyes replace Selenium or Playwright?
No. Eyes adds visual checkpoints to an existing functional test flow. Your automation framework still navigates the application and establishes the state under test.
Should Safari and Chrome share one baseline?
Usually they have separate baselines because browser is part of the default environment identity. Use a shared cross-environment baseline only when that comparison is intentional and you have confirmed current SDK guidance.
Can Playwright’s WebKit project prove Safari compatibility?
It tests the WebKit browser engine in the configured Playwright environment; do not assume that alone represents every Safari version or device you support.
Does Eyes automatically decide whether a baseline change is correct?
It reports differences, but a reviewer should determine whether a change is a defect or an intended update before saving a new baseline.
Can ScreenshotNeo replace Eyes for regression testing?
No. ScreenshotNeo captures pages through an API; the Eyes workflow described here compares checkpoints with baselines and supports visual result review. Choose the tool for the task you need.


