ScreenshotNeo

BlogHow-to

How to Take a Screenshot with Selenium and Headless Chrome in Java

Capture and save a screenshot with Selenium 4 and headless Chrome in Java, with working code, output options, troubleshooting, and a simpler API alternative.

By the ScreenshotNeo team4 October 20267 min read

Use Selenium’s TakesScreenshot interface to capture the page, request OutputType.FILE, and copy Selenium’s temporary screenshot file to a path you control. Run Chrome headlessly by adding --headless=new to ChromeOptions, and set a window size when you need repeatable viewport dimensions.

This guide uses Selenium’s Java API with ChromeDriver. The regular WebDriver screenshot is not a guaranteed full-page capture in every driver and browser configuration; confirm that behavior for your version if you need the whole scrollable document. See the official [Selenium screenshot guide](https://www.selenium.dev/documentation/webdriver/interactions/windows/) and [Chrome options documentation](https://www.selenium.dev/documentation/webdriver/browsers/chrome/).

1. Set up a Java project

Add Selenium Java to your project using your build tool, then make sure a compatible Chrome browser and ChromeDriver are available. Selenium’s current setup and driver management behavior can vary by release and environment, so check the Selenium documentation for your installed version and validate the combination in the CI image where the code will run.

Maven dependency example (replace the version with the Selenium version chosen for your project):

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

The example below is a complete Java class. Save it as ScreenshotExample.java and run it with Selenium and a working Chrome/ChromeDriver setup on the classpath.

2. Capture and save a viewport screenshot

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

import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;

public class ScreenshotExample {
    public static void main(String[] args) throws IOException {
        ChromeOptions options = new ChromeOptions();
        options.addArguments("--headless=new");
        options.addArguments("--window-size=1440,900");

        WebDriver driver = new ChromeDriver(options);
        try {
            driver.get("https://example.com");

            File temporaryScreenshot = ((TakesScreenshot) driver)
                    .getScreenshotAs(OutputType.FILE);
            Files.copy(temporaryScreenshot.toPath(), Path.of("screenshot.png"),
                    StandardCopyOption.REPLACE_EXISTING);
        } finally {
            driver.quit();
        }
    }
}

OutputType.FILE returns a temporary file. Copy it to a destination you control before relying on it as a durable artifact; Selenium documents that the temporary file is deleted when the JVM exits. The finally block closes the browser session on both success and failure.

Control the viewport

--window-size=1440,900 gives Chrome a deliberate viewport size for the capture. The resulting screenshot dimensions depend on the browser viewport and device scale configuration. Keep the viewport fixed in visual regression jobs so changes in the capture environment do not create unrelated image diffs. Chrome’s headless CLI documentation also pairs screenshot capture with --window-size.

Choose the screenshot representation

Selenium’s OutputType offers three useful forms:

Output type Use it when Handling
FILE You want a simple file-based flow. Copy the temporary file to your final path before JVM exit.
BYTES You want to write bytes with Java NIO or pass data to a storage client. Write the returned byte array to your destination.
BASE64 The receiving system accepts Base64 text. Decode or transmit the returned encoded string as required.

Byte output example:

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

Base64 output example:

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

These alternatives avoid depending on the temporary file path when your next step consumes in-memory data. Refer to the [Selenium OutputType API](https://www.selenium.dev/selenium/docs/api/java/org/openqa/selenium/OutputType.html) for the API contract.

3. Wait for the page before capturing

driver.get() waits according to the browser’s page-load strategy, but a page can continue changing after navigation completes. For dynamic content, wait for a specific element or state that indicates the content you want is ready. Avoid arbitrary sleeps when a condition can be checked directly.

import java.time.Duration;
import org.openqa.selenium.By;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

// After driver.get(url):
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(15));
wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("main")));
// Now call getScreenshotAs(...)

Use a selector that is meaningful for the target page, such as the main content container or a known result element. If the page is expected to show a consent dialog or a login wall, decide whether the screenshot should include that state or whether the test should handle it first.

