skip to content

In Selenium, what do OutputType.FILE, OutputType.BYTES and OutputType.BASE64 return from getScreenshotAs?

level: juniorimportance: nice to knowfreq 38%

answer

  1. The argument picks the return type
  2. Three constants, one PNG underneath
  3. One of them touches the disk
  4. Temp file, generated name, deleted on exit
  5. Copy it before the JVM ends

basics

~10 s

All three wrap the same base64 PNG the browser returned. FILE gives a temporary file the JVM deletes on exit, BYTES gives the raw PNG byte array, and BASE64 gives the encoded string unchanged.

solid answer

~40 s

`TakesScreenshot.getScreenshotAs(OutputType<X>)` always receives one base64-encoded PNG from the driver; the `OutputType` you pass is just a converter that decides the Java type. `OutputType.BASE64` returns that `String` untouched, `OutputType.BYTES` returns the decoded `byte[]`, and `OutputType.FILE` writes the bytes to a file created by `Files.createTempFile("screenshot", ".png")` and marked `deleteOnExit()`. That last one is the trap: the path is generated, it lives in the platform temp directory, and it disappears when the JVM ends, so you must copy it yourself — `FileHandler.copy(from, to)` or `Files.copy` — before the run finishes. None of the three changes how much of the page is captured; the scope is fixed by the command, not by the conversion.

code

java · 27 lines
java
import java.io.File;
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.io.FileHandler;

public class RedactionEvidence {
  public static void main(String[] args) throws Exception {
    WebDriver driver = new ChromeDriver();
    try {
      driver.get("https://redactor.example/matters/8842/agreement");

      File temp = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
      Path evidenceDir = Files.createDirectories(Path.of("evidence"));
      FileHandler.copy(temp, evidenceDir.resolve("matter-8842-clause-14.png").toFile());

      byte[] png = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
      String inline = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BASE64);
      System.out.println(png.length + " bytes, " + inline.length() + " base64 chars");
    } finally {
      driver.quit();
    }
  }
}

go deeper

for a junior

Be ready to name all three constants and the Java type each returns, and to say that the file variant is temporary. Knowing you must copy it is the part interviewers actually listen for.

for a middle

Explain that OutputType is a converter over a single base64 PNG response, not a capture mode, and describe exactly what the FILE variant does: temp file, generated name, deleteOnExit.

for a senior

Show the operational angle: generated temp names tell a reviewer nothing, deleteOnExit never runs on a killed container, and unredacted document images left in a temp directory are a real disclosure risk.

for a principal

Own the convention. Decide once how the whole suite names, stores and expires captured evidence, and keep the output-type choice behind a single helper so no test writes its own path handling.

