ScreenshotNeo

BlogGuides

Ultrafast Cross-Browser Testing: How It Works

See how parallel browser tests work, how Applitools’ Ultrafast Grid differs, and how to configure a runnable Playwright workflow.

By the ScreenshotNeo team4 October 202610 min read

Ultrafast cross-browser testing reduces elapsed time by running independent tests or browser targets at the same time. In the common approach, automation executes in actual browser environments—locally or on a remote grid—and the results are combined. “Ultrafast” also names Applitools’ specific visual-testing workflow: it captures DOM and CSS data, renders the page across a grid in parallel, then analyzes the resulting images. Those are related goals, but they are different execution models.

This guide shows how to configure parallel browser testing with Playwright, how hosted grids fit in, what Applitools means by Ultrafast, and how to choose coverage without multiplying test time or cost unnecessarily.

1. What makes cross-browser testing fast?

Parallelism makes a suite faster by assigning independent work to multiple workers or remote sessions. If a suite contains 12 independent tests and has four available workers, the runner can work on up to four tests at once. The elapsed time is not guaranteed to be exactly one quarter: startup, shared setup, slow tests, resource contention, retries, and session limits all affect the result.

Parallelism does not choose the right browsers for you and does not make an incompatible test safe to run concurrently. First choose meaningful targets—browser engines, versions, operating systems, viewport sizes, and devices—then distribute compatible work across the capacity available.

Approach What runs Useful for Main constraint
Local browser projects Your automation runs against installed or downloaded browser engines. Fast feedback and broad engine checks during development. Local machine resources and the versions you run.
Self-managed grid Automation sessions are distributed to browsers on machines you manage. Teams needing control over their environment or internal app access. Grid setup, maintenance, capacity, and diagnostics.
Hosted browser/device grid A provider provisions remote browser or device sessions. Testing across remote versions, operating systems, and devices. Plan limits, concurrency, supported test types, and remote access configuration.
Captured-page visual rendering A captured page representation is rendered in parallel for visual analysis. Visual comparison across environments without separately loading the app for each render. It is not the same as executing the full functional test in every browser.

2. Configure parallel browser projects with Playwright

Playwright projects let one test suite run against browser targets such as Chromium, Firefox, and WebKit. The configuration below defines those projects, uses four workers, and runs the same tests in each browser project. The browser projects control target coverage; the worker setting controls concurrency within the run.

Install and create the configuration

npm init -y
npm install --save-dev @playwright/test
npx playwright install

Create playwright.config.ts:

import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  testDir: './tests',
  fullyParallel: true,
  workers: process.env.CI ? 4 : undefined,
  retries: process.env.CI ? 1 : 0,
  reporter: [['list'], ['html', { open: 'never' }]],
  use: {
    baseURL: process.env.BASE_URL || 'http://127.0.0.1:3000',
    trace: 'retain-on-failure',
  },
  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },
    {
      name: 'firefox',
      use: { ...devices['Desktop Firefox'] },
    },
    {
      name: 'webkit',
      use: { ...devices['Desktop Safari'] },
    },
  ],
});

Create tests/home.spec.ts:

import { test, expect } from '@playwright/test';

test('home page lets a user open the pricing page', async ({ page }) => {
  await page.goto('/');
  await expect(page.getByRole('heading', { name: /welcome/i })).toBeVisible();
  await page.getByRole('link', { name: /pricing/i }).click();
  await expect(page).toHaveURL(/pricing/);
});

Run all projects:

BASE_URL=https://your-staging.example npx playwright test

On Windows PowerShell, set the environment variable first with $env:BASE_URL="https://your-staging.example", then run npx playwright test. To run only one project, use npx playwright test --project=firefox. To cap local concurrency explicitly, use npx playwright test --workers=2. To inspect the HTML report after a run, use npx playwright show-report.

