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.
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"
options = Options() options.add_argument("--headless=new")
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
driver = webdriver.Chrome(service=service, options=options) try:
driver.execute_cdp_cmd( "Emulation.setDeviceMetricsOverride", { "width": viewport[0], "height": viewport[1], "deviceScaleFactor": 1, "mobile": False, }, )
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
WebDriverWait(driver, timeout=10).until( EC.title_is("Example Domain") )
if not driver.save_screenshot(str(output_file)): raise RuntimeError("Selenium did not save the screenshot")
finally: driver.quit()
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")
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}")
$ python3 capture_screenshot.py retained: artifacts/example-home-8f667723547b416996c12e8a957d19f2.png png bytes: 17117 png dimensions: 1280 x 720