How to Test Websites on Older Browser Versions
Choose the older browser versions that matter to your users, then test real journeys in pinned local browsers or a hosted browser grid.
To test a website on older browser versions, first define the exact browser, version, operating system, and user journeys you need to support. Then run your automated checks in a browser environment that actually provides that version. Playwright is useful for repeatable checks across its supported Chromium, Firefox, and WebKit builds; for a specific older Chrome, Edge, Safari, or OS combination, use a hosted grid or a controlled machine that lists that exact target.
There is no single correct “old browser” target. Base the support matrix on your audience data, contracts, or published support policy. A browser family alone is not enough: version, operating system, viewport, and sometimes device hardware affect results.
1. Define the support matrix
Write down the environments and the journeys that must work before selecting tools. Avoid treating a broad browser label such as “Safari” or “Chrome” as a complete test target.
| Field | What to record |
|---|---|
| Browser | Family and, when relevant, branded product: Chrome, Edge, Safari, Firefox. |
| Version | An exact version or a minimum supported version. Use a fixed version for a release gate. |
| Operating system | Windows, macOS, Linux, iOS, or Android as applicable to the reported behavior. |
| Form factor | Desktop, tablet, or phone; include viewport dimensions when layout matters. |
| Critical journeys | For example, sign-in, search, checkout, form submission, file upload, or a key workflow in your application. |
| Evidence | Browser and OS reported by the environment, test output, console/network errors, and a screenshot or trace when useful. |
Keep the matrix small enough to run consistently. Include only combinations justified by usage, support commitments, or a known defect. Revisit it when those requirements change.
2. Choose an environment that can run the target
| Approach | Use it for | What to verify |
|---|---|---|
| Playwright-managed browsers | Repeatable automated checks in supported Chromium, Firefox, and WebKit builds. | Browser binaries must match the Playwright release. Playwright WebKit is not branded Safari, and operating-system behavior can differ. |
| Hosted browser grid | Exact browser/OS combinations without maintaining a local lab. | Check the exact product’s current matrix and select explicit capabilities. Availability differs between provider products and changes over time. |
| Grid with a local tunnel | Testing a localhost, staging, or internal-only site in remote browsers. | Configure the provider’s local connection and the matching capability in the test session. |
| Dedicated legacy machine or device | A required target absent from hosted offerings, or hardware-specific reproduction. | Maintain it as a controlled environment and keep it tied to a documented support need. |
Playwright updates the browser revisions it supports along with its releases. Its documentation says that each Playwright version needs specific browser binaries; pin your package version and install its matching browsers for repeatable runs. Playwright browser documentation
Playwright’s WebKit build is not branded Safari. If a failure depends on Safari itself, Apple’s operating system, codecs, or other platform behavior, run in an environment that supplies the specific browser and operating system. Do not treat a WebKit run on a different OS as proof of exact Safari behavior. Playwright’s WebKit notes
3. Run repeatable cross-browser checks with Playwright
This example creates a small runnable Playwright Test project and runs the same basic user journey in Playwright’s Chromium, Firefox, and WebKit builds. It checks a reachable example site; replace the URL and locators with your app’s stable test page and controls.
- Install Node.js, then create a directory and initialize the project.
- Install and pin Playwright Test, then install the corresponding browser binaries.
- Save the two files below and run the test.
mkdir older-browser-check
cd older-browser-check
npm init -y
npm install --save-dev @playwright/test
npx playwright install chromium firefox webkit
Create playwright.config.js:
const { defineConfig } = require('@playwright/test');
module.exports = defineConfig({
testDir: './tests',
timeout: 30_000,
expect: { timeout: 5_000 },
retries: 0,
reporter: 'list',
use: {
headless: true,
viewport: { width: 1280, height: 800 },
trace: 'retain-on-failure',
screenshot: 'only-on-failure',
},
projects: [
{ name: 'chromium', use: { browserName: 'chromium' } },
{ name: 'firefox', use: { browserName: 'firefox' } },
{ name: 'webkit', use: { browserName: 'webkit' } },
],
});
Create tests/basic.spec.js:
const { test, expect } = require('@playwright/test');
test('homepage loads and primary navigation works', async ({ page }) => {
const response = await page.goto('https://example.com', {
waitUntil: 'domcontentloaded',
});
expect(response, 'navigation should return a response').not.toBeNull();
expect(response.status(), 'HTTP response should be successful').toBeLessThan(400);
await expect(page.locator('h1')).toBeVisible();
await expect(page.locator('h1')).toContainText('Example Domain');
});
Run all configured projects or select one:
npx playwright test
npx playwright test --project=firefox
The example proves only that this test passed in the installed Playwright browser builds on the machine or CI operating system. It does not select historical browser releases. For a minimum supported version older than the revisions Playwright supplies, move that test to a grid or controlled machine offering the exact target.
Pin the setup for repeatability
Commit package-lock.json (or your package manager’s lockfile) and install dependencies with the lockfile in CI. Use the same Playwright package version to install and execute browser binaries. When deliberately updating Playwright, rerun its browser installation command and review the resulting test changes.
# Install exact versions from package-lock.json in CI
npm ci
npx playwright install chromium firefox webkit
npx playwright test
A changing alias such as latest is useful for checking current releases, but it is not a stable historical target. Keep a fixed target explicit in the provider’s version capability, and confirm that exact browser/OS combination in the current provider documentation or dashboard. BrowserStack maintains separate matrices for its Selenium and Playwright offerings; do not assume a version listed for one applies to the other. BrowserStack Automate documentation · BrowserStack Playwright documentation
4. Test exact older browser and operating-system versions on a grid
A hosted grid is appropriate when the required version or OS is not available among your local Playwright binaries. Select the provider product first, then find its current supported environment listing. Configure browser, version, and operating system explicitly; avoid a default session whose environment may change.
- Identify the exact target from your matrix, such as a named browser release on a specified OS.
- Check that the provider’s chosen product currently supports that combination.
- Set explicit browser and OS capabilities in the test configuration. Use an explicit version for fixed historical coverage; aliases like
latestdescribe moving targets. - Run the same journey and capture the session’s reported environment with the result.
- For visual or platform-sensitive failures, repeat in that exact target and inspect the page, console, and network activity.
Provider support changes. Recheck availability before making a particular browser/OS pair a release gate. For BrowserStack, consult the documentation or dashboard for the specific integration you use: Selenium and Playwright do not necessarily expose identical matrices. BrowserStack Selenium Automate · BrowserStack Playwright
5. Reach a private site from a remote browser
A remote browser cannot normally reach a developer’s localhost or an internal hostname by itself. Use the hosted provider’s Local Testing tunnel or equivalent private-network connection, then enable its local setting in the browser session. BrowserStack documents Local Testing for connecting remote browsers and devices to internal websites; its Playwright capabilities include a browserstack.local setting. Follow the provider’s current setup and capability instructions for your product. BrowserStack Local Testing documentation · BrowserStack Playwright documentation
Check that the tunnel is connected, the test session enables local access, and the URL resolves from the remote environment. Do not expose an internal site publicly just to make a remote test work.
6. Make failures actionable
- Record the environment. Save browser name and version, OS, viewport or device, and provider session identifier with each failure.
- Separate test setup errors from compatibility defects. A missing binary, unsupported provider target, or unreachable staging site says nothing about whether the page works in the intended browser.
- Check the whole journey. Assert visible outcomes after actions, not only that the initial page loaded. Include the failure-prone controls, validation, navigation, and completion state relevant to your product.
- Inspect browser evidence. Use traces, screenshots, console messages, and failed network requests to distinguish a JavaScript/API incompatibility from a layout or environment issue.
- Repeat platform-sensitive failures. Verify visual, media, input, and OS-specific reports in the exact target environment before changing application code.
7. Screenshot a page while investigating compatibility
A screenshot helps compare layout and visible rendering, but it does not replace interaction tests or prove that a page works in an older browser. Capture the page from the target environment when that distinction matters. For a quick record of a publicly reachable page, a screenshot API can produce a visual artifact; ScreenshotNeo is the first option to try because it removes consent clutter before capture, bills only clean shots, and its lowest paid plan is $5.
ScreenshotNeo is a website screenshot API and MCP server. Its API accepts a URL and returns an image or PDF. This call captures a page to a WebP file; see the ScreenshotNeo API documentation for available formats and options.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
For a hosted legacy-browser test, run the screenshot from inside that browser session when you need the output to represent that exact browser and OS. An API capture is useful for a visual artifact, not a substitute for running the page in the target browser.
8. Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Playwright says an executable is missing. | The matching browser binary was not installed, or the package version changed. | Run npx playwright install chromium firefox webkit using the project’s pinned Playwright version. |
| A test passes locally but fails in CI before launching. | CI lacks operating-system dependencies or the browser installation step. | Install browsers in the CI job; on supported Linux setups, use npx playwright install --with-deps as appropriate. |
| The target old version is absent from Playwright. | Playwright-managed builds track revisions associated with its releases, not every historical branded browser. | Use a grid or controlled machine that explicitly supplies the required version and OS. |
| WebKit passes but Safari fails. | Playwright’s WebKit is not branded Safari; OS and platform features may differ. | Reproduce on the required Safari and Apple OS environment. |
| A hosted session launches a different browser or OS. | Capabilities are incomplete, use a moving alias, or the target is unsupported by that product. | Set explicit capabilities and verify the selected product’s current matrix and session metadata. |
| A remote test cannot open a staging or localhost URL. | The remote environment has no route to the private network, or the tunnel/local capability is missing. | Start the provider’s Local Testing connection and enable local access in the session; check hostname and port resolution. |
| The screenshot differs but functional assertions pass. | Viewport, fonts, OS rendering, dynamic content, or timing differs. | Compare at the same viewport and exact platform, wait for the relevant content, and inspect in the target environment before treating the difference as a defect. |
| The failure disappears on retry. | The test may depend on external services, timing, or mutable test data. | Stabilize test data and readiness conditions, retain trace evidence, and use retries as diagnostics rather than masking a recurring failure. |
9. Performance, reliability, and cost
- Run broad checks locally; spend grid time on justified targets. A short Playwright suite across supported engines can catch broad issues, while a small, documented set of fixed legacy combinations avoids maintaining an unnecessarily large matrix.
- Parallelism is a tradeoff. Parallel jobs can reduce elapsed time but use more CI workers or hosted sessions. Keep the release gate focused on high-value journeys and run larger exploratory coverage separately.
- Pin and update deliberately. Pin Playwright and its lockfile for reproducibility. Update on a schedule, reinstall the matching browser binaries, and review failures caused by changed browser revisions.
- Hosted costs depend on the chosen provider and plan. The research does not establish current prices; check the provider’s current terms and session limits before sizing a grid.
- Keep evidence with the build. Preserve environment metadata and failure artifacts long enough to compare regressions. Avoid treating screenshots as a functional pass signal.
10. Or skip the browser setup
For a screenshot of a page without installing or managing a browser, call ScreenshotNeo’s API. This captures a visual reference; it does not execute your journey in a chosen historical browser or establish browser compatibility.
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,
)
r.raise_for_status()
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 fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));
Cookie banners, popups, and chat widgets are removed before the shot. Bot checks, blank pages, and failed loads are never billed. An MCP server lets AI agents use the screenshot tools. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. See the API docs and MCP setup documentation for details. Create a free ScreenshotNeo account.
FAQ
Can I install any historical Chrome or Safari version with Playwright?
Playwright installs browser revisions associated with its own releases. For a historical branded browser or a specific OS pairing outside those builds, use a provider or controlled machine that offers the exact target.
Does a passing screenshot prove an old browser works?
No. A screenshot checks visible output at one point in time. Run the important interactions in the actual target environment and assert their outcomes.
Should I test every old browser version?
No universal list applies. Test versions required by audience evidence, contractual obligations, support policy, or a specific defect, and remove targets when those reasons no longer apply.
What should I save with a compatibility bug report?
Include the exact browser and version, operating system, viewport or device, steps to reproduce, expected and observed behavior, and a trace, screenshot, console message, or failed request when available.
Sources
- Playwright: Browsers — browser revision matching, installation, and WebKit/Safari distinctions.
- BrowserStack: Automate with Selenium and BrowserStack: Playwright — provider-specific browser/OS capabilities and availability.
- BrowserStack: Local Testing — connecting remote browser sessions to private sites.


