Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Capture the screenshot in your test framework’s failure path, before WebDriver teardown calls quit(). In Python, call driver.save_screenshot(path) while the driver session is still alive. In Java, use TakesScreenshot.getScreenshotAs(...). Treat screenshot capture as secondary reporting: if it fails, record that fact without replacing the exception that caused the test to fail.
Why timing matters after a failed command
A Selenium command failure does not guarantee that the browser session is still usable. The command may have failed because an element was missing, a wait expired, a navigation timed out, or the remote browser endpoint disappeared. Selenium’s screenshot APIs depend on an active WebDriver session, so the reliable place to capture evidence is the framework’s failure-reporting hook, before teardown closes the session.
Do not put the screenshot call only after driver.quit(), and do not assume every failed command leaves a capturable page. If the browser process or remote session has already ended, the screenshot can fail as well.
- Preserve the original assertion or WebDriver exception as the test failure.
- Wrap the screenshot operation in its own error handling.
- Use an absolute or deliberately constructed artifact path.
- Make filenames unique when tests run concurrently or retry.
Python: save a PNG directly from WebDriver
Selenium’s Python WebDriver exposes save_screenshot(filename) and get_screenshot_as_file(filename). Both save the current window as a PNG and return False when the file operation fails. The API also provides PNG bytes and a base64 representation when your test reporter accepts attachments instead of files.
#1 Best Overall
A minimal failure-safe helper
from pathlib import Path
def save_failure_screenshot(driver, path="artifacts/failure.png"):
output = Path(path)
output.parent.mkdir(parents=True, exist_ok=True)
try:
saved = driver.save_screenshot(str(output))
except Exception as screenshot_error:
# Keep the original test exception; report this separately.
print(f"Screenshot capture raised an error: {screenshot_error}")
return None
if not saved:
print(f"Could not save screenshot to {output}")
return None
return output
Call the helper from the failure branch while driver still exists:
def test_checkout(driver):
try:
driver.get("https://example.test/checkout")
driver.find_element("id", "pay-now").click()
assert "Receipt" in driver.title
except Exception:
save_failure_screenshot(driver, "artifacts/checkout-failure.png")
raise
The raise is important. It re-raises the original exception after the diagnostic attempt, so a failed screenshot does not make a passing test or hide the real defect.
Use bytes or base64 for report attachments
When a CI system, JUnit-style reporter, or custom dashboard accepts binary attachments, use get_screenshot_as_png() or get_screenshot_as_base64() instead of writing a file yourself. The same lifecycle rule applies: obtain the data before teardown, and handle capture errors independently.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
try:
png_bytes = driver.get_screenshot_as_png()
report.attach("failure.png", png_bytes, "image/png")
except Exception as screenshot_error:
report.log(f"Screenshot unavailable: {screenshot_error}")
raise
pytest-selenium: persist the plugin screenshot extra
pytest-selenium can place a screenshot in the report’s debug extras. If you are not using the plugin’s HTML report, its documented pytest_selenium_capture_debug(item, report, extra) hook lets you decode the base64 screenshot and write a PNG.
Rank #2
import base64
from pathlib import Path
def pytest_selenium_capture_debug(item, report, extra):
for entry in extra:
if entry["name"] != "Screenshot":
continue
content = base64.b64decode(entry["content"].encode("utf-8"))
path = Path("artifacts") / f"{item.name}.png"
path.parent.mkdir(parents=True, exist_ok=True)
path.write_bytes(content)
The example uses the test name as the filename. In parallel execution, add a worker, run, retry, or timestamp component so two tests cannot overwrite each other. Also confirm the hook signature against the pytest-selenium version installed in your project; the current documentation is labeled “latest,” while the available crawl information is old.
Collision-resistant pytest filenames
import os
import re
def artifact_name(item):
worker = os.getenv("PYTEST_XDIST_WORKER", "local")
safe = re.sub(r"[^A-Za-z0-9_.-]+", "_", item.nodeid)
return f"{worker}-{safe}.png"
Use that name in the hook when your suite runs with xdist or another parallel runner. Keep artifacts grouped by build and test run so a retry does not silently replace the first failure.
Java Selenium: use TakesScreenshot
The Selenium Java API exposes getScreenshotAs(OutputType<X>). The 4.28.0 reference documents file and base64 output types and states that the method can throw WebDriverException when capture fails.
Free tools Windows power users keep installed
One-click scans. No signup required.
Save a file without masking the original failure
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException;
public final class FailureScreenshot {
public static void save(WebDriver driver, Path destination) {
try {
Files.createDirectories(destination.getParent());
File temporary = ((TakesScreenshot) driver)
.getScreenshotAs(OutputType.FILE);
Files.copy(temporary.toPath(), destination,
StandardCopyOption.REPLACE_EXISTING);
} catch (WebDriverException e) {
System.err.println("WebDriver screenshot failed: " + e.getMessage());
} catch (Exception e) {
System.err.println("Screenshot file operation failed: " + e.getMessage());
}
}
}
Invoke this method from your JUnit, TestNG, or custom listener before the driver is quit. Match the API reference to the Selenium version used by your build rather than copying imports blindly between major versions.
Rank #3
Base64 output for an attachment
try {
String image = ((TakesScreenshot) driver)
.getScreenshotAs(OutputType.BASE64);
report.attachBase64("failure", image, "image/png");
} catch (WebDriverException captureError) {
report.log("Screenshot unavailable: " + captureError.getMessage());
}
Framework-specific alternatives
Selenide
Selenide documents automatic screenshots for certain failed checks and integrations with JUnit 4, TestNG, and JUnit 5. If you use Selenide, configure its report folder and framework integration rather than adding a second capture hook that may run after the browser has been closed. Verify which failures your Selenide version captures automatically.
Custom runners and remote grids
For a custom runner, place capture in the same callback that records the failure, immediately before teardown. With a remote driver, a network interruption can make both the failed command and the screenshot request unavailable. Logging the secondary capture error is still useful because it distinguishes “the page was not captured” from “the page was captured and saved.”
What the screenshot actually contains
save_screenshot and TakesScreenshot capture the current browser window or viewport exposed by the driver. They do not automatically prove that the entire document, every lazy-loaded image, or a previous page state was visible. If the failure occurred during navigation, the image may show a partially loaded page, an error document, or the last stable browser state. That is diagnostic evidence, not a replay of every command that ran.
Capture any additional state your diagnosis needs—URL, title, current command, browser logs, and the exception traceback—in the same failure record. Keep those records together so the PNG is interpretable.
Rank #4
Common failure modes and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
save_screenshot returns False |
Destination directory is missing or the process cannot write there. | Create the parent directory, use a full path, and check CI workspace permissions. |
Java throws WebDriverException |
The browser session, driver, or remote endpoint is no longer available. | Record the capture error, preserve the original failure, and inspect session or grid logs. |
| No file appears after a failed test | Capture runs after teardown, or the failure bypasses the hook. | Move capture into the framework’s failure callback and verify that callback executes for the failing test type. |
| Parallel tests overwrite images | Filenames contain only the test name. | Add worker, run, retry, and/or a unique identifier to the path. |
| The PNG shows a blank or half-loaded page | The failure happened during navigation or before rendering completed. | Save URL, title, logs, and the exception alongside the image; do not interpret the screenshot as a complete page trace. |
| The screenshot error replaces the assertion error | The reporting code raised its own exception. | Catch screenshot and file errors separately, log them, then re-raise the original test exception. |
Reliability, performance, and security considerations
Keep capture out of the success path
A screenshot is most valuable on failure. Capturing every successful step adds file I/O and storage without improving failure diagnosis. If you need checkpoints, make them explicit and retain only the states your debugging policy requires.
Use deterministic artifact retention
CI jobs should publish the artifact directory even when the test process exits nonzero. Apply retention limits and ensure that retries use separate paths. A screenshot can contain account details, tokens rendered in a page, customer data, or internal URLs; protect it with the same access controls and retention rules as logs and video.
Do not wait until teardown
Many fixtures quit the driver in a finalizer regardless of whether the test failed. Register the failure hook before that finalizer runs. If your framework’s lifecycle is unclear, create a deliberately failing test and confirm that the PNG is produced while the browser remains open.
Or skip the browser setup
If your requirement is simply to obtain a clean image of a URL rather than preserve the exact state of a Selenium session, ScreenshotNeo provides a website screenshot API and MCP server. One GET request returns PNG, JPEG, WebP, or a PDF. It accepts cookie and consent banners before capture, removes more than 60 known consent platforms plus newsletter popups and chat widgets, and reports whether a response was billed. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed.
See the ScreenshotNeo documentation for request options. A minimal cURL request is:
Best Value
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)
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}`);
ScreenshotNeo also offers full-page capture, element selectors, dark mode, device presets, custom viewports, retina scale, PDF settings, custom CSS and JavaScript, pre-capture clicks, hidden selectors, selector or network-idle waits, request blocking, headers, cookies, user agents, authorization, timezone and geolocation, transparent backgrounds, resizing, configurable-TTL caching, signed image links, asynchronous jobs with signed webhooks, bulk capture for up to 100 URLs per call, a usage API, and an OpenAPI specification. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.
The Free plan includes 1,000 screenshots per month without a card. Paid plans start at $5 for 3,000 shots; every feature is included on every plan. If you want URL screenshots without maintaining a browser setup, sign up for the free ScreenshotNeo plan.
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallOutdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchFrequently Asked Questions
Can a failed Selenium command be retried before taking the screenshot?
Only if your test design explicitly retries the operation. Capture the first failure before retrying so the original browser state is not lost, and store each attempt under a different artifact name.
Should screenshot artifacts be treated like production data?
Yes. The image may expose authenticated pages or personal information, so restrict access and apply the same retention and deletion policy used for test logs.
Quick Recap
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.

