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

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Capture the image with ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE), create your destination directory, and copy the returned temporary file to a name you control. OutputType.FILE is not a permanent archive: Selenium deletes that temporary file when the JVM exits, so the copy is the step that preserves it.

Working Java example

The following helper creates the folder if necessary, captures the current WebDriver browsing context, and copies the result to a durable path. It uses the Apache Commons IO class shown in Selenium’s Java documentation.

import org.apache.commons.io.FileUtils;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public final class ScreenshotHelper {
    private ScreenshotHelper() {}

    public static Path saveScreenshot(WebDriver driver, String destination)
            throws IOException {
        Path target = Paths.get(destination);
        Path parent = target.getParent();
        if (parent != null) {
            Files.createDirectories(parent);
        }

        File temporary = ((TakesScreenshot) driver)
                .getScreenshotAs(OutputType.FILE);
        File permanent = target.toFile();
        FileUtils.copyFile(temporary, permanent);
        return target;
    }
}

Use it after the page has reached the state you want to record:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
WebDriver driver = /* create ChromeDriver, FirefoxDriver, EdgeDriver, SafariDriver, or another driver */;
try {
    driver.get("https://example.com");
    ScreenshotHelper.saveScreenshot(driver, "screenshots/result.png");
} finally {
    driver.quit();
}

A relative path such as screenshots/result.png is resolved from the Java process’s working directory. Pass an absolute path when a test runner, CI service, or IDE may use a different working directory. The method declares IOException; callers can catch it, add a test failure, or let their framework report it.

What the Selenium call returns

TakesScreenshot indicates that a driver can capture screenshots in different representations. Selenium documents this capability for WebDriver implementations including ChromeDriver, EdgeDriver, FirefoxDriver, SafariDriver, and RemoteWebDriver. The exact visible extent is governed by the driver’s WebDriver implementation. Conformant implementations follow the W3C WebDriver specification; non-conformant implementations may use a best-effort fallback, so do not assume identical dimensions across browsers.

Output representation choices

Output type Returned value Use it when
OutputType.FILE A temporary File You want Selenium’s documented copy-to-path workflow. Copy it before the JVM exits.
OutputType.BYTES Raw screenshot bytes Your application writes to a stream, object store, database, or custom file API.
OutputType.BASE64 A Base64-encoded string An API, message, or report requires encoded image data instead of a binary file.

The output type changes how your code persists the capture; it does not make a temporary FILE permanent by itself.

Writing bytes without Commons IO

If your project already uses Java NIO, request bytes and write them directly. This avoids adding a copy utility dependency while retaining the same directory and error handling:

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.
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public static Path saveScreenshotBytes(WebDriver driver, String destination)
        throws IOException {
    Path target = Paths.get(destination);
    Path parent = target.getParent();
    if (parent != null) {
        Files.createDirectories(parent);
    }
    byte[] image = ((TakesScreenshot) driver)
            .getScreenshotAs(OutputType.BYTES);
    Files.write(target, image);
    return target;
}

Choose one approach per call. The Commons IO version mirrors Selenium’s example; the NIO version gives you direct control over the byte write.

Saving an element instead of the whole browsing context

For a screenshot of one supported WebElement, call the screenshot method on that element and copy the returned temporary file in the same way:

import org.apache.commons.io.FileUtils;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.WebElement;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public static Path saveElementScreenshot(WebElement element, String destination)
        throws IOException {
    Path target = Paths.get(destination);
    Path parent = target.getParent();
    if (parent != null) {
        Files.createDirectories(parent);
    }
    File temporary = element.getScreenshotAs(OutputType.FILE);
    FileUtils.copyFile(temporary, target.toFile());
    return target;
}

This is distinct from driver.getScreenshotAs(...): the former asks the element for its rendered image, while the latter captures the current browsing context. The same filesystem rules apply.

Directory, naming, and test-suite practices

Create directories before copying

Files.createDirectories is idempotent: it creates missing parent directories and does nothing when they already exist. Without that step, a destination such as artifacts/login/failure.png fails if either parent directory is absent.

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

Use collision-resistant names

Parallel tests can overwrite a fixed filename. Include a test name, a short unique identifier, and an image extension, for example artifacts/checkout/checkout-failure-7f3a.png. If the same path is intentionally reused, coordinate writers or serialize the capture.

