Free tools Windows power users keep installed
One-click scans. No signup required.
In Python, the shortest Selenium screenshot workflow is to create a WebDriver, open a URL, call driver.save_screenshot("screenshot.png"), check the Boolean result, and close the session with driver.quit(). The method captures the current browser window as a PNG; it does not automatically guarantee a full-page image.
This guide builds that minimal script into a reliable workflow: setup, repeatable viewport sizing, element captures, in-memory output, waits, failure handling, and alternatives when running a browser is unnecessary.
What you need before writing the script
Selenium WebDriver controls a real browser through a language binding, a browser, and the browser’s driver implementation. This article uses Python. Install the Selenium package in the environment where the script will run, and consider using an isolated Python virtual environment. Current Selenium Manager support generally finds and manages a compatible driver when you instantiate a supported browser WebDriver. Older installations may still require manual driver configuration.
- A supported Python installation and the Selenium Python binding.
- A browser such as Chrome, with permission to launch it.
- A writable destination for the image file.
Run the script in an environment where the browser can display a window, or configure the browser for the headless mode appropriate to your deployment. Headless operation is useful on servers, but rendering can differ from a desktop session.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →#1 Best Overall
The minimal Python screenshot script
from selenium import webdriver
# Selenium Manager can generally find/manage the browser driver
# for supported browser and platform combinations.
driver = webdriver.Chrome()
try:
driver.get("https://example.com")
saved = driver.save_screenshot("screenshot.png")
if not saved:
raise OSError("Selenium could not save screenshot.png")
finally:
driver.quit()
save_screenshot() writes a PNG of the current browsing context and returns True when the save succeeds. A False result indicates an I/O failure, so checking it is worthwhile when a missing image would break a build or test. Supplying an absolute path removes ambiguity about the process’s current working directory.
What each line does
webdriver.Chrome()starts a Chrome WebDriver session.driver.get()navigates to the target URL and waits for the navigation command to complete.save_screenshot()captures the current browser window to a PNG file.- The
finallyblock callsquit()even if navigation or saving raises an exception, releasing the browser and driver process.
Make captures repeatable
Responsive layouts change with the browser’s viewport. Set a known window size before navigation or capture when screenshots will be compared between runs.
from selenium import webdriver
options = webdriver.ChromeOptions()
# options.add_argument("--headless=new") # enable when your deployment needs it
driver = webdriver.Chrome(options=options)
try:
driver.set_window_size(1440, 1000)
driver.get("https://example.com")
if not driver.save_screenshot("artifacts/example-1440.png"):
raise OSError("Screenshot was not written")
finally:
driver.quit()
Matching width and height does not make images pixel-identical. Browser and operating-system versions, installed fonts, device scale, animations, clocks, network responses, and other dynamic content can still change pixels. Use a consistent runtime and page state when visual differences matter.
Wait for the page state you actually want
A navigation command is not a guarantee that every image, chart, font, or JavaScript component has finished rendering. Prefer an explicit condition for the content that must appear, rather than an arbitrary long sleep.
Rank #2
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
driver = webdriver.Chrome()
try:
driver.get("https://example.com/dashboard")
WebDriverWait(driver, 20).until(
EC.visibility_of_element_located((By.CSS_SELECTOR, "main.dashboard"))
)
if not driver.save_screenshot("dashboard.png"):
raise OSError("Could not save dashboard.png")
finally:
driver.quit()
Use a short, deliberate delay only for a known animation or delayed asset, and document why it is needed. For lazy-loaded pages, scroll or wait for the relevant element before capturing. A screenshot records what is rendered at that instant; it does not force below-the-fold content to load.
Capture one element instead of the whole window
When you need a card, logo, chart, or component, locate its WebElement and call its screenshot method.
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
driver = webdriver.Chrome()
try:
driver.get("https://example.com")
card = WebDriverWait(driver, 20).until(
EC.visibility_of_element_located((By.CSS_SELECTOR, ".pricing-card"))
)
if not card.screenshot("pricing-card.png"):
raise OSError("Could not save the element screenshot")
finally:
driver.quit()
Element capture is different from a window capture: the output is limited to the element’s rendered bounds. Keep the selector stable; a class generated at runtime can make the script fail after a redesign.
Choose a file, bytes, or Base64 output
| Method | Result | Use it when |
|---|---|---|
driver.save_screenshot(path) |
PNG written to disk; Boolean success value | You need an artifact for review, CI, or archival |
driver.get_screenshot_as_png() |
Raw PNG bytes | You will upload, hash, transform, or test the image in memory |
driver.get_screenshot_as_base64() |
Base64-encoded PNG data | You need to embed the image in HTML or transmit text data |
png_bytes = driver.get_screenshot_as_png()
with open("screenshot.png", "wb") as image_file:
image_file.write(png_bytes)
base64_png = driver.get_screenshot_as_base64()'
These methods capture the current window. For a complete page taller than the viewport, do not assume the basic call will stitch the page. A full-page result requires browser-specific behavior or a separate scrolling/stitching strategy, each of which can introduce seams, sticky-header duplication, and lazy-loading issues.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Useful variations for real scripts
Use a deterministic output path
Create an artifacts directory before starting and include a timestamp, test name, or URL slug in the filename. Avoid relative paths when a CI runner may choose a different working directory.
Capture after an interaction
from selenium.webdriver.common.by import By
button = driver.find_element(By.CSS_SELECTOR, "button.more-details")
button.click()
# Wait for the expanded panel here, then capture.
driver.save_screenshot("after-click.png")
Do not capture immediately after a click if the page updates asynchronously. Wait for the panel’s visible state or for an old element to become stale and a new one to appear.
Run multiple URLs safely
from pathlib import Path
from urllib.parse import urlparse
from selenium import webdriver
urls = ["https://example.com", "https://example.org"]
out = Path("screenshots")
out.mkdir(exist_ok=True)
driver = webdriver.Chrome()
try:
for url in urls:
driver.get(url)
host = urlparse(url).netloc.replace(":", "_")
path = out / f"{host}.png"
if not driver.save_screenshot(str(path)):
raise OSError(f"Failed to save {path}")
finally:
driver.quit()
One browser session is efficient for a small sequence, but isolate tests when cookies, local storage, authentication, or page state could leak from one URL to another.
Common failures and fixes
The browser or driver will not start
- Cause: The browser is missing, blocked by policy, or the driver cannot match it.
- Fix: Confirm the browser launches for the same user, update the Selenium package and browser together, and review Selenium Manager’s startup error. On older setups, verify the driver executable path manually.
The file is not where expected
- Cause: A relative path is resolved from the process’s current directory, not necessarily the script’s directory.
- Fix: Print or construct an absolute path, ensure the parent directory exists, and check the Boolean return value.
The screenshot is blank or incomplete
- Cause: Capture occurred before the app rendered, content is lazy-loaded, or a navigation error page is being shown.
- Fix: Wait for a meaningful element, verify the URL and page text, scroll to trigger lazy loading when appropriate, and capture again.
An element screenshot raises a lookup or visibility error
- Cause: The selector is wrong, the element is inside an iframe, it has not appeared, or it is hidden.
- Fix: Switch into the correct iframe, use an explicit wait, verify the selector in browser developer tools, and capture only after the element is visible.
Images differ between runs
- Cause: Viewport, fonts, browser version, device scale, animations, time, or remote data changed.
- Fix: Standardize window size and runtime, disable or wait out animations where your test permits, and make test data deterministic. Identical dimensions alone are not a pixel-perfect guarantee.
The script hangs or leaves processes behind
- Cause: An unbounded wait or an exception that bypasses cleanup.
- Fix: Give explicit waits a timeout and keep browser creation inside a
try/finallyblock soquit()always runs.
Performance, reliability, and security notes
- Browser startup is usually the expensive part of a one-shot capture. Reuse a session for a controlled batch, but reset state when isolation is required.
- Set timeouts for page loads and explicit waits so a broken site cannot hold a worker forever.
- Store screenshots as build artifacts with retention limits; images can contain personal data, tokens displayed in the UI, or private customer information.
- Do not place credentials in URLs or source code. Use the browser profile, cookies, or authentication mechanism appropriate to your test environment, and protect resulting files.
- Headless and headed browsers can render differently. Validate the mode used in production rather than assuming a desktop capture will match.
Or skip the browser setup
If your job is simply to obtain a clean website image, ScreenshotNeo provides a website screenshot API and MCP server. One GET request returns PNG, JPEG, WebP, or a PDF, without you managing WebDriver.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
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 documentation for parameters and response details. The same request in 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)
And in 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}`);
- Cookie and consent banners, newsletter popups, and chat widgets are removed before the shot; each cleanup step can be turned off.
- Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed as clean shots. Response headers identify the page verdict and billing status.
- An MCP server provides
take_screenshot,get_page_info, andcapture_pdftools for Claude, Cursor, and other MCP clients. - There are 1,000 free shots each month with no card required. Paid plans start at $5 for 3,000 shots; every feature is available on every plan.
Create a free ScreenshotNeo account to try the 1,000 monthly shots without a card.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.FAQ
Does Selenium save screenshots as PNG?
Yes. Python’s save_screenshot(), get_screenshot_as_png(), and Base64 screenshot method represent PNG output.
Can I take a screenshot before calling driver.quit()?
Yes. Capture while the session is active, then call quit() in cleanup so the browser process closes even after an error.
Recommended Free Tools
Is an element screenshot the same as a full-page screenshot?
No. An element screenshot is limited to one located WebElement, while a driver screenshot covers the current browser window.
Best Value
Frequently Asked Questions
Can Selenium capture a screenshot of a PDF viewer or browser chrome?
WebDriver screenshots describe the web page’s current browsing context, not the operating system desktop or browser’s address bar and other chrome.
Should I use PNG, JPEG, or WebP with Selenium’s built-in method?
The Python WebDriver screenshot methods documented here produce PNG data. Choose another format only after saving and converting the image with a separate image-processing step or service.
How do I prove a screenshot came from the expected page?
Record the requested URL, final URL, viewport size, timestamp, and a page marker such as a heading alongside the image, then fail the job if the marker is absent.
The Bottom Line
For a Python Selenium script, use driver.get(), wait for the state you need, call driver.save_screenshot(path) or an element’s screenshot(path), check the result, and always quit the driver. Standardize the viewport and runtime when image consistency matters.
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.




