ScreenshotNeo

BlogHow-to

How to Capture Screenshots in Selenium with Chrome

Capture a Chrome window or element with Selenium, save it as a PNG, or return image data for processing. Includes runnable Python examples and fixes for common errors.

By the ScreenshotNeo team29 September 202610 min read

How to Capture Screenshots in Selenium with Chrome

Selenium can capture the current Chrome window and save it as a PNG with driver.save_screenshot("screenshot.png"). Navigate to the page first, check the method’s Boolean return value if file-write failures matter, and close the WebDriver session when you are done. For a single component, use the element’s screenshot method instead. The documented driver screenshot is for the current browsing context; this method alone does not establish a full-page capture.

1. Install Selenium and capture a Chrome window

Install Selenium in the Python environment that will run the script:

Selenium navigates the browser first, then saves the current window as a PNG.
Selenium navigates the browser first, then saves the current window as a PNG.
python -m pip install selenium

Then save the following as capture.py and run it with python capture.py:

from selenium import webdriver


driver = webdriver.Chrome()
try:
    driver.get("https://example.com")
    saved = driver.save_screenshot("screenshot.png")
    if not saved:
        raise OSError("Could not save screenshot")
finally:
    driver.quit()

This opens Chrome through Selenium, navigates to the example page, writes screenshot.png in the process’s current working directory, checks whether the save succeeded, and shuts down the browser even if an earlier step raises an error. Selenium’s official example follows the same sequence: create a Chrome driver, navigate, save a screenshot, then quit. See Selenium’s WebDriver examples.

save_screenshot(path) writes the current window as PNG. Use a full path if you need the output in a known location, and use a .png extension. The API documents a Boolean result: True on success and False for an I/O error. See the Selenium Python Chromium WebDriver API.

Choose an output path deliberately

A relative filename is resolved from the process’s working directory, which can differ when the script runs from an IDE, scheduled job, test runner, or container. Use an absolute path to make the destination explicit:

from pathlib import Path
from selenium import webdriver

output = Path("artifacts") / "screenshot.png"
output.parent.mkdir(parents=True, exist_ok=True)

driver = webdriver.Chrome()
try:
    driver.get("https://example.com")
    if not driver.save_screenshot(str(output.resolve())):
        raise OSError(f"Could not save screenshot to {output}")
finally:
    driver.quit()

The directory creation step handles a missing artifacts folder. It does not change what Selenium captures; it only prepares the destination.

2. Wait for the page state you need

A screenshot captures the page state present when the command runs. A successful navigation does not necessarily mean that every client-side component, image, or late-loading section is ready. If the screenshot must include a particular element, wait for that element before capture:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait


driver = webdriver.Chrome()
try:
    driver.get("https://example.com")
    WebDriverWait(driver, 15).until(
        EC.visibility_of_element_located((By.CSS_SELECTOR, "main"))
    )
    if not driver.save_screenshot("screenshot.png"):
        raise OSError("Could not save screenshot")
finally:
    driver.quit()

Replace main with a selector that represents the state your task requires. The explicit wait has a finite timeout, so a missing or never-visible target fails rather than leaving a capture job waiting forever. Selenium’s screenshot API itself does not promise that a page’s asynchronous work has finished; the script must decide what “ready” means for its page.

3. Pick the screenshot scope and output form

Selenium exposes a few useful forms of screenshot output. Choose based on whether the result should be a file, image data for further processing, or a capture of one element.

Use a driver screenshot for the current window and an element screenshot for one component.
Use a driver screenshot for the current window and an element screenshot for one component.
Method Scope and result Use it when
driver.save_screenshot(path) Current window; writes a PNG file and returns a Boolean. You need an artifact on disk.
driver.get_screenshot_as_file(path) Current window; saves a PNG file and returns a Boolean. You prefer the explicit “as file” method name.
driver.get_screenshot_as_png() Current window; returns PNG bytes. You want to pass image bytes to another library or storage client.
driver.get_screenshot_as_base64() Current window; returns a Base64-encoded string. A downstream interface specifically expects encoded text, such as an HTML data URL.
element.screenshot(path) One located element; saves its screenshot to a file. You need a component rather than the whole current window.

These methods and their output forms are documented in the Python Chromium WebDriver API. WebDriver’s screenshot response is encoded in Base64 at the protocol level; Selenium’s methods provide convenient decoded or file-oriented choices. See Selenium’s screenshot documentation.

Keep the PNG in memory

Use the byte-returning method when the next step accepts bytes and you do not need an intermediate file:

from selenium import webdriver


driver = webdriver.Chrome()
try:
    driver.get("https://example.com")
    png_bytes = driver.get_screenshot_as_png()
    if not png_bytes:
        raise RuntimeError("Selenium returned an empty screenshot")

    # Example destination: write the bytes to a file.
    with open("screenshot.png", "wb") as image_file:
        image_file.write(png_bytes)
finally:
    driver.quit()

The example writes the bytes only to demonstrate that they are image data; replace that block with your image-processing or upload step. Handling the bytes directly can avoid an extra read from disk when another library accepts a byte stream.

Return Base64 when a text encoding is required

from selenium import webdriver


driver = webdriver.Chrome()
try:
    driver.get("https://example.com")
    encoded_png = driver.get_screenshot_as_base64()
    data_url = "data:image/png;base64," + encoded_png
    print(data_url)
finally:
    driver.quit()

Base64 makes binary image data representable as text, but it is larger than the original bytes. Avoid printing or logging the full string for large captures; pass it directly to the consumer that needs it.

4. Capture one element instead of the window

