Automated browser checks often fail at a visual transition that logs cannot reconstruct. A screenshot taken in the same WebDriver session preserves the rendered layout, message, or overlay as a PNG artifact for later diagnosis.

A unique filename prevents parallel jobs or repeated runs from replacing earlier evidence. An explicit Chromium viewport also gives the retained image deliberate dimensions instead of inheriting an unpredictable browser window.

Navigation can finish before client-rendered content reaches the state worth preserving, so the capture needs its own page-specific expected condition. Treat the resulting file as sensitive when the page can expose account names, private records, session data, or internal URLs.

Steps to capture a screenshot with Selenium:

  1. Define a collision-safe PNG destination and 1280-by-720 viewport at the start of capture_screenshot.py.
    capture_screenshot.py
    from pathlib import Path
    import shutil
    from struct import unpack
    from uuid import uuid4
     
    from selenium import webdriver
    from selenium.webdriver.chrome.options import Options
    from selenium.webdriver.chrome.service import Service
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.support.ui import WebDriverWait
     
     
    viewport = (1280, 720)
    output_directory = Path("artifacts")
    output_directory.mkdir(parents=True, exist_ok=True)
    output_file = output_directory / f"example-home-{uuid4().hex}.png"
  2. Configure headless Chrome below the capture boundary.
    options = Options()
    options.add_argument("--headless=new")

Drive the browser to a capture-ready state:

  1. Select a PATH-provided ChromeDriver before falling back to Selenium Manager.
    driver_path = shutil.which("chromedriver")
    service = Service(driver_path) if driver_path else Service()

    A configured chromedriver takes precedence when it is available; an empty Service() lets Selenium Manager resolve the driver otherwise.
    Related: How to configure ChromeDriver for Selenium

  2. Start a Chrome WebDriver session with the selected service and options.
    driver = webdriver.Chrome(service=service, options=options)
    try:
  3. Apply the selected viewport to the active Chromium session inside the try block.
        driver.execute_cdp_cmd(
            "Emulation.setDeviceMetricsOverride",
            {
                "width": viewport[0],
                "height": viewport[1],
                "deviceScaleFactor": 1,
                "mobile": False,
            },
        )
  4. Navigate the session to https://example.com/.
        driver.get("https://example.com/")

    Navigation waits for the selected page-load strategy, but client-rendered state may still need its own condition.
    Related: How to wait for page load in Selenium

  5. Wait until the page title exactly matches Example Domain.
        WebDriverWait(driver, timeout=10).until(
            EC.title_is("Example Domain")
        )
  6. Require save_screenshot() to return True for the collision-safe PNG path.
        if not driver.save_screenshot(str(output_file)):
            raise RuntimeError("Selenium did not save the screenshot")
  7. Quit the Chrome session from a finally block.
    finally:
        driver.quit()

Prove the PNG survived session cleanup:

  1. Reject a retained file without a valid PNG signature after the Chrome session closes.
    png_bytes = output_file.read_bytes()
    if len(png_bytes) < 24 or png_bytes[:8] != b"\x89PNG\r\n\x1a\n":
        raise RuntimeError("The retained file is not a valid PNG")
  2. Reject retained PNG dimensions that differ from the selected viewport.
    width, height = unpack(">II", png_bytes[16:24])
    if (width, height) != viewport:
        raise RuntimeError(
            f"Expected {viewport[0]} x {viewport[1]}, got {width} x {height}"
        )
     
    print(f"retained: {output_file}")
    print(f"png bytes: {len(png_bytes)}")
    print(f"png dimensions: {width} x {height}")
  3. Run capture_screenshot.py to verify the retained PNG.
    $ python3 capture_screenshot.py
    retained: artifacts/example-home-8f667723547b416996c12e8a957d19f2.png
    png bytes: 17117
    png dimensions: 1280 x 720