Capture at the right point

Take the screenshot after navigation, waits, and any required interaction have completed. A successful API call can still produce an image of an intermediate loading state if your test captures too early. Keep the driver alive until the copy finishes; quitting the session first can make the capture or file operation fail.

Remote and CI execution

With RemoteWebDriver, the screenshot request is sent to the remote browser and the returned representation is transferred to the Java process. The destination directory therefore belongs to the machine running your Java test code, not necessarily the machine hosting the browser. In CI, publish that directory as an artifact after the test step, and use an absolute workspace path when the runner changes its working directory.

Common failures and fixes

Symptom Likely cause Fix
ClassCastException at the capture line The driver object does not implement TakesScreenshot. Use a Selenium driver implementation that supports screenshots, or check capability before casting. Do not cast an unrelated driver type.
FileNotFoundException or “No such file or directory” during copy The parent folder does not exist, or the process lacks permission. Call Files.createDirectories(parent), verify the resolved path, and grant the test process write access.
IOException while copying The temporary file disappeared, the destination is locked, or storage is unavailable. Copy immediately after getScreenshotAs; avoid reusing a path concurrently; check free space and filesystem permissions.
An image is blank or shows a loading page Capture occurred before the required page state was ready. Wait for the relevant element or navigation condition in your test, then capture. The screenshot API does not decide when your application is ready.
Different browsers produce different image extents Driver implementations can differ; non-conformant implementations use best-effort behavior. Define browser-specific expectations, keep driver/browser versions compatible, and assert only the dimensions your test actually requires.
The file exists during the run but is missing later OutputType.FILE was treated as the final destination. Copy it to your own path (or use BYTES and write the bytes). The Selenium temporary file is deleted when the JVM exits.
Element capture fails while full-page capture works The selected element is not available or the driver does not support element screenshots in that context. Locate the element after the page state is ready and handle the driver’s documented support and fallback behavior.

Keeping screenshot capture reliable and affordable

Separate evidence from test logic

Put directory creation, naming, and exception handling in one helper. Test methods then call one line and can attach the returned path to their reports. This also gives you one place to change from Commons IO to NIO or to add retention rules.

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

Control storage growth

Screenshots are binary artifacts. Save them for failures or explicitly marked checkpoints rather than every polling loop, and apply your CI system’s retention policy. A deterministic directory layout makes cleanup and artifact upload predictable.

Do not confuse a successful HTTP or WebDriver command with a useful image

The API can complete while the page is blank, blocked, or still rendering. Record the page URL and test step alongside the file name so a later reviewer can distinguish a browser problem from an application-state problem.

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

Or skip the browser setup

If you need a URL image rather than a browser session you maintain, ScreenshotNeo provides a GET endpoint and an MCP server for AI agents. It accepts consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each cleanup step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers.

See the ScreenshotNeo API documentation for the complete option list. The one-call examples below use the supplied endpoint and target URL:

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

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

ScreenshotNeo also supports full-page captures with lazy images loaded, CSS-selector element capture, dark mode, device presets and custom viewports, retina scale, PDF output, custom CSS and JavaScript, clicks before capture, selector or network-idle waits, request and resource blocking, headers, cookies, user agents, authorization, timezone and geolocation, transparent backgrounds, resizing, selectable caching TTLs, signed image links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, a usage API, and an OpenAPI specification. Parameter names used by other screenshot APIs are accepted to ease migration.

An MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients. Every feature is included on every plan. The Free plan includes 1,000 screenshots each month without a card; paid plans start at $5 for 3,000 screenshots, with yearly billing providing two months free.

Create a free ScreenshotNeo account to get the 1,000 monthly screenshots without adding a card.

Frequently Asked Questions

Where is a relative screenshot path created?

It is created under the Java process’s current working directory. Use an absolute path when your IDE, build tool, or CI runner may start the process elsewhere.

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

Can the same helper support both full-page and element captures?

Yes. Keep the filesystem code shared, but invoke getScreenshotAs on the WebDriver for the browsing context or on the target WebElement for an element image.

The Bottom Line

Use getScreenshotAs, create the destination directory, and copy the temporary result to your own path. That copy—not the Selenium temporary file—is the durable screenshot your Java build can archive.

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.