ScreenshotNeo

BlogHow-to

Selenium Screenshot Examples: Capture and Save a Browser Screenshot

Learn how to capture Selenium screenshots in Python and Java, save files, capture elements or full pages, troubleshoot failures, and automate reliably.

By the ScreenshotNeo team29 September 20269 min read

Selenium Screenshot Examples: Capture and Save a Browser Screenshot

Selenium can capture the current browser window as a PNG, return the image in memory, or capture a supported element. In Python, the shortest reliable pattern is driver.save_screenshot("artifacts/example.png"). Create the destination directory first, check the Boolean return value, and always quit the driver in a finally block.

from pathlib import Path
from selenium import webdriver

out = Path("artifacts")
out.mkdir(parents=True, exist_ok=True)

driver = webdriver.Chrome()
try:
    driver.get("https://example.com")
    ok = driver.save_screenshot(str(out / "example.png"))
    if not ok:
        raise OSError("Selenium could not write the screenshot")
finally:
    driver.quit()

This guide explains the equivalent APIs in Python and Java, the difference between viewport, element, and full-page captures, and the failure modes that appear in CI. The examples use official Selenium APIs; behavior can vary by browser and driver.

1. Install Selenium and a browser driver

Install the language binding and make a compatible browser available. Recent Selenium releases can manage drivers automatically in many environments, but a locked-down CI image may still require an explicitly installed driver.

Python

python -m pip install selenium

Use a supported Chrome, Chromium, Firefox, or another WebDriver-compatible browser. The Python API documents save_screenshot(filename) and get_screenshot_as_file(filename) as PNG file operations. The filename should end in .png. See the Selenium Python API documentation.

Java

Add the Selenium Java dependency to Maven or Gradle. With Maven:

<dependency>
  <groupId>org.seleniumhq.selenium</groupId>
  <artifactId>selenium-java</artifactId>
  <version>4.35.0</version>
</dependency>

Use a dependency version approved by your project. The Java API exposes screenshots through TakesScreenshot; its contract applies to drivers and, where supported, WebElements. See the Java TakesScreenshot API.

2. Capture and save a viewport screenshot in Python

save_screenshot captures the current browser context, usually the visible viewport. It returns True when the file is saved and False for an I/O failure. Use an absolute or deliberately controlled relative path so CI artifacts are easy to find.

A stable screenshot flow waits for page state before writing the image.
A stable screenshot flow waits for page state before writing the image.
from pathlib import Path
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

output = Path("artifacts")
output.mkdir(exist_ok=True)

options = Options()
# options.add_argument("--headless=new")  # useful on CI
options.add_argument("--window-size=1440,1000")

driver = webdriver.Chrome(options=options)
try:
    driver.get("https://example.com")
    filename = output / "homepage.png"
    if not driver.save_screenshot(str(filename)):
        raise OSError(f"Screenshot was not written: {filename}")
    print(filename.resolve())
finally:
    driver.quit()

get_screenshot_as_file is the file-oriented alternative:

ok = driver.get_screenshot_as_file("artifacts/homepage.png")
if not ok:
    raise OSError("Screenshot save failed")

Get PNG bytes or Base64 instead of writing a file

png_bytes = driver.get_screenshot_as_png()
Path("artifacts/from-bytes.png").write_bytes(png_bytes)

base64_png = driver.get_screenshot_as_base64()
html = f'<img alt="capture" src="data:image/png;base64,{base64_png}">'
Path("artifacts/preview.html").write_text(html, encoding="utf-8")

Bytes are useful when uploading directly to object storage or attaching evidence to a test report. Base64 is convenient for embedding in HTML, but it increases the size of the text payload.

3. Capture and save a screenshot in Java

Java uses TakesScreenshot and an OutputType. The file returned by the driver is temporary, so copy it to a path owned by your test or application.

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;

