Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

A WebDriver connection that disappears during a screenshot is usually a symptom, not the root cause. Classify the failure first: a synchronization race, a browser or driver process exit, a page/script timeout, a local file-write error, or a remote transport problem. Then apply the fix for that class. The sequence below isolates each layer without hiding failures behind longer timeouts.

Classify the failure before changing code

Save the complete exception, WebDriver command, URL, session ID and timestamp. The exact wording points to a different layer:

Symptom Likely layer First check
timeout while loading or executing script Page or script timing Configured timeout and an explicit readiness condition
get_screenshot_as_file() returns False Screenshot-file I/O Absolute path, directory permissions and free disk space
Connection reset, disconnected, or session deleted Browser/driver process or transport Driver and browser logs; whether the browser process exited
Failure only on a grid or remote host Remote endpoint/network Compare with a local run and inspect server/network logs

Do not treat all four as “the screenshot is flaky.” A file permission error does not require a new browser session, while a crashed browser cannot be repaired by changing the output filename.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

1. Stabilize the page state with an explicit wait

Selenium identifies poor synchronization as its most common error source. A screenshot command can arrive while a framework is replacing the DOM, an overlay is covering the target, or lazy content is still being inserted. Replace fixed sleeps with a bounded wait for the condition that makes your particular capture valid.

Wait for the element or state you will capture

Examples include the target element becoming visible, a loading overlay becoming invisible, or a known application state appearing. Keep implicit waits disabled when using explicit waits; mixing the two can produce unpredictable timeout behavior.

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
from pathlib import Path

out = Path("/tmp/shots").resolve()
out.mkdir(parents=True, exist_ok=True)

options = webdriver.ChromeOptions()
# options.add_argument("--headless=new")  # enable when appropriate for your environment
driver = webdriver.Chrome(options=options)
driver.implicitly_wait(0)
driver.set_page_load_timeout(45)
driver.set_script_timeout(30)

try:
    driver.get("https://example.com/dashboard")
    wait = WebDriverWait(driver, 20, poll_frequency=0.2)
    wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "main.dashboard")))
    wait.until(EC.invisibility_of_element_located((By.CSS_SELECTOR, ".loading-overlay")))

    path = out / "dashboard.png"
    ok = driver.get_screenshot_as_file(str(path))
    if not ok:
        raise OSError(f"WebDriver could not write {path}")
finally:
    driver.quit()

When the wait expires, log the current URL, the selector/state you were waiting for, browser console output and the driver log. That evidence distinguishes a page that never reached readiness from a browser that vanished.

Why a sleep is not a reliable substitute

A fixed delay is either too short on a busy CI host or unnecessarily long on a fast run. It also says nothing about whether a navigation actually completed. Use a sleep only for a documented animation or debounce interval, and still verify the resulting DOM condition.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

2. Verify browser, driver and Selenium identity

Record these values for every failing job:

  • Browser name, exact version and channel.
  • Driver name and exact version.
  • Selenium binding version.
  • Operating system, architecture and whether the run is local, containerized or remote.
  • The executable paths actually selected by the test process.

ChromeDriver is a standalone server implementing WebDriver and WebDriver BiDi. Current Chrome for Testing channels distribute browser and driver binaries. An unexpected executable earlier on PATH, or a browser/driver channel mismatch, can cause the browser to exit while the client is sending a screenshot command.

Turn on verbose logs

Configure Selenium service logging and retain the resulting files as CI artifacts. Look for the browser launch command, the binary path, capability negotiation and the last command before the process exit. If the log shows a new session was never established, investigate startup; if it ends immediately before the screenshot, investigate a crash or resource limit.

Test another supported browser

Run the same minimal reproducer with another installed browser. If only one browser fails, focus on that browser’s binary, profile, flags and driver. If all browsers fail at the same point, the page synchronization, host resources or remote transport is more likely.

3. Reproduce browser startup outside WebDriver

Use the exact browser binary and user identity from the failing test environment. Launch it directly with the same headless/display and container settings, then open the target URL. Preserve stderr and browser logs. This separates a browser startup crash from a WebDriver protocol problem.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Linux and container checks

  • Confirm the test is not running Chrome as root. ChromeDriver documents root execution on Linux as a common startup-crash cause.
  • Compare the CI user, sandbox configuration, installed browser path and headless flags with a successful local run.
  • Check shared-memory capacity, process and file-descriptor limits, and whether the container is killing the browser for memory.
  • Keep the browser and driver logs when a process exits so a crash is not mistaken for a network reset.

The --no-sandbox flag is an unsupported, highly discouraged workaround. Configure a regular, non-privileged user and correct the container instead.

4. Separate timeout errors from screenshot-file errors

Set page-load and script timeouts for the application rather than increasing every timeout after a failure. A slow navigation, a script that never resolves, a browser crash and an unwritable PNG path are different incidents.

Use an absolute, writable destination

Create the directory before the test and check the screenshot API’s return value. In Selenium’s Python API, get_screenshot_as_file() (also exposed as save_screenshot()) returns False for an I/O failure. Ignoring that boolean can make a local file problem look like a lost session.

from pathlib import Path

path = Path("artifacts") / "run-42.png"
path.parent.mkdir(parents=True, exist_ok=True)
path = path.resolve()

if not driver.get_screenshot_as_file(str(path)):
    raise RuntimeError(f"Screenshot write failed: {path}")
if not path.is_file() or path.stat().st_size == 0:
    raise RuntimeError(f"Screenshot is missing or empty: {path}")

