Back to Blog

Selenium Screenshot Guide: Code Examples (2026)

By MorganPublished May 13, 202610 min read

# Selenium Screenshot Guide: Capture Pages, Elements & Failures

To take a Selenium screenshot, cast the driver to TakesScreenshot and call getScreenshotAs(OutputType.FILE) in Java, driver.save_screenshot("shot.png") in Python, or driver.takeScreenshot() in JavaScript. Selenium 4 supports element-level captures and (in some browsers) full-page captures via the Chrome DevTools Protocol.

Selenium WebDriver is the right pick for legacy test suites. It also fits cross-browser runs on BrowserStack or Sauce Labs, and polyglot teams mixing Java, Python, .NET, and Ruby. Newer tools like Playwright and Puppeteer are faster. But Selenium still owns the cross-language story and ships Safari support out of the box. This guide walks through every screenshot operation you'll need. Code in three languages, plus the gotchas QA engineers hit in production.

Setup matrix: install Selenium for your stack

LanguageInstallDriver
Pythonpip install seleniumBuilt-in via Selenium Manager (4.10+)
Node.jsnpm install selenium-webdriverBuilt-in or npm i chromedriver
JavaMaven: org.seleniumhq.selenium:selenium-java:4.xBuilt-in
.NETdotnet add package Selenium.WebDriverBuilt-in
Rubygem install selenium-webdriverBuilt-in

Selenium 4.10 and later ship with Selenium Manager. It grabs the right Chrome, Firefox, Edge, or Safari driver for your browser. You no longer need webdriver-manager packages. You also don't have to pin ChromeDriver versions by hand. See the official Selenium docs for the full setup matrix.

Page screenshot: viewport capture in three languages

The default Selenium screenshot is a viewport capture. It grabs only what the user sees, not the full scrollable page.

Python:

from selenium import webdriver

driver = webdriver.Chrome()
driver.get("https://example.com")
driver.save_screenshot("page.png")
driver.quit()

Java:

import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import java.io.File;
import java.nio.file.Files;

WebDriver driver = new ChromeDriver();
driver.get("https://example.com");
File src = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
Files.copy(src.toPath(), new File("page.png").toPath());
driver.quit();

JavaScript (Node):

const { Builder } = require('selenium-webdriver');
const fs = require('fs');

const driver = await new Builder().forBrowser('chrome').build();
await driver.get('https://example.com');
const png = await driver.takeScreenshot();
fs.writeFileSync('page.png', png, 'base64');
await driver.quit();

That's the bread-and-butter call. Each binding wraps the same WebDriver protocol endpoint under the hood.

Element screenshot: capture a single component

Selenium 4 added native element screenshots, so you can crop straight to a specific button, card, or chart without post-processing.

# Python
header = driver.find_element("css selector", "h1.hero-title")
header.screenshot("hero.png")
// Java
WebElement header = driver.findElement(By.cssSelector("h1.hero-title"));
File src = header.getScreenshotAs(OutputType.FILE);
Files.copy(src.toPath(), new File("hero.png").toPath());
// JavaScript
const header = await driver.findElement(By.css('h1.hero-title'));
const png = await header.takeScreenshot();
fs.writeFileSync('hero.png', png, 'base64');

Element screenshots are pixel-precise. They respect the element's own padding and border. They're the cleanest way to feed component-level images into a visual diff tool.

Save as base64, byte array, or file

Often you don't want a file on disk. You might attach the image to a test report. Or embed it in an HTML email. Or push it to S3 directly.

# Python — base64 string
b64 = driver.get_screenshot_as_base64()

# Python — raw bytes
png_bytes = driver.get_screenshot_as_png()
// Java — file, bytes, or base64
File file = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
byte[] bytes = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
String b64 = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BASE64);
// JavaScript — base64 by default
const b64 = await driver.takeScreenshot();
const buf = Buffer.from(b64, 'base64');

Selenium only emits PNG. There's no native option for JPEG or WebP. Need a smaller format? Encode the PNG bytes through Pillow (Python) or sharp (Node) after capture.

The full-page caveat: Selenium's biggest gap

Diagram showing Selenium's scroll-and-stitch full-page screenshot workaround
Diagram showing Selenium's scroll-and-stitch full-page screenshot workaround

Here's where Selenium falls behind Playwright and Puppeteer. Selenium WebDriver has no one-line full-page API that works everywhere. The viewport is all you get by default.

You have three workarounds:

1. Firefox-only native API. Selenium 4 added getFullPageScreenshotAs() for the Firefox driver:

// Firefox only
File src = ((FirefoxDriver) driver).getFullPageScreenshotAs(OutputType.FILE);

If you're already standardized on Firefox for screenshot tests, this is the cleanest path.

2. Headless Chrome + window resize. Resize the window to match body.scrollHeight. Then take a regular screenshot. Chrome captures the full document because everything fits in the viewport.

total_height = driver.execute_script("return document.body.scrollHeight")
driver.set_window_size(1280, total_height)
driver.save_screenshot("fullpage.png")

This works in headless mode. But it breaks for fixed headers and lazy-loaded images. Scroll the page first if your site loads images on scroll.

3. Chrome DevTools Protocol (CDP). In Selenium 4, you can call CDP commands directly:

result = driver.execute_cdp_cmd(
    "Page.captureScreenshot",
    {"captureBeyondViewport": True, "fromSurface": True}
)
import base64
with open("fullpage.png", "wb") as f:
    f.write(base64.b64decode(result["data"]))

CDP is the most reliable approach. But it locks you to Chromium-based browsers. Pick whichever workaround matches your browser matrix.

ScreenSnap Pro
Sponsored by the makers

Tired of plain screenshots? Try ScreenSnap Pro.