When the required image is a chart, card, or other single component, locate that element and call its screenshot method. Selenium documents element capture separately from the current-context screenshot.

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait


driver = webdriver.Chrome()
try:
    driver.get("https://example.com")
    chart = WebDriverWait(driver, 15).until(
        EC.visibility_of_element_located((By.CSS_SELECTOR, "#chart"))
    )
    if not chart.screenshot("chart.png"):
        raise OSError("Could not save the element screenshot")
finally:
    driver.quit()

Change #chart to the page’s actual CSS selector. Waiting for visibility before capture helps distinguish “the page loaded” from “the target component is ready.” If the selector matches no element or the element never becomes visible, investigate the page markup and wait condition before changing the screenshot call.

Element capture is the right scope when surrounding navigation, sidebars, or unrelated content should not be part of the artifact. Use a driver-level method when you want the current window. The researched Selenium references establish those scopes; they do not establish behavior for full-page capture or specific viewport dimensions.

5. Run the capture from cURL, Python, or Node.js with an API

Selenium is useful when the task depends on controlling a Chrome session. If the input is simply a URL and the desired result is an image or PDF, a screenshot API can remove the need to provision and manage a browser in your script.

cURL

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

Python

import requests

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

Node.js

const q = new URLSearchParams({
  access_key: 'YOUR_API_KEY',
  url: 'https://example.com'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await Bun.write('shot.webp', new Uint8Array(await res.arrayBuffer()));

The Node example uses Bun’s Bun.write to save the response. In a Node.js-only project, use fs/promises instead:

import { writeFile } from 'node:fs/promises';

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

See the ScreenshotNeo API documentation for request options and response details. These examples use the API’s given request shape and adapt only the target URL.

6. Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server from ScreenshotNeo. Its one-call API accepts a URL and returns a screenshot or PDF. Cookie banners, popups, and chat widgets are removed before the shot; each step can be turned off. Bot checks, blank pages, and failed loads are never billed, and responses include page-verdict and billing headers. AI agents can use its MCP server tools, including take_screenshot, get_page_info, and capture_pdf.

There are 1,000 screenshots a month on the free plan with no card. Paid plans start at $5 for 3,000 shots. Other available options include full-page capture, element selection, device and viewport settings, custom CSS and JavaScript, wait conditions, request blocking, caching, bulk capture, and signed links. Check the docs for the supported parameters and response behavior.

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

Sign up for 1,000 free screenshots a month, with no card required.

7. Troubleshooting Selenium screenshot failures

Symptom Likely cause What to check
The output file is missing. The relative path points to a different working directory, the parent folder does not exist, or the write failed. Print or inspect Path.cwd(), create the parent directory, use an absolute path, and check the Boolean result from save_screenshot.
save_screenshot returns False. The file could not be written at the requested path. Check directory permissions, whether the parent exists, and whether the destination is writable. Use a path your process can write to.
The capture is blank or missing a component. The screenshot ran before the required page state or element was ready. Wait for a meaningful visible element or condition before calling the screenshot method. Check whether the selector matches the current page.
An element screenshot fails. The locator did not identify the intended element, or it was not available in the expected state. Verify the selector against the loaded page and use an explicit wait before calling element.screenshot.
The script hangs or leaves Chrome running after an error. The session was not closed on every code path, or the script is waiting indefinitely for a page condition. Put driver.quit() in a finally block and give explicit waits a finite timeout.
The result is not a full-page image. The documented driver method captures the current window; this research does not verify a Chrome-specific full-page technique. Use the documented method only for its current-window scope, or consult current Selenium documentation for a separately supported approach before relying on one.

8. Performance, reliability, and cost

For repeated captures, reuse a browser session where the workflow permits it instead of starting Chrome for every URL. Always close the session in a finally block so a failed navigation or file write does not leave browser processes behind. Put a finite timeout around readiness checks; a page that never reaches the expected state should become a visible failure that your job runner can handle.

Choose the smallest output form that fits the next step. Save directly to a file when you need an artifact; use PNG bytes when a downstream image step accepts binary data; use Base64 only when a text encoding is required. Base64 is convenient for transport through text-only interfaces, while byte output avoids that encoding step.

The Selenium methods described here do not provide a per-capture price, hosting cost, or reliability guarantee. Your operating cost depends on where Chrome runs and how your application provisions it. For URL-to-image jobs where maintaining the browser environment is the main overhead, ScreenshotNeo offers a free tier of 1,000 shots monthly and paid plans beginning at $5 for 3,000; only clean shots are billed according to the product details above. Confirm the plan and options on the ScreenshotNeo site before integrating them into a budget.

9. FAQ

Does save_screenshot return the image?

No. It saves a PNG file and returns a Boolean indicating whether the save succeeded. Use get_screenshot_as_png() when you need PNG bytes in memory.

Can I capture only a chart or card?

Yes. Locate the target element and call its screenshot method. That captures the selected element rather than the whole current browsing context.

Does this example prove that headless Chrome behaves identically?

No. The cited material establishes the screenshot methods and their output, but it does not establish headless equivalence. Check the documentation for the Selenium and Chrome versions you deploy if headless behavior is a requirement.

Does this method capture the entire page?

The documented driver.save_screenshot behavior is a screenshot of the current window. The sources used here do not establish a Chrome-specific full-page capture method, so do not assume that this call captures content beyond the current window.

Can I embed the result in HTML?

Use get_screenshot_as_base64() when an encoded image string is useful, for example as the value after a PNG data URL prefix. Prefer bytes or a file when the consumer does not require Base64.