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.

In Selenium Python, open the page and call driver.save_screenshot("screenshot.png"). It writes a PNG of the current browser window and returns True when the file is saved or False when an IOError prevents the write. Use a valid path ending in .png, then quit the driver when your automation is finished.

Save a Selenium screenshot to a PNG file

This is the smallest complete Selenium example:

from selenium import webdriver


driver = webdriver.Chrome()
driver.get("https://example.com")

saved = driver.save_screenshot("screenshot.png")
if not saved:
    raise IOError("Selenium could not write screenshot.png")

driver.quit()

save_screenshot(filename) saves the current window to a PNG image file. A relative name writes beside the process’s current working directory; use an absolute path when a test runner, container, or scheduled job must place the file predictably.

Install Selenium and prepare the browser

Install the Python package in the environment that will run the test:

python -m pip install -U selenium

The machine also needs a supported browser. Selenium 4 can manage the matching driver in common setups; if your environment controls drivers itself, ensure the driver executable is available before creating webdriver.Chrome(). A driver that cannot start is a setup failure, not a screenshot failure.

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

Use a deterministic destination

Create the destination directory before the call and include a test-specific filename. Selenium reports only whether the write operation succeeded; it does not create missing parent directories for you.

from pathlib import Path
from selenium import webdriver


out = Path("artifacts")
out.mkdir(parents=True, exist_ok=True)
path = out / "home-page.png"

driver = webdriver.Chrome()
try:
    driver.get("https://example.com")
    if not driver.save_screenshot(str(path)):
        raise IOError(f"Screenshot was not saved: {path}")
finally:
    driver.quit()

The finally block closes the browser even if navigation or file writing raises an exception.

Choose the output form your code needs

Selenium exposes the same capture in three useful forms. Select the form that matches the next operation instead of writing a temporary file unnecessarily.

Method Result Best use
driver.save_screenshot("shot.png") PNG file and a Boolean success value Test artifacts, CI attachments, or local review
driver.get_screenshot_as_file("shot.png") PNG file and the same success behavior Codebases using Selenium’s documented alias
driver.get_screenshot_as_png() PNG bytes Upload to object storage, attach to a report, or process in memory
driver.get_screenshot_as_base64() Base64-encoded text Embedding the image in HTML or a JSON payload

Save bytes without a temporary file

from selenium import webdriver


driver = webdriver.Chrome()
try:
    driver.get("https://example.com")
    png_bytes = driver.get_screenshot_as_png()
    with open("screenshot.png", "wb") as image_file:
        image_file.write(png_bytes)
finally:
    driver.quit()

Opening the destination with "wb" is essential: PNG data is binary. The bytes can instead be passed directly to an HTTP client, a test-report attachment API, or an image library.

Free tools Windows power users keep installed

One-click scans. No signup required.

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

Use base64 in an HTML image

from selenium import webdriver


driver = webdriver.Chrome()
try:
    driver.get("https://example.com")
    encoded = driver.get_screenshot_as_base64()
    html = f'<img alt="Selenium capture" src="data:image/png;base64,{encoded}">'
    with open("report.html", "w", encoding="utf-8") as report:
        report.write(html)
finally:
    driver.quit()

Capture one element instead of the whole window

Find a WebElement, then call its screenshot method:

from selenium import webdriver
from selenium.webdriver.common.by import By


driver = webdriver.Chrome()
try:
    driver.get("https://example.com")
    heading = driver.find_element(By.CSS_SELECTOR, "h1")
    if not heading.screenshot("heading.png"):
        raise IOError("Element screenshot was not saved")
finally:
    driver.quit()

The element must exist in the loaded document. Use an explicit wait when the page renders the target asynchronously, otherwise the lookup can fail before the element appears.

from selenium.webdriver.support.ui import WebDriverWait

heading = WebDriverWait(driver, 10).until(
    lambda browser: browser.find_element(By.CSS_SELECTOR, "h1")
)
heading.screenshot("heading.png")

What Selenium does—and does not—capture

Current window is the documented scope

The Python method is documented as a screenshot of the current window. Do not assume that save_screenshot automatically produces a complete, vertically stitched image of a long page. If you need a full-page artifact, you must use a browser- or driver-specific full-page capability, resize and capture deliberately, or implement a scrolling and stitching workflow; the ordinary Python method description alone does not promise that result.

Driver and browser differences

Selenium’s Java TakesScreenshot API also supports drivers and web elements. W3C-conformant implementations follow the WebDriver specification. For a non-conformant implementation, the documented fallback is best effort and can represent the entire page, current window, a visible frame, or the display depending on the browser and driver. Treat that fallback as implementation-dependent rather than a portable full-page guarantee.

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

Wait for the state you want to preserve

A screenshot records the browser state at the instant of the call. Navigate first, wait for the relevant element or application state, perform any required click or form interaction, and only then capture. If fonts, images, or client-rendered content arrive later, an early capture will faithfully show the incomplete state.

Reliable screenshot patterns for tests and automation

Capture on failure while preserving the original exception

from pathlib import Path
from selenium import webdriver


artifact_dir = Path("artifacts")
artifact_dir.mkdir(exist_ok=True)
driver = webdriver.Chrome()
try:
    driver.get("https://example.com")
    # assertions and test steps go here
