ScreenshotNeo

BlogHow-to

How to take consistent Selenium screenshots across different operating systems

Standardize Selenium screenshots across operating systems with fixed browser versions, viewports, and page state, while accounting for rendering differences that remain.

By the ScreenshotNeo team4 October 20267 min read

To make Selenium screenshots comparable across operating systems, fix the browser and driver versions, set an explicit window size, verify the resulting CSS viewport, and capture only after the page reaches a stable state. Keep the operating system image, fonts, locale, device scale factor, and test data consistent where possible. These controls improve repeatability; they do not guarantee pixel-identical rendering across Windows, macOS, and Linux.

Run visual comparisons on every OS and browser combination you support, and decide what differences your test should tolerate. Selenium provides window sizing and screenshot APIs; the rendering environment still matters. Selenium’s window and screenshot documentation explains that screen resolution can affect how an application renders.

1. Fix the inputs that affect a capture

A screenshot is the output of both the page and its execution environment. Record the following with each baseline and capture:

Input How to control it
Browser and driver Choose the browser family and version your test targets. Keep versions aligned between baseline creation and later runs; record both versions.
Operating system Use a stable OS image in CI. If local and CI images differ, treat them as separate environments and compare results.
Window and viewport Set a deliberate window size. Read window.innerWidth and window.innerHeight in the page to verify the CSS viewport actually received.
Scale factor Keep the device scale factor consistent and record the output image dimensions. A CSS viewport and a raster image do not necessarily have the same pixel dimensions.
Fonts and rendering configuration Install the same fonts in the test image and keep browser preferences and graphics configuration stable where possible.
Locale and time Fix locale, timezone, and test data so dates, number formatting, and time-dependent content are reproducible.
Page state Use deterministic data and wait for the specific content and assets your test needs.

These are variables to control and validate, not a guarantee that matching them will produce identical pixels. The reviewed documentation does not quantify the contribution of each variable.

2. Set a fixed Selenium window size

Do not use maximize as a substitute for a fixed size: it fills the available screen space, which can vary from machine to machine. Selenium exposes window sizing controls, and Chrome supports session configuration through ChromeOptions. See the Selenium window documentation and ChromeDriver capabilities and ChromeOptions.

Here is a complete Python example using Selenium. It sets a fixed window, checks the actual CSS viewport, waits for a page-specific ready condition, and saves the current browsing context as a PNG.

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait

options = webdriver.ChromeOptions()
# Optional: use headless Chrome in environments without a display.
options.add_argument("--headless")

driver = webdriver.Chrome(options=options)
try:
    driver.set_window_size(1440, 1000)
    driver.get("https://example.com")

    # Replace this with an application-specific readiness condition.
    WebDriverWait(driver, 20).until(
        lambda d: d.execute_script("return document.readyState") == "complete"
    )
    viewport = driver.execute_script(
        "return {width: window.innerWidth, height: window.innerHeight, "
        "scale: window.devicePixelRatio}"
    )
    print("Viewport:", viewport)

    driver.save_screenshot("capture.png")
finally:
    driver.quit()

Install Selenium for Python with python -m pip install selenium. A real test should replace the generic readiness check with a condition for its application, such as a visible element that appears once data has loaded. The requested outer window size is not the same thing as a guaranteed CSS viewport size; inspect and log the actual dimensions on each target environment.

Chrome’s headless screenshot documentation also demonstrates explicit dimensions using a window-size argument. For a Selenium test, prefer setting the window through WebDriver and verifying the page’s viewport rather than assuming host screen dimensions. Chrome Headless documentation.

3. Wait for a visually stable page

document.readyState == "complete" only indicates the document load event has completed. It does not prove that a single-page application has finished fetching data, web fonts have loaded, lazy images have appeared, or animations have stopped. Use the most specific readiness conditions available:

  1. Wait for the application to signal that the target view is ready, or for a meaningful page element to appear.
  2. Wait for required images to finish loading. If the app uses lazy loading, scroll the target content into view or use an application-specific mechanism to ensure it has rendered.
  3. Wait for fonts when they matter to layout; the page can expose document.fonts.ready for this purpose.
  4. Disable or settle animations and transitions in the test environment if they make captures nondeterministic.
  5. Capture after asynchronous data and overlays reach the intended test state.

A fixed sleep can be a fallback for an unavoidable delay, but it is brittle: it may be too short on a slow run and unnecessarily long on a fast one. Prefer state-based waits, with a timeout that fails visibly when the page never becomes ready.

4. Choose viewport or element screenshots