public class SaveScreenshot {
  public static void main(String[] args) throws Exception {
    Path output = Path.of("artifacts");
    Files.createDirectories(output);

    WebDriver driver = new ChromeDriver();
    try {
      driver.get("https://example.com");
      File source = ((TakesScreenshot) driver)
          .getScreenshotAs(OutputType.FILE);
      Files.copy(source.toPath(), output.resolve("example.png"),
          StandardCopyOption.REPLACE_EXISTING);
    } finally {
      driver.quit();
    }
  }
}

For in-memory output, request OutputType.BYTES or OutputType.BASE64:

byte[] png = ((TakesScreenshot) driver)
    .getScreenshotAs(OutputType.BYTES);
Files.write(Path.of("artifacts", "bytes.png"), png);

String base64 = ((TakesScreenshot) driver)
    .getScreenshotAs(OutputType.BASE64);

4. Capture one element instead of the whole viewport

Element screenshots are useful for a component visual test, a chart, or a receipt. Find the element after the page has rendered, then call the binding’s element screenshot method when the driver and element implement the screenshot contract.

Python

from selenium.webdriver.common.by import By

card = driver.find_element(By.CSS_SELECTOR, "main .pricing-card")
card.screenshot("artifacts/pricing-card.png")

Java

import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;

WebElement card = driver.findElement(By.cssSelector("main .pricing-card"));
File source = card.getScreenshotAs(OutputType.FILE);
Files.copy(source.toPath(), Path.of("artifacts", "pricing-card.png"),
    StandardCopyOption.REPLACE_EXISTING);

Wait for the element to exist and be displayed before capturing it. A hidden element, a zero-size element, or a selector that matches the wrong responsive variant can produce an exception or an unexpected image.

5. Capture a full-page screenshot

A normal screenshot represents the current window or visible browser context. Full-document capture is a separate capability and is driver-specific. Firefox’s Python WebDriver API documents get_full_page_screenshot_as_file("artifacts/full.png").

Full-page capture is a separate, driver-specific capability.
Full-page capture is a separate, driver-specific capability.
from selenium import webdriver

firefox = webdriver.Firefox()
try:
    firefox.get("https://example.com/long-page")
    firefox.get_full_page_screenshot_as_file("artifacts/full.png")
finally:
    firefox.quit()

Do not assume that the same full-page method works identically in every browser. If your driver lacks a native implementation, common alternatives are scrolling and stitching viewport images, using a browser-specific DevTools command, or changing the capture tool. Stitching needs care around fixed headers, sticky elements, animations, and lazy-loaded content.

6. Make captures deterministic

Most screenshot differences come from page state rather than the save call. Apply these controls before capture:

  1. Set the viewport. Use a fixed window size or driver window dimensions.
  2. Wait for a meaningful condition. Prefer an explicit element or state over a blind sleep.
  3. Disable motion. Inject CSS that sets animation and transition durations to zero when visual stability matters.
  4. Control data. Seed test data and use a predictable account, locale, and timezone.
  5. Wait for fonts and images. A screenshot taken while fonts swap or images decode can differ between runs.
  6. Close overlays. Cookie dialogs, chat launchers, and promotional modals can cover the target.
from selenium.webdriver.support.ui import WebDriverWait

wait = WebDriverWait(driver, 20)
hero = wait.until(lambda d: d.find_element("css selector", "main"))
wait.until(lambda d: hero.is_displayed())
driver.execute_script("""
  const style = document.createElement('style');
  style.textContent = `*, *::before, *::after {
    animation-duration: 0s !important;
    animation-delay: 0s !important;
    transition-duration: 0s !important;
    caret-color: transparent !important;
  }`;
  document.head.appendChild(style);
""")
driver.save_screenshot("artifacts/stable.png")

7. Choose the right output and capture scope

Need Recommended API Notes
Visible browser state save_screenshot / getScreenshotAs(FILE) Captures the current window or viewport.
Upload without a temporary file get_screenshot_as_png / OutputType.BYTES Keep the bytes in memory and send them to storage.
Embed in an HTML report Base64 output Convenient, but larger than a binary file.
One component Element screenshot Requires driver and element support.
Entire document Driver-specific full-page API Firefox documents a dedicated Python method; support differs by driver.