Beautiful backgrounds, pro annotations, GIF recording, and instant cloud sharing — all in one app. Pay $29 once, own it forever.

See what it does

Visual regression testing with Selenium

Visual regression test comparing two screenshots with pixel diff highlights
Visual regression test comparing two screenshots with pixel diff highlights

Selenium has no built-in image diffing. You'll pair it with one of three tools: Applitools, Percy, or an open-source library like pixelmatch.

Applitools wraps the screenshot call so you don't manage baselines by hand:

Eyes eyes = new Eyes();
eyes.setApiKey(System.getenv("APPLITOOLS_API_KEY"));
eyes.open(driver, "MyApp", "Login Page Test");
eyes.checkWindow("Login form");
eyes.close();

Percy uses a similar pattern in JavaScript:

const percySnapshot = require('@percy/selenium-webdriver');
await percySnapshot(driver, 'Login page');

For a deeper look at frameworks and diff strategies, see our guide on visual regression testing. Pick a managed service when speed of setup matters more than cost. Pick pixelmatch when you want zero fees and don't mind wiring the diff loop yourself.

Common gotchas every QA hits

A few production traps catch teams over and over.

Wait before you capture. A screenshot taken before the page renders is just a blank canvas. Wrap captures with WebDriverWait:

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

WebDriverWait(driver, 10).until(
    EC.presence_of_element_located((By.CSS_SELECTOR, ".product-card"))
)
driver.save_screenshot("loaded.png")

Use the new headless mode. In Chrome 109 and later, the old --headless flag is out of date. Use --headless=new:

options = webdriver.ChromeOptions()
options.add_argument("--headless=new")
options.add_argument("--window-size=1920,1080")

The new headless mode uses the same rendering pipeline as headed Chrome. Your screenshots match what users see.

Use absolute paths in CI. Relative paths break in Docker and GitHub Actions runners. The working directory shifts. Resolve paths up front:

import os
out = os.path.join(os.getcwd(), "artifacts", "page.png")
driver.save_screenshot(out)

Watch zoom and DPI. Browser zoom and high-DPI displays change screenshot dimensions. Force a fixed window size and pin the device scale factor. That gives you byte-equal screenshots in CI:

options.add_argument("--force-device-scale-factor=1")
options.add_argument("--window-size=1280,720")

Capture on test failure. This is the highest-value pattern. Hook the failure path of your test framework. Every red build then leaves a screenshot artifact. In pytest:

import pytest

@pytest.fixture(autouse=True)
def screenshot_on_failure(request, driver):
    yield
    if request.node.rep_call.failed:
        driver.save_screenshot(f"failures/{request.node.name}.png")

In TestNG (Java), implement ITestListener.onTestFailure and call getScreenshotAs from there.

Selenium vs Playwright vs Puppeteer for screenshots

Comparison of Selenium, Playwright, and Puppeteer screenshot features
Comparison of Selenium, Playwright, and Puppeteer screenshot features

Each tool has a different sweet spot:

FeatureSeleniumPlaywrightPuppeteer
LanguagesJava, Python, JS, .NET, RubyJS, Python, Java, .NETJS only
Full-page screenshotWorkaroundsNative, one lineNative, one line
Element screenshotYes (Selenium 4)YesYes
JPEG / quality controlNo (PNG only)YesYes
Safari supportYes (SafariDriver)Yes (WebKit)No
SpeedSlowerFasterFaster

Selenium is older and slower. But it has the broadest language support and the only out-of-the-box Safari driver. If your team writes Java tests today, Selenium is still the path of least resistance. For a side-by-side breakdown of the two newer tools, see Puppeteer vs Playwright. Our best screenshot APIs roundup covers hosted services that can replace WebDriver for simpler jobs.

For ad-hoc desktop screenshots while you're debugging, ScreenSnap Pro offers region capture, annotation, and instant cloud links on Mac and Windows. Test code stays in Selenium. Quick "send this to a teammate" captures stay in a desktop app.

CI/CD example: Selenium on GitHub Actions

Here's a working GitHub Actions workflow that runs Selenium with ChromeDriver and uploads any screenshot artifacts on failure:

GitHub Actions running Selenium tests with Chrome and Firefox
GitHub Actions running Selenium tests with Chrome and Firefox
name: Selenium Tests
on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.12'
      - name: Install dependencies
        run: pip install selenium pytest
      - name: Run tests
        run: pytest tests/ --tb=short
      - name: Upload screenshots
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: screenshots
          path: failures/

Ubuntu runners ship with Chrome preinstalled. Selenium Manager picks the matching ChromeDriver. The if: always() clause uploads screenshots even when tests fail. That's exactly when you want them. The Selenium GitHub repository has more sample workflows in its docs.

Frequently Asked Questions

Wrapping up

Selenium isn't the fastest tool for screenshots. But it's the most flexible across languages and browsers. Three patterns to remember. Cast to TakesScreenshot for raw captures. Call element.screenshot() for component-level images. Lean on CDP or Firefox's native API when you need full-page output. Pair it with a diff tool for visual regression. Now you have a full pipeline from capture to artifact.

For the desktop side of your workflow, ScreenSnap Pro handles ad-hoc captures with annotation and one-click cloud sharing. No test framework needed. It's a $29 one-time purchase for Mac and Windows.

Author
Morgan

Morgan

Indie Developer

Indie developer, founder of ScreenSnap Pro. A decade of shipping consumer Mac apps and developer tools. Read full bio

@m_0_r_g_a_n_
ScreenSnap Pro — turn plain screenshots into polished visuals with backgrounds and annotations
Available formacOS&Windows

Make every screenshot look pro.

ScreenSnap Pro turns plain screenshots into polished visuals — backgrounds, annotations, GIF recording, and instant cloud links.

See ScreenSnap Pro