4. Viewport screenshots and full-page captures

The code above captures a screenshot through WebDriver, but do not assume it always includes the entire scrollable document. The captured area and full-page behavior depend on the driver and browser implementation. If you need a full-page image, confirm the supported method for your exact Selenium and Chrome versions, or use a separately documented full-page capture mechanism.

For a stable viewport capture, specify the window size and capture after the required page state is ready. For a full-document capture, validate the final image dimensions and content in the target runtime rather than inferring full-page support from a successful screenshot call.

5. Troubleshooting

Symptom Likely cause Fix
Chrome fails to start or reports a session creation error Chrome and ChromeDriver are incompatible, the browser is missing, or the runtime cannot launch its installed browser. Check the Chrome version, Selenium version, driver resolution, and container dependencies. Reproduce in the same image used by CI.
getScreenshotAs does not compile The driver reference is not cast to TakesScreenshot, or Selenium imports/dependencies are missing. Use ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE) and verify the Selenium Java dependency and imports.
The screenshot file disappears after the program exits OutputType.FILE provides a temporary file that Selenium says is deleted when the JVM exits. Copy it to the desired path immediately, or use BYTES and write the returned array.
The image has unexpected dimensions The browser viewport differs from the intended size, or the capture environment uses different settings. Set an explicit --window-size and keep browser configuration consistent across runs.
The screenshot shows a loader or incomplete content Navigation completed before the dynamic content became ready. Wait for a target element or application-specific ready condition before capturing. Set a bounded timeout and report a useful failure if it never appears.
The image contains only the visible portion of the page The regular screenshot behavior in that driver captures a viewport rather than the entire document. Verify full-page support for the specific driver/version or use a separately documented full-page method.
The process hangs or leaves Chrome running Cleanup did not run after an exception or process termination. Keep driver.quit() in a finally block, and use job-level time limits for CI tasks.

6. Performance, reliability, and cost

  • Startup time: Browser startup is part of each new WebDriver session. Reuse a session for several captures when the pages and isolation requirements allow it; always close the session when the task is complete.
  • Waits: Wait for the state you need, not a long fixed delay. Bound waits so an unavailable page cannot stall a worker indefinitely.
  • Repeatability: Pin or deliberately manage Selenium and browser versions, keep viewport and options consistent, and run captures in a consistent environment.
  • Output handling: Use file output for straightforward local persistence; bytes can simplify writing to object storage or another API without handling a temporary file. Large images still consume memory and disk proportional to their size.
  • Cost: Selenium and Chrome are software components rather than a per-screenshot API in this example. Your infrastructure, CI minutes, storage, and maintenance have costs; no benchmark or fixed cost is implied here.

7. Or skip the browser setup

If you need a screenshot without provisioning Chrome and WebDriver, ScreenshotNeo is a website screenshot API and MCP server for developers. Its API accepts a URL and returns an image or PDF. See the ScreenshotNeo API documentation.

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

Cookie and consent banners, newsletter popups, and chat widgets are removed before capture; those steps can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers report the page verdict and billing status. An MCP server lets AI agents using Claude, Cursor, or another MCP client call take_screenshot, get_page_info, and capture_pdf. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots.

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

8. FAQ

Can I use Selenium screenshots in a Java test?

Yes. Capture after the test reaches the state it needs, then save or compare the resulting file as part of your test workflow.

Should I save a screenshot as PNG or JPEG?

The WebDriver screenshot API examples here save the returned image bytes directly. Choose a format based on your downstream tooling and verify what the browser driver returns before applying format-specific processing.

Can I take screenshots of pages that require authentication?

A WebDriver session can capture the page state available to that session after your test authenticates. Handle credentials securely and avoid storing sensitive screenshots in public artifacts.

Does headless Chrome produce the same result as visible Chrome?

Do not assume pixel-identical output across modes, versions, fonts, operating systems, or GPU configurations. Keep the environment stable if image comparisons matter.

Sources