8. Troubleshooting Selenium screenshots

“Screenshot was not written” or a false return value

Cause: The directory does not exist, the process lacks write permission, or the path points to a read-only workspace.
Fix: Create the directory with mkdir or Files.createDirectories, use a writable absolute path, and check the Boolean result.

WebDriverException or a blank image

Cause: Browser and driver versions are incompatible, the page has not rendered, or the capture occurs during navigation.
Fix: Align browser and driver versions, wait for a stable selector, and capture after navigation completes. Save the page URL and browser logs alongside the image.

Element screenshot fails with “element not interactable”

Cause: The element is hidden, has zero dimensions, is outside a responsive layout, or is covered by an overlay.
Fix: Wait for visibility, verify its bounding rectangle with JavaScript, close overlays, and set a viewport where the element is displayed.

The image is clipped

Cause: A regular screenshot only covers the current window. It does not automatically include content below the fold.
Fix: Use a supported full-page method, or scroll and stitch images with explicit handling for fixed-position elements.

Text or images change between runs

Cause: Web fonts, lazy loading, animation, ads, timestamps, randomized content, or network timing.
Fix: Wait for the required resources, freeze animation, block or mock volatile content in a test environment, and use deterministic data.

Works locally but fails in CI

Cause: Missing display support, different fonts, a smaller default viewport, sandbox restrictions, or a different working directory.
Fix: Use headless mode configured for your browser, set the window size explicitly, install required fonts, create artifact directories, and publish screenshots on failure.

9. Performance, reliability, and cost considerations

Selenium starts a browser and loads the page for every session, so startup and network time usually dominate the file-writing call. Reuse a driver for related captures when isolation rules permit, but reset cookies, local storage, and navigation state between tests. Parallel sessions can reduce wall-clock time while increasing CPU, memory, and network pressure; size concurrency for the CI worker rather than assuming unlimited scaling.

For reliable visual comparisons, keep browser versions, fonts, viewport dimensions, device scale, locale, timezone, and test data stable. Store the URL, commit identifier, browser version, and capture timestamp as metadata. Retry navigation failures only when the failure is transient; retries can hide real regressions if every failed screenshot is silently replaced.

Selenium itself does not charge per screenshot. Your costs are the machines, CI minutes, browser containers, bandwidth, and any external test infrastructure. The official API references do not publish a universal screenshot timing or success-rate benchmark, so measure your own pages and environment.

10. Or skip the browser setup

ScreenshotNeo provides a website screenshot API when you want an HTTP request instead of managing WebDriver. Its API accepts one GET request and returns PNG, JPEG, WebP, or PDF output. Full-page capture, element selectors, dark mode, device presets, custom CSS and JavaScript, waits, request blocking, headers, cookies, user agents, geolocation, resizing, caching, signed links, asynchronous jobs, bulk capture, and PDF options are available through the documented parameters.

cURL:

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}`);

See the ScreenshotNeo documentation for all parameters. Consent banners are accepted and more than 60 known consent platforms, newsletter popups, and chat widgets are removed before capture; each step can be disabled. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and the response reports the result with X-Page-Verdict and X-Billed headers. An MCP server exposes take_screenshot, get_page_info, and capture_pdf for 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 screenshots.

Start with 1,000 free screenshots per month.

11. Frequently asked questions

Does Selenium save screenshots as JPEG?

The documented Selenium file APIs save PNG screenshots. Convert the resulting bytes with an image library if another format is required.

Can I take a screenshot before calling quit?

Yes. Capture inside the try block and call quit in finally so the browser closes even when saving fails.

Why should I check the Python return value?

save_screenshot and get_screenshot_as_file return a Boolean that indicates whether the file operation succeeded. Checking it turns a missing artifact into an immediate, diagnosable error.

Is full-page capture standardized across browsers?

No. Full-document screenshot support is driver-specific. Verify the API for the browser you run in production and keep a fallback for other drivers.

Can an element produce a screenshot in every driver?

No. Element capture depends on the driver and element implementing the screenshot contract. Test the exact browser and driver combination used by your suite.