ScreenshotNeo

BlogHow-to

Capture a Website Screenshot in Java with Selenium and Save It as a Byte Array

Capture a page with Selenium in Java and get the screenshot directly as byte[]. Learn what the bytes contain, how to save or upload them, and how to handle common issues.

By the ScreenshotNeo team4 October 20267 min read

Use Selenium’s TakesScreenshot interface and request OutputType.BYTES. The result is the screenshot image as a Java byte[]:

byte[] screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);

Call it after navigating to the page and before quitting the driver. The bytes are image data; you can write them to a file, send them to an image-processing library, or upload them without first creating a temporary screenshot file.

1. Complete Java example

This example starts Chrome, opens a page, captures its screenshot into a byte array, writes those bytes as a PNG file, and quits the driver even if capture or writing fails. It assumes Selenium and a compatible Chrome setup are already available to the project.

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

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.WebDriverException;

public class ScreenshotToBytes {
    public static void main(String[] args) throws IOException {
        WebDriver driver = new ChromeDriver();
        try {
            driver.get("https://example.com");

            byte[] screenshot = ((TakesScreenshot) driver)
                    .getScreenshotAs(OutputType.BYTES);

            Files.write(Path.of("screenshot.png"), screenshot);
            System.out.println("Wrote " + screenshot.length + " bytes");
        } catch (WebDriverException e) {
            System.err.println("Selenium could not capture the page: " + e.getMessage());
            throw e;
        } finally {
            driver.quit();
        }
    }
}

The API call returns raw bytes. The .png extension in this example is a filename choice; use an image format supported by the browser driver and match the extension to the actual returned format if your workflow depends on it.

2. What the byte array contains

OutputType.BYTES asks Selenium for the screenshot represented as raw bytes, rather than a Base64 string or a temporary file. Treat it as encoded image data, not as an array of pixel colors. To inspect or transform pixels, decode the image with an image library.

Output type Result Use it when
OutputType.BYTES byte[] of image data You want to pass bytes to Java code, store them, or upload them.
OutputType.BASE64 Base64-encoded string A protocol or text field needs a Base64 representation. Decode it before treating it as image bytes.
OutputType.FILE Temporary file You need a file-based workflow. Follow the API’s temporary-file handling rules and copy it to a durable location if needed.

Selenium documents these output representations in its OutputType API. The screenshot operation captures the current browsing context. Do not assume it always means the entire vertically scrolling page: behavior depends on the driver and browser implementation. See Selenium’s window and tab screenshot guidance and RemoteWebDriver API.

3. Save, upload, or process the bytes

Write to a file

import java.nio.file.Files;
import java.nio.file.Path;

Files.write(Path.of("page.png"), screenshot);

Files.write creates the file if it does not exist and replaces its contents if it does. Ensure the parent directory exists and that the process has permission to write there.

Send to an HTTP service

For a multipart upload, pass the byte array as the file part using the HTTP client or framework already used by your application. Set the content type to the image format you actually received, and avoid converting the bytes to a string with the platform’s default charset. If an endpoint specifically requires Base64, encode the bytes explicitly:

import java.util.Base64;

String base64 = Base64.getEncoder().encodeToString(screenshot);

Decode for image processing

import java.io.ByteArrayInputStream;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;

BufferedImage image = ImageIO.read(new ByteArrayInputStream(screenshot));
if (image == null) {
    throw new IllegalArgumentException("Screenshot bytes were not a supported image");
}

Use ImageIO only for formats it supports in your Java runtime; other formats may need an additional image library.

4. Capture timing and scope

Navigate before calling the screenshot method. If the page renders content asynchronously, wait for a page-specific condition before capture; otherwise the screenshot may be valid but show an incomplete state. A fixed delay can help with a known animation or timed widget, but explicit waits for a meaningful condition are usually more reliable.

For example, wait for a known element to appear:

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

new WebDriverWait(driver, Duration.ofSeconds(15))
        .until(visibilityOfElementLocated(By.cssSelector("main")));