driver.save_screenshot("capture.png") captures the current browser context. It is suitable for a viewport comparison. Selenium also provides element screenshots, which are useful when only a component should be compared:

element = driver.find_element("css selector", "main .checkout-summary")
element.screenshot("checkout-summary.png")

A viewport screenshot is not a promise of identical full-document capture behavior across drivers. If the test requires a full-page image, confirm that the chosen browser and capture method support the expected behavior, then validate the resulting dimensions. Keep the comparison scope explicit: viewport, element, or whole document.

5. Run the supported operating-system matrix

WebDriver provides a platform- and language-neutral way to control browsers, and Selenium can control a local browser or a remote machine through Selenium Server. That portability helps share test logic, but it does not make browser rendering identical across operating systems. Selenium WebDriver overview. The W3C WebDriver document consulted for this article is a Working Draft, not a final Recommendation; its platform-neutral protocol describes browser control, not a promise of pixel parity. W3C WebDriver Working Draft.

  1. List the OS and browser combinations your product supports.
  2. Run the same deterministic scenario on each combination using the same intended viewport and recorded session inputs.
  3. Store screenshots with metadata: OS image, browser and driver versions, viewport, device scale factor, locale, timezone, and test-data version.
  4. Compare each capture against a baseline made for that environment, or use an explicitly chosen tolerance for cross-environment comparisons.
  5. Investigate unexpected changes by checking viewport dimensions and page readiness before treating every pixel difference as a product regression.

If developers and build agents need reproducible results, use the same container or managed OS image for both baseline generation and comparison where feasible. Keep separate baselines when the supported environments render differently and those differences are expected.

6. Troubleshooting

Symptom Likely cause Fix
Screenshot dimensions differ between machines The requested outer window dimensions produced different inner viewports, or device scale factors differ. Log innerWidth, innerHeight, and devicePixelRatio from the page. Set the window explicitly and standardize the scale factor in the environment.
Layout shifts or text wraps differently Viewport, fonts, locale, browser version, or page data differ. Compare the recorded metadata, install consistent fonts, fix locale and data, and confirm the CSS viewport before inspecting the page itself.
Screenshot is blank or missing content The page or application had not reached the required ready state, or navigation failed. Wait for an application-specific ready condition and required assets. Capture useful logs and fail the test if the condition times out.
Intermittent differences within one OS Animations, asynchronous content, timestamps, random data, or lazy loading vary between runs. Make test data deterministic, wait for the intended content, and disable or settle motion for visual tests.
Headless and headed captures differ The browser modes or their environment are not equivalent, or viewport configuration was not verified. Keep browser versions and options consistent, log the viewport and scale, and maintain separate baselines if both modes are supported.
Element screenshot fails or captures the wrong area The selector is ambiguous, the element is not visible, or the page changed before capture. Wait for the target element to be visible, use a stable selector, and capture after the page reaches the intended state.
WebDriver cannot start the browser Browser and driver setup is missing or incompatible, or the agent lacks required runtime dependencies. Check the installed browser and driver versions and the CI image configuration; use the same pinned setup as the working environment.

7. Performance, reliability, and cost

Screenshot stability has a runtime cost: explicit waits and loading the page’s required assets add time, while oversized viewports and full-page captures can produce larger images. Keep readiness conditions scoped to the tested view and avoid waiting for unrelated network activity when the application can expose a precise ready signal.

For reliability, use a controlled browser environment, save metadata with the artifact, and make timeouts fail with enough diagnostic information to reproduce the run. The research sources provide no cross-OS consistency benchmark or quantified cost for Selenium capture; execution cost depends on your browser infrastructure, CI capacity, and test duration.

8. Or skip the browser setup

ScreenshotNeo provides a screenshot API and MCP server for developers. A GET request with a URL returns an image or PDF. For this example, it returns a WebP screenshot of the target page:

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

See the ScreenshotNeo API documentation for request options. Cookie and consent banners are accepted like a visitor and removed before capture; newsletter popups and chat widgets are also removed, and each cleanup step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, with the response indicating page verdict and billing status in headers. 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 shots.

Sign up free for 1,000 screenshots a month, no card required.

FAQ

Will setting the same Selenium window size make screenshots pixel-identical on every OS?

No. It controls an important input, but it does not guarantee identical rendering across operating systems. Test and baseline the OS and browser combinations you support.

Should I maximize the browser before a visual test?

Usually not for reproducible screenshots. Maximize uses the available screen space, which may differ by host. Choose a fixed size and verify the actual viewport.

Is a fixed delay enough to make captures stable?

Not reliably. Wait for application state and required assets, then use a timeout to surface runs that never become ready.