How to Test Modern Websites Across Browsers and Devices
Build a practical browser and device test plan with Playwright, responsive checks, emulation, and targeted real-environment validation.
To test a modern website across browsers and devices, first define the browsers, operating systems, screen ranges, input types, and user journeys your site intends to support. Automate stable, important journeys across Chromium, Firefox, and WebKit; test responsive layouts at widths where your design changes; use emulation for scalable coverage; and validate in an actual target environment when a device or browser-specific issue matters. There is no universal test matrix: use your audience and the risk of each journey to choose coverage.
These checks cover two different things. Cross-browser testing looks for differences in browser and engine behavior. Responsive testing checks whether layout and usability work at different sizes and orientations. A viewport preset alone does not cover browser compatibility, and testing three engines at one desktop size does not establish that a mobile layout works.
1. Define the support target
Write down the combinations and workflows that matter before adding projects to a test suite. Base priorities on your stated support commitments, audience information available to your team, and the consequences of a failure. The documentation cited here describes tool capabilities; it does not prescribe a universal audience threshold or a matrix that guarantees compatibility.
- Browser and engine: Chromium, Firefox, WebKit, and branded Chrome or Edge channels if your users or support policy make them relevant.
- Operating system and version: choose combinations according to your supported audience and where a failure would matter. Hosted provider matrices change, so check the current matrix before relying on a specific combination.
- Screen and orientation: identify the widths that trigger your own layout transitions, plus meaningful content stress points and portrait or landscape modes your experience supports.
- Input and context: consider touch versus mouse, locale, timezone, permissions, geolocation, and color scheme when these affect functionality.
- Journeys: select stable, high-value paths such as signing in, completing a form, viewing a key page, or finishing checkout. Include the flows that would cause the most harm if broken.
Keep the list intentional. Each combination has a maintenance cost, so add one when it covers a supported user group, a meaningful layout transition, a critical journey, or a reported failure.
2. Automate browser coverage with Playwright
Playwright supports Chromium, WebKit, and Firefox, plus branded Chrome and Edge channels. Projects let you run the same test suite under different browser and device configurations. Playwright’s documentation says it can run tests on those browser engines and branded browsers such as Google Chrome and Microsoft Edge: Playwright browser documentation.
Install a runnable starter project
Use a current Node.js installation. Create a directory, install Playwright Test, install the matching browser binaries, and add a test:
mkdir browser-coverage
cd browser-coverage
npm init -y
npm install --save-dev @playwright/test
npx playwright install
mkdir tests
Create playwright.config.ts:
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './tests',
fullyParallel: true,
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, replacing the example path and expected content with stable selectors and assertions from your own application:
import { test, expect } from '@playwright/test';
test('home page renders its primary action', async ({ page }) => {
await page.goto('/');
await expect(page.getByRole('heading', { name: 'Welcome' })).toBeVisible();
await expect(page.getByRole('link', { name: 'Get started' })).toBeVisible();
});
Run the suite across all configured projects:
BASE_URL=https://example.com npx playwright test
Run one project when reproducing or narrowing a failure:
BASE_URL=https://example.com npx playwright test --project=webkit
Use role, label, and other user-facing locators where practical. They tend to express what the user interacts with and are easier to maintain than selectors coupled to incidental markup. Make assertions about meaningful outcomes, not just that navigation returned.
Keep browser versions reproducible
Playwright browser binaries need to match the installed Playwright package. After installing or updating the package, install the corresponding browsers with npx playwright install. In CI, keep the package lockfile, record the Playwright version and selected browser projects in logs or reports, and make the same browser set available to local reproduction. Playwright recommends regular updates so teams cover current browser versions; update the package and its browser binaries together. See Playwright’s browser installation and version guidance.
3. Check responsive layouts at meaningful widths
Responsive coverage is about how the page behaves as available space and orientation change. Choose widths around your site’s actual layout transitions, then add widths that stress long content, navigation, forms, dialogs, and embedded media. Avoid treating a device preset list as exhaustive viewport coverage.
At each selected size, inspect or assert:
- Text wrapping, clipped labels, and controls that become hard to reach.
- Navigation menus, dialogs, sticky headers, and consent interfaces.
- Images and embedded content that overflow, distort, or leave large gaps.
- Forms, validation messages, buttons, and keyboard or touch access.
- Unexpected horizontal scrolling and elements obscured by fixed UI.
- Orientation changes, when both portrait and landscape are supported.
For a quick automated width check, add a project with a specific viewport or create a test that sets the viewport at meaningful boundaries. This Playwright example checks for document-level horizontal overflow at two chosen widths; choose values based on your own layout rather than copying them as a standard:
import { test, expect } from '@playwright/test';
for (const width of [390, 768]) {
test(`page has no document overflow at ${width}px`, async ({ page }) => {
await page.setViewportSize({ width, height: 844 });
await page.goto('/');
const dimensions = await page.evaluate(() => ({
documentWidth: document.documentElement.scrollWidth,
viewportWidth: document.documentElement.clientWidth,
}));
expect(dimensions.documentWidth).toBeLessThanOrEqual(dimensions.viewportWidth);
});
}
An overflow assertion is a useful signal, not a complete responsive design check. It does not tell you whether a control is awkward to use, a heading is visually unbalanced, or content is hidden in a way the test did not anticipate. Pair assertions with review of key states and interactions.
4. Use emulation for breadth, then validate the target environment
Playwright can emulate selected device and browser parameters, including viewport and screen size, user agent, touch, locale, timezone, permissions, geolocation, and color scheme. Its device profiles are useful for repeating checks at known settings. Read Playwright’s emulation documentation for the supported settings and configuration examples.
Emulation is a way to scale coverage of selected parameters; it does not establish that every behavior of a physical device has been reproduced. Use an actual target browser and operating system when the issue appears specific to them, when device behavior is central to the feature, or when a failure must be verified in the environment your users have.
For example, hosted testing services can provide configurable OS, browser, and device combinations. BrowserStack documents Live for manual browser testing and Automate for browser automation, and publishes a Playwright support matrix. The available combinations are provider-specific and can change, so check its current Playwright browser and OS matrix before planning coverage. A device appearing in a service matrix is an option, not a recommendation to purchase it.
5. Compare failures across useful axes
When a check fails, record enough context to reproduce it and compare like with like:
| Axis | What to compare | What it can reveal |
|---|---|---|
| Browser and engine | Chromium, Firefox, WebKit, and relevant branded channels | Differences in rendering, browser APIs, or interaction behavior |
| OS and version | Only combinations that matter to your support target | Platform-specific behavior and browser version differences |
| Viewport and orientation | Widths around layout transitions and supported orientations | Responsive layout and usability problems |
| Device realism | Emulated parameters versus the target physical or hosted environment | Whether the issue depends on behavior emulation did not reproduce |
| Workflow and maintenance | Local automation, hosted access, browser updates, and reproduction steps | Whether the coverage remains reliable and maintainable |
Save the failing test name, browser and Playwright versions, OS or hosted environment, viewport, orientation, and relevant trace or screenshot. Change one axis at a time when narrowing the cause. If a failure happens only in a hosted target, verify that the provider currently supports that browser and OS combination.
6. Build a risk-based matrix
Use a small baseline and add targeted coverage where it buys confidence. An example structure is below; it is a planning template, not a universal required matrix.
| Coverage layer | Example scope | When it helps |
|---|---|---|
| Automated engine baseline | Critical journeys in Chromium, Firefox, and WebKit | Catch broad browser behavior regressions on each change |
| Responsive checkpoints | Widths around your breakpoints, content extremes, and supported orientations | Catch layout and usability regressions |
| Context emulation | Touch, locale, timezone, color scheme, geolocation, or permissions used by the feature | Exercise context-dependent paths without hand-configuring every run |
| Target environment check | A relevant real device, OS/browser pair, or hosted session | Investigate target-specific behavior or validate high-risk flows |
For each added project or environment, state which audience, journey, or risk it covers. Revisit that choice when supported browsers, layouts, or product workflows change.
7. Troubleshoot common failures
| Symptom | Likely cause | Fix |
|---|---|---|
| Playwright cannot launch a browser | The browser binary is missing or does not match the installed package. | Run npx playwright install after installing or updating Playwright. In CI, use the browser binaries for the locked package version. |
| Test passes locally but fails in CI | Different browser versions, missing environment configuration, timing assumptions, or an unavailable service. | Record package/browser versions and environment, make the expected browser projects available, and use assertions that wait for the user-visible condition. |
| Only one engine fails | A browser API, rendering behavior, or application assumption differs. | Keep the failing engine in the reproduction, inspect its trace, and reduce the case before changing application code. |
| Mobile-sized page still overflows | A fixed-width element, long unbroken text, image, or positioned component exceeds the viewport. | Inspect the overflowing element at the failing width; test nearby widths and the relevant interaction state. |
| Emulated device works but a physical device does not | The emulation did not reproduce a device or OS behavior that matters to the issue. | Reproduce in the target environment and record its exact browser, OS, device, orientation, and steps. |
| Hosted environment is unavailable or differs from expectations | The provider’s supported browser, OS, or device matrix may have changed. | Check the current provider matrix and select a currently supported combination. |
| Test is flaky around navigation or loading | The test assumes a fixed delay or checks before the relevant state is ready. | Wait for a concrete page state or user-visible result; reserve fixed delays for cases where time itself is the behavior under test. |
8. Performance, reliability, and cost
More projects and environments expand coverage but also increase runtime, resource use, and maintenance. Start with critical journeys and the browser engines and widths that support your stated audience. Run the broadest stable suite at the cadence your release process can support, and use targeted project selection to reproduce a specific failure. Parallel execution can reduce elapsed time when CI resources allow it, but it consumes more concurrent resources.
Reliability depends on repeatable inputs: keep Playwright and browser versions aligned, make environment configuration explicit, and avoid timing-sensitive assertions. Preserve traces or other failure artifacts your team needs to diagnose regressions. A green emulation run is evidence for the emulated configuration, not proof of every physical-device behavior.
Local Playwright automation has no per-session provider fee in the framework setup shown here, though it uses developer and CI compute. Hosted browser or device access adds a provider and plan decision; pricing and availability are not established here, so check the provider’s current terms before committing. Do not add a paid device cloud merely to make a matrix look comprehensive: first identify the environment or risk it covers.
Or skip the browser setup
If your goal is to capture a page rather than run an interactive compatibility suite, ScreenshotNeo returns a screenshot or PDF from one request. It is a website screenshot API and MCP server for developers, made by Yorker Media. The API can capture PNG, JPEG, or WebP images; the example below saves the response body as a WebP file. 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://example.com \
-o shot.webp
Cookie and consent banners are accepted before capture, and 60+ known consent platforms, newsletter popups, and chat widgets are removed; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers say which outcome occurred. Its MCP server gives AI agents tools to take screenshots, inspect page information, and capture PDFs. Plans include 1,000 screenshots per month free with no card; paid plans start at $5 for 3,000 screenshots. See ScreenshotNeo for product details. Sign up for 1,000 free screenshots a month, with no card.
A screenshot API is useful for page captures and visual inputs to workflows; it does not replace interactive browser tests or actual target-environment validation for compatibility issues.
FAQ
How do I test my website on different browsers?
Automate important journeys in Chromium, Firefox, and WebKit with Playwright, then add branded channels if they matter to your support target. Keep the package and browser binaries aligned.
How do I test a website on mobile devices?
Use emulated device settings for broad responsive and context checks. Validate in a relevant real or hosted target environment when physical-device or OS behavior matters.
How do I check responsive design across screen sizes?
Test widths around your own layout transitions and content stress points. Check both layout and usability, including navigation, forms, dialogs, images, and overflow.
Do I need real devices or is browser emulation enough?
Emulation is useful for scalable coverage of selected settings. Use a real target environment when the feature or failure depends on behavior emulation may not reproduce.
Does passing this matrix guarantee compatibility for every user?
No finite matrix establishes that. It provides evidence for the environments, configurations, and journeys you selected; adjust it as your audience and risks change.