except Exception:
    driver.save_screenshot(str(artifact_dir / "failure.png"))
    raise
finally:
    driver.quit()

Use unique names when tests run in parallel, such as a test identifier plus a timestamp or worker number. Otherwise concurrent workers can overwrite one another.

Check both Selenium’s result and the filesystem

A True return indicates that Selenium completed its file-saving operation. For build systems that require a non-empty artifact, additionally check that the path exists and has a positive size after the call.

from pathlib import Path

path = Path("screenshot.png")
if not driver.save_screenshot(str(path)) or not path.is_file() or path.stat().st_size == 0:
    raise RuntimeError("Screenshot artifact is missing or empty")

Keep the capture inexpensive

  • Capture only at meaningful checkpoints or on failure instead of every assertion.
  • Prefer bytes when an uploader accepts bytes, avoiding a disk write and read.
  • Keep browser sessions alive for a test flow, but always close them in a finally block.
  • Use deterministic names and separate artifact directories for parallel workers.

Troubleshoot common failures

WebDriverException while creating the driver

Cause: The browser is missing, the driver cannot start, or the driver and browser are incompatible. Fix: install a supported browser, update Selenium and the driver-management setup used by your environment, and run a minimal navigation before adding screenshot logic.

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

The method returns False or raises an IOError

Cause: The destination is not writable, a parent directory is absent, or the path is invalid. Fix: create the directory, use an absolute path, verify permissions, and check the Boolean return value. On Windows, use a raw string or pathlib.Path so backslashes are not interpreted as escapes.

The file exists but shows the wrong page or an incomplete layout

Cause: The capture ran before navigation, a redirect finished, an element appeared, or client-side rendering completed. Fix: wait for a URL, selector, or application condition that represents the ready state, then capture. Avoid arbitrary sleeps when a condition can be observed.

An element screenshot cannot find the element

Cause: The selector is wrong, the element is inside a frame, or it has not been rendered yet. Fix: switch into the correct frame when applicable, verify the selector in browser developer tools, and use WebDriverWait for its presence or visibility.

The image is not full page

Cause: The ordinary Python driver call targets the current window. Fix: choose a documented full-page feature for your specific browser and driver, or build a scroll-and-stitch process; do not label the ordinary result as full page.

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

Parallel tests overwrite screenshots

Cause: Workers share the same filename. Fix: include the test name, worker identifier, and a unique run value in each path, and publish each worker’s artifact directory separately.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server for developers. One GET request returns a PNG, JPEG, WebP, or PDF. It accepts cookie and consent banners before capture, removes more than 60 known consent platforms plus newsletter popups and chat widgets, and lets you turn each cleanup step off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed; every response identifies the page verdict and billing status in X-Page-Verdict and X-Billed headers.

The basic call is:

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 all parameters. The same request in Python is:

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(`ScreenshotNeo HTTP ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));

Options that replace custom Selenium plumbing

  • Full-page capture with lazy images loaded, or one element selected by CSS.
  • Dark mode, 12 device presets, arbitrary viewports, and retina scale.
  • PDF paper size, margins, landscape mode, and page ranges.
  • Custom CSS and JavaScript, a click before capture, hidden selectors, and waits for a selector, delay, or network idle.
  • Blocking for ads, trackers, requests, or resource types; custom headers, cookies, user agent, Authorization, timezone, and geolocation.
  • Transparent backgrounds, image resizing, chosen cache TTLs, signed links for public <img> tags, asynchronous jobs with signed webhooks, bulk capture for up to 100 URLs per call, usage reporting, and an OpenAPI specification.

An MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients, so an AI agent can request captures without you wiring a browser session. ScreenshotNeo also accepts parameter names used by other screenshot APIs, which can reduce migration work.

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

Cost and billing

Plan Included shots per month Price
Free 1,000 $0, no card
Starter 3,000 $5
Growth 15,000 $15
Pro 60,000 $39
Scale 250,000 $99
Business 1,000,000 $249

Yearly billing provides two months free, and every feature is available on every plan. Create a free ScreenshotNeo account to get 1,000 screenshots a month with no card.

Which approach should you use?

  • Use Selenium when the screenshot is part of an end-to-end browser test that already needs clicks, assertions, authentication, or JavaScript state.
  • Use Selenium element screenshots when the artifact is a component such as a chart, form, or heading rather than the viewport.
  • Use ScreenshotNeo when you need repeatable URL-to-image or PDF jobs, consent and popup cleanup, asynchronous or bulk capture, or an MCP workflow without maintaining browser drivers.

Frequently Asked Questions

Does saving a screenshot end the Selenium session?

No. The screenshot methods return after capturing; the browser remains available for additional navigation and assertions. Call driver.quit() when the complete automation flow is finished.

Can I keep a screenshot in memory for an upload?

Yes. Use driver.get_screenshot_as_png() and pass the returned bytes to the upload client instead of writing a local PNG first.

Why is a PNG filename recommended?

The documented Selenium file methods save PNG images. Give the path a .png extension so the artifact type is explicit to tools and reviewers.

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

The Bottom Line

For Selenium Python, call driver.save_screenshot("screenshot.png"), check its Boolean result, and close the driver in a finally block. Use element, bytes, or base64 methods when your output needs differ; choose a dedicated screenshot API when browser setup and page cleanup are the work you are trying to avoid.

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.