How to decide what runs in parallel

  • Tests should not depend on execution order or shared mutable state. Give each test its own account or fixture data when necessary.
  • Browser projects multiply coverage. Three browser projects mean the suite’s tests are scheduled against three browser targets; workers determine how many tasks can proceed concurrently, subject to runner scheduling and available resources.
  • Start with the engines and viewports your users rely on. Add specific versions, operating systems, and devices when your compatibility risks require them.
  • Keep a smaller high-signal suite for frequent commits and schedule broader combinations where the additional coverage justifies the time and capacity.

3. Run tests on a remote or hosted grid

A grid distributes browser sessions across machines. With a self-managed Selenium Grid, you own the nodes, versions, networking, capacity, and maintenance. With a hosted service, the provider supplies remote environments, and the test runner connects using the provider’s documented integration and credentials.

The exact configuration varies by provider, so do not copy a generic endpoint or capability set. Follow the provider’s current documentation for the endpoint, authentication, supported browser identifiers, concurrency limits, and local-app tunnel or network access. Keep credentials in environment variables or CI secrets rather than source control. For every target, verify that the requested browser and device combination is available on the account.

BrowserStack describes Automate as supporting 3,000+ desktop and mobile browser combinations and hundreds of parallel tests. These are the provider’s own current service claims, not independent comparative measurements; check the combinations and account limits relevant to your application. SmartBear documents parallel execution on remote environments, while also listing test categories that do not support its parallel mode. Confirm support for your own test types before moving a suite to a grid.

4. What Applitools Ultrafast means

Applitools uses “Ultrafast” as a product name for its visual-testing workflow. Its published description says the test runs and captures DOM/CSS data, sends that data to the Ultrafast Grid for parallel rendering, and then uses Eyes Visual AI to analyze the rendered results. Applitools’ 2022 material says Eyes can use data captured by the first test to re-render screens rather than connecting to and loading the application separately in each cloud environment.

That mechanism is vendor-specific. Playwright projects and hosted browser grids commonly execute automation against selected browser environments. A visual rendering grid can complement functional tests, but it does not automatically prove that user interactions, browser APIs, authentication flows, or network behavior work in every real target environment.

5. Select coverage and capacity

Choose target combinations by risk

Start with the browser engines your audience uses and the areas most likely to break: complex layout, forms, media, browser-specific APIs, responsive breakpoints, and critical purchase or sign-in flows. Add operating systems, browser versions, and real devices where the product requirements call for them. Avoid treating every possible combination as equally important; the matrix should answer a compatibility question.

Estimate the practical speed limit

Parallel execution is constrained by the smallest available capacity among runner workers, machine resources, provider sessions, licenses, and compatible independent tests. More workers can reduce queueing until another limit is reached. After that, extra concurrency may only increase resource contention or cost. Measure the suite’s own wall-clock time and identify the slowest tests and setup steps before raising concurrency.

Keep results diagnosable

Use assertions that describe expected behavior, preserve traces or logs for failures, and make test data isolated. A combined report helps identify which browser project failed, but a failure can still come from the test, the app, the browser environment, or grid infrastructure. Record the target and environment with each failure so the team can reproduce it.

6. Visual testing and screenshots

Functional tests answer whether an interaction and its expected result succeeded. Visual checks answer whether the rendered page differs from an accepted baseline. They can be used together: functional assertions catch behavior failures, while screenshots or visual comparisons reveal layout, typography, and styling changes.

ScreenshotNeo is a website screenshot API and MCP server from Yorker Media. It can capture a URL as PNG, JPEG, WebP, or PDF, and supports full-page capture, element selectors, device presets and custom viewports, dark mode, custom CSS/JavaScript, waits, and other capture options. It is useful when you need a clean page image or a screenshot input for a workflow; it does not replace running functional tests in the browsers you need to validate. See the ScreenshotNeo site and its API documentation for the request options.

7. Or skip the browser setup

If your immediate task is to capture a page rather than exercise interactions across browser engines, ScreenshotNeo takes one GET request with the target URL. This runnable cURL example saves a WebP screenshot:

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);