Check directory ownership, read-only mounts, disk quota and available space. A successful WebDriver command followed by a missing file is an I/O diagnosis, not evidence that ChromeDriver disconnected.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

5. Treat remote execution as a separate layer

WebDriver can control a local browser or a browser on another machine through Selenium Server. A remote run adds endpoint authentication, firewalls, proxies, network latency and server health to the browser and file layers.

Use a local-versus-remote comparison

  1. Run the minimal test locally with the same URL and wait condition.
  2. Run it against the remote endpoint with server and network logs enabled.
  3. Compare command latency, session lifetime, browser process logs and screenshot handling.
  4. Change one variable at a time: endpoint, browser version, host or wait condition.

If local succeeds and remote fails, inspect endpoint reachability, idle timeouts, proxy resets and server-side browser exits. If both fail, return to synchronization, binary alignment and host resources.

Secure the endpoint

Firewall the WebDriver endpoint, restrict allowed IP addresses, use a protected network and run tests with a non-privileged account. Do not expose an unauthenticated driver service to the public internet. A managed browser grid may reduce maintenance when local infrastructure is the dominant source of failures, but it does not remove the need to diagnose page readiness and file handling.

A repeatable diagnostic sequence

  1. Save the full exception, command, URL, session ID and timestamp.
  2. Enable Selenium, driver and browser logs and preserve them with the test artifact.
  3. Replace sleeps with an explicit wait for the screenshot’s readiness condition; keep implicit waits off.
  4. Print browser, driver, Selenium, OS, architecture and executable-path details.
  5. Launch the exact browser binary directly in the same environment.
  6. Check root execution, sandbox/container restrictions, shared memory and process exits.
  7. Confirm page-load/script timeout values and an absolute writable PNG path; check the screenshot return value.
  8. Compare another supported browser and local versus remote execution.
  9. After classification, change one variable at a time and retain the smallest reproducer that still fails.

Common failure patterns and targeted fixes

“Session deleted” immediately after navigation

Read the driver log for a browser process exit. Verify binary versions, launch the same binary directly, and inspect root/container and memory conditions. Do not add retries until the process remains alive.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

“Connection reset” only under load

Compare command latency and host resource usage with a single-worker run. Reduce concurrency temporarily, inspect shared memory and file descriptors, and check whether a remote proxy or server idle limit closes the connection.

Screenshot intermittently captures a blank or half-rendered page

The session may be healthy; the page is not ready. Wait for the target element and for loading overlays or known skeleton states to disappear. Capture the URL and DOM state when the wait times out.

Method reports failure but the session remains usable

Check the boolean result and absolute path, then inspect permissions, mount mode and free disk space. This is a file-write failure unless a subsequent WebDriver command also reports a disconnected session.

Only the remote grid fails

Run locally, then compare endpoint logs, network path, server health and browser lifetime. Protect the endpoint and verify that the remote host uses the intended browser and driver binaries.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

For production captures, ScreenshotNeo provides a single HTTP request instead of maintaining Selenium, browser binaries and driver sessions. Cookie and consent banners are accepted and removed before capture, along with 60+ known consent platforms, newsletter popups and chat widgets; each step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads and cache hits cost nothing, and the response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP server lets Claude, Cursor and other MCP clients call take_screenshot, get_page_info and capture_pdf.

The API supports full-page captures with lazy images loaded, CSS-selector element shots, dark mode, 12 device presets or custom viewports, retina scale, PDF paper sizes/margins/landscape/page ranges, HTML/CSS rendering, custom JavaScript and CSS, clicks, selector waits, delays, network-idle waits, request/resource blocking, headers, cookies, user agents, Authorization, timezone, geolocation, transparent backgrounds, resizing, TTL caching, signed image links, asynchronous jobs with signed webhooks, bulk capture of 100 URLs per call, a usage API and an OpenAPI specification. Common parameter names used by other screenshot APIs are accepted to ease migration.

cURL

See the ScreenshotNeo documentation for authentication and options.

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

Python

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)

Node.js

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`${res.status} ${res.statusText}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));

There is a free allowance of 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots; every feature is on every plan. Create a free ScreenshotNeo account to try the API.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Reliability, performance and cost decisions

  • Retries: retry only classified transient failures, such as a remote transport reset. Reusing a dead session will not fix a browser crash; create a new session and preserve the original logs.
  • Parallelism: increase workers only after measuring browser memory, shared memory, CPU and file-descriptor limits. More sessions can turn a stable test into repeated process exits.
  • Readiness: a precise wait is usually faster than a generous global timeout because it captures as soon as the required state exists.
  • Observability: store command timing, session ID, URL, versions, paths, verdicts and logs with each artifact.
  • Remote trade-off: remote execution centralizes browsers but adds network and endpoint failure modes; local execution removes transport dependence but leaves binary and host maintenance to you.

Frequently Asked Questions

Should I restart the driver after every screenshot?

No. Keep a session for related captures while it remains healthy. Start a new session only after logs show a browser or driver process exit, or after the session is explicitly invalid.

Can increasing the screenshot timeout fix a disconnected session?

Usually not. A timeout controls waiting for a page or script; a disconnected or deleted session indicates process or transport failure. Classify the exception first.

Why does a screenshot work locally but fail in CI?

CI often changes the user, browser path, sandbox/container settings, shared-memory limits and available resources. Launch the exact CI browser directly and compare its logs and versions with the local run.

Is a blank screenshot proof that WebDriver disconnected?

No. It can mean the page was captured before its content became ready. Wait for a target DOM condition and inspect the session separately from the image file.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.