## What `TakesScreenshot` actually hands you Selenium's screenshot API is one interface with one method. `org.openqa.selenium.TakesScreenshot` declares `<X> X getScreenshotAs(OutputType<X> target)`, and `RemoteWebDriver` — the class every browser driver in Selenium 4 extends — implements it. In a suite for a legal-document redaction tool you write `((TakesScreenshot) driver).getScreenshotAs(...)` after a failed assertion on a redacted clause, and **the argument you pass decides the Java type you get back**. What crosses the wire never changes. The W3C **Take Screenshot** command answers with a **base64-encoded, lossless PNG** carried as a string. `RemoteWebDriver.getScreenshotAs` then inspects the response value: a `String` goes to `target.convertFromBase64Png(...)`, a `byte[]` goes to `target.convertFromPngBytes(...)`, and anything else raises a runtime error naming the command. `OutputType<T>` is therefore not a capture mode at all — it is a **converter** with exactly those two methods. ## The three constants side by side | constant | Java type returned | what you actually hold | |---|---|---| | `OutputType.BASE64` | `String` | the encoded PNG text, byte-for-byte as the driver sent it | | `OutputType.BYTES` | `byte[]` | the decoded PNG bytes, ready for a stream or an attachment | | `OutputType.FILE` | `java.io.File` | a temporary `screenshot*.png` marked `deleteOnExit()` | - **`BASE64`** does the least work: it returns the payload unchanged, which is why it is the cheapest variant when the destination is an HTML report that embeds `data:image/png;base64,` inline. - **`BYTES`** decodes once. Hand these to anything that wants an `InputStream`, a byte array, or an image decoder. - **`FILE`** decodes and then writes, so it costs a disk round trip you may not need. ## The temporary-file trap The javadoc on `OutputType.FILE` is explicit: obtain the screenshot into a temporary file that will be deleted once the JVM exits, and it is up to users to make a copy of it. The implementation is literal about all three parts: 1. it calls `Files.createTempFile("screenshot", ".png")`, so the file lands in the platform temp directory under a generated name — never a path you chose; 2. it writes the PNG bytes there, wrapping any `IOException` in a `WebDriverException`; 3. it calls `deleteOnExit()` on the resulting `File` before returning it. The consequence bites teams that record `shot.getAbsolutePath()` into a failure record and move on. When the run ends, the path in the record points at nothing. - **Copy it while the JVM is alive.** `FileHandler.copy(from, to)` in `org.openqa.selenium.io` is Selenium's own two-argument helper; `java.nio.file.Files.copy` does the same job with the JDK. - **Create the destination directory yourself.** `FileHandler.copy` opens an output stream on the target file; it does not create missing parent folders for a single-file copy. - **`deleteOnExit()` only fires on an orderly shutdown.** A run killed mid-flight leaves the temp PNGs on the machine, which matters when the pages being captured are unredacted client documents. ## Choosing a variant for a redaction suite There is no quality difference to trade off, so pick by destination: - attaching evidence to a report sink that takes bytes — `OutputType.BYTES`, no file ever touches disk; - inlining the image into a single self-contained HTML page — `OutputType.BASE64`; - handing a path to a step that genuinely wants one — `OutputType.FILE`, immediately copied somewhere durable. A useful habit on this domain: capture to `BYTES` and write the file yourself under a name that identifies the matter and the assertion, because the generated `screenshot1234.png` name tells a reviewer nothing about which redaction failed. ## What the output type does not change This is the part candidates most often get wrong. - **All three carry the same pixels.** The scope of the image is fixed by the command the driver sent, not by the conversion you asked for. Choosing `BASE64` over `FILE` does not capture more of the page. - **All three are PNG.** The spec returns a lossless PNG; there is no `OutputType` that yields a JPEG or lets you set a quality level. - **Failure surfaces the same way regardless.** `getScreenshotAs` declares `throws WebDriverException`, and an implementation that cannot capture at all throws `UnsupportedOperationException` — the output type is never the reason a capture fails. So treat `OutputType` as plumbing: it answers "what shape do I want this in", never "how much of the page do I want".

  • Why does OutputType have two conversion methods rather than one?
    `OutputType<T>` declares `convertFromBase64Png(String)` and `convertFromPngBytes(byte[])` because `RemoteWebDriver` inspects the response value before converting. A W3C driver answers with a base64 string, but the response value can arrive already decoded as a `byte[]`, and the driver dispatches to whichever method matches. Anything else raises a runtime error naming the screenshot command.
  • If a report needs a PNG on disk under a meaningful name, which output type would you pick?
    `OutputType.BYTES`, then write the file yourself. `OutputType.FILE` costs an extra decode-and-write into a generated `screenshot*.png` name you then have to copy anyway, and the temp original is deleted on exit. Taking bytes and writing once to `matter-8842-clause-14.png` is fewer steps and produces a name a reviewer can read.

saying these in an interview costs you the question

  • Claiming OutputType.FILE returns a permanent file you can keep
  • Thinking BASE64 or BYTES captures more of the page than FILE
  • Assuming you can choose JPEG or set an image quality
  • Believing the temp file survives the JVM exiting
  • Saying getScreenshotAs returns void and writes to a fixed folder