Replace YOUR_API_KEY with your key. The cURL and Python examples are directly runnable with cURL and Python plus the requests package. The Node example uses Bun’s Bun.write to save the response body; in Node.js, use this equivalent to write the returned bytes:

import { writeFile } from 'node:fs/promises';
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 writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));

Before capture, ScreenshotNeo accepts the cookie or consent banner like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be disabled. Bot checks/CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers report the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf 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.

Sign up for ScreenshotNeo and get 1,000 free screenshots a month with no card.

8. Troubleshooting

Symptom Likely cause What to check
Tests still take nearly as long after adding workers The suite has too few independent tests, a serial dependency, slow shared setup, or a capacity bottleneck. Check worker utilization, test dependencies, setup/teardown time, CPU and memory pressure, and remote session limits.
Failures appear only when running in parallel Tests may share accounts, records, files, ports, or other mutable state. Isolate data and external resources per test or worker; remove order-dependent assumptions.
A project cannot launch its browser The browser binary is missing or the environment lacks dependencies. Run npx playwright install in the build environment and follow the framework’s install guidance for that operating system/container.
Remote session creation fails Credentials, endpoint, capabilities, or requested target may be incorrect or unavailable. Use the provider’s current integration examples; check secrets, target inventory, plan concurrency, and account permissions.
Remote browser cannot reach staging The app is on a private network or the grid lacks a route to it. Configure the provider’s documented tunnel or network access method and confirm the environment is reachable from the remote session.
Screenshot differences vary between runs Dynamic content, animation, fonts, data, viewport, or loading timing is unstable. Stabilize test data and waits, disable animation where appropriate, and use consistent browser and viewport settings.
Some test types do not run in parallel The framework or provider does not support that test category in parallel mode. Check the product’s support matrix and run the affected category separately or with a supported execution path.
Screenshot request returns an unexpected result The URL, key, page state, or capture options may be invalid, or the site may be showing a bot check or blank page. Check the response status and ScreenshotNeo’s X-Page-Verdict and X-Billed headers; review the documented parameters and retry only after addressing the page or request condition.

9. Performance, reliability, and cost

  • Performance: Parallelism primarily reduces elapsed time, not the total amount of test work. Worker startup and shared setup may cap the gain. Increase workers gradually and compare suite wall time.
  • Reliability: Parallel tests need isolated data and independent setup. Preserve traces, logs, and browser target metadata. Treat intermittent failures as evidence to investigate environment and race conditions, not as a reason to automatically expand retries.
  • Capacity and cost: Local workers consume machine resources; self-managed grids consume infrastructure and maintenance; hosted grids may constrain concurrency or charge according to their plan. Validate the provider’s current terms and supported combinations.
  • Visual test cost: Baselines need review and maintenance. A visual difference can be a genuine regression or expected content change, so the review process should distinguish them.
  • Screenshot API cost: ScreenshotNeo bills only clean shots. Bot checks/CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing. Its plans are Free for 1,000 monthly shots, Starter $5 for 3,000, Growth $15 for 15,000, Pro $39 for 60,000, Scale $99 for 250,000, and Business $249 for 1,000,000. Yearly billing gives two months free; every feature is available on every plan. See the docs for options and response details.

10. Frequently asked questions

Does cross-browser testing mean the same as visual testing?

No. Cross-browser testing can verify behavior and compatibility in selected environments. Visual testing compares rendered appearances, typically against baselines. Teams often use both.

Does every cross-browser grid use Applitools’ captured DOM/CSS workflow?

No. That is Applitools’ description of its Ultrafast Grid workflow. Many grids execute tests in actual browser sessions.

Should every test run in every browser?

Only if that coverage answers a real compatibility or risk question and the resulting capacity is justified. Prioritize critical flows and supported targets.

Can screenshots prove that an application works in a browser?

A screenshot shows rendered output at a point in time. It cannot by itself establish that forms, navigation, APIs, or interactive behavior work correctly.

Sources