byte[] screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);

This waits for the selected element to become visible; it does not prove that every image, font, or third-party widget has finished loading. Choose a condition that represents the state your capture needs.

The driver screenshot API concerns the current browsing context. If you are inside a frame, switch to the intended frame or return to the top-level document before capture. Full-page capture is not guaranteed by the basic call across all drivers; check the behavior of your specific browser and driver if you need content beyond the visible area.

5. cURL, Python, and Node.js alternative

The direct byte-array method above is the Java Selenium answer. If your workflow can call a screenshot API instead of running a browser, these examples request a screenshot from ScreenshotNeo; they return the response image bytes for the target URL.

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,
)
r.raise_for_status()
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}`);
const bytes = new Uint8Array(await res.arrayBuffer());

Get an API key and review the ScreenshotNeo API documentation for request options and response details. The request can return PNG, JPEG, WebP, or PDF depending on the requested output.

6. Troubleshooting

Symptom Likely cause What to do
ClassCastException when casting to TakesScreenshot The selected driver does not implement the screenshot interface, or the object is not the driver you expect. Check the concrete WebDriver implementation and use one that supports screenshots. Selenium exposes screenshot capture through TakesScreenshot.
WebDriverException during capture The browser or driver failed to fulfill the screenshot request, or the session is no longer usable. Log the exception and session context; verify the browser session is alive and compatible, then retry only if the operation and page state make retrying appropriate. Selenium declares this exception for the remote screenshot method.
Image is blank or missing expected content Capture happened before the page reached the required state, or content is in another frame or still loading. Wait for a page-specific element or state, check frame selection, and capture again after the expected content is visible.
Only the viewport appears The driver captured the current browsing context rather than a stitched full-page image. Confirm the browser and driver’s screenshot behavior. Use a supported full-page capability or a different capture approach when the whole document is required.
Cannot open the resulting file The filename extension or assumed format does not match the returned data, the write was incomplete, or the bytes were altered by text conversion. Write the byte array directly, inspect the actual image format with a decoder, and keep the file extension and content type consistent.
Out of memory with large captures The browser image and byte array are held in memory, possibly alongside copies made by application code. Reduce viewport or page scope when possible, avoid unnecessary copies and Base64 conversions, and release references after processing.

7. Performance, reliability, and cost

Selenium capture requires a running browser session, so the total work includes browser startup, navigation, waits, and image serialization. Reuse a managed browser session when your application architecture permits it, and set explicit timeouts for navigation and waits so a slow page does not hold a worker indefinitely. Capture only when the page is in the desired state.

The byte array occupies memory in proportion to the encoded screenshot size. Large viewports and long pages can produce larger images and more memory pressure; avoid retaining many screenshots in a batch. If you need to persist or transmit the result, stream or hand off bytes promptly where your surrounding APIs allow it.

Selenium itself does not impose a per-screenshot service price in this API usage, but running browsers consumes your own compute and infrastructure resources. Account for browser hosting, concurrency, retries, and storage when estimating application cost. The API documents that screenshot failures can raise WebDriverException; define application-specific logging and retry behavior rather than blindly repeating captures.

8. Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server for developers. Make one GET request to capture a URL and receive image bytes:

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

Cookie banners are accepted and removed before the shot, along with supported newsletter popups and chat widgets. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed. Its MCP server lets AI agents use screenshot tools. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots. See the API docs and MCP documentation for details.

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

9. FAQ

Does getScreenshotAs(OutputType.BYTES) return Base64?

No. It returns raw image data as byte[]. Choose BASE64 only when you need a Base64-encoded string.

Can I use the result after calling driver.quit()?

Yes. Once returned, the byte array is ordinary Java data and does not depend on the browser session remaining open.

Does this call capture the full page?

Do not assume so. The basic screenshot operation captures the current browsing context, and full-page behavior depends on the driver and browser.

Can I return the byte array from a web controller?

Yes. Return the bytes as the response body and set the response content type to the actual image format. Follow your framework’s normal response-size and error-handling practices.