Resource library

QA How-To

How to Use Selenium full page screenshot in Java (2026)

Capture a selenium full page screenshot Java artifact with Firefox native APIs, Chromium CDP, stable page state, CI naming, and image validation for CI.

24 min read | 3,217 words

TL;DR

For a Selenium full page screenshot in Java, Firefox provides the direct `HasFullPageScreenshot.getFullPageScreenshotAs(OutputType.BYTES)` API. Standard `TakesScreenshot` normally captures the viewport. For Chrome or Edge, a browser-specific `ChromiumDriver.executeCdpCommand("Page.captureScreenshot", ...)` solution can capture beyond the viewport, but it should be isolated and tested against your browser versions.

Key Takeaways

  • Do not assume `TakesScreenshot.getScreenshotAs` captures the full document, its normal WebDriver result is usually the current viewport.
  • Use FirefoxDriver's `HasFullPageScreenshot.getFullPageScreenshotAs` for the clearest native Java full-page path.
  • Use ChromiumDriver's CDP command support only when a Chromium-specific implementation is acceptable and isolate it behind a capability-aware utility.
  • Wait for application readiness, fonts, animations, and intentional lazy loading before capturing the image.
  • Write PNG bytes to a durable artifact path and validate dimensions, format, name, and attachment behavior in CI.
  • Treat sticky elements, iframes, very tall documents, device scale, and responsive breakpoints as explicit screenshot-test inputs.
  • Keep screenshots free of passwords, tokens, customer data, and other sensitive test content.

A selenium full page screenshot java implementation must distinguish the scrollable document from the visible browser viewport. The standard TakesScreenshot.getScreenshotAs(...) call generally captures the current viewport. For a direct full-document image, FirefoxDriver implements Selenium's HasFullPageScreenshot interface. Chromium browsers need a browser-specific mechanism such as Chrome DevTools Protocol, or a carefully tested scroll-and-stitch library.

This guide shows the native Firefox route first because its intent is explicit in the Java API. It then provides a Chromium CDP implementation, explains why screenshots become incomplete or duplicated, and turns capture into a safe CI artifact rather than a one-off local file.

TL;DR

Approach Browser scope Captures Strength Main limitation
TakesScreenshot WebDriver implementations Usually viewport Standard and simple Not a full-page guarantee
HasFullPageScreenshot Firefox, including applicable augmented remote sessions Entire page Direct Selenium Java API Firefox-specific and marked Beta
Page.captureScreenshot through CDP Local or supported ChromiumDriver sessions Content clip beyond viewport No manual stitching Chromium and CDP-specific
Scroll and stitch Potentially cross-browser Multiple viewport tiles Customizable Sticky elements, seams, scaling, and lazy content
Element screenshot WebElement One element Focused evidence Not the whole document

The shortest reliable local Firefox call is:

byte[] png = ((HasFullPageScreenshot) driver)
    .getFullPageScreenshotAs(OutputType.BYTES);
Files.write(Path.of("artifacts", "full-page.png"), png);

Create the artifact directory first, and capture only after the page has reached the state the image is supposed to represent.

1. Selenium Full Page Screenshot Java Fundamentals

A browser has several relevant rectangles. The viewport is the visible content area. The document can be much taller or wider and require scrolling. A screen can include browser chrome outside the web content. Selenium WebDriver screenshot commands operate on web browsing contexts, not arbitrary desktop pixels.

TakesScreenshot is the standard Java interface implemented by common drivers and remote drivers. Its getScreenshotAs(OutputType<X>) method returns PNG data as a temporary File, Base64 string, or byte array. Under W3C WebDriver behavior, a driver screenshot represents the top-level browsing context's viewport. Browser-specific behavior can vary, so do not rename a normal viewport file to full-page.png and assume coverage.

FirefoxDriver also implements org.openqa.selenium.firefox.HasFullPageScreenshot. Its getFullPageScreenshotAs method explicitly captures the full page. The interface is marked Beta, so keep the call behind a small utility and compile against the Selenium version your suite supports.

ChromeDriver and EdgeDriver extend ChromiumDriver, which exposes executeCdpCommand. CDP's Page domain can capture a clip beyond the visible viewport. Selenium's Java API encourages its higher-level DevTools API for many CDP tasks, but screenshot commands and types can vary by protocol version. A raw command avoids importing Selenium's versioned DevTools domain packages, while still being Chromium-specific.

The correct route is capability-driven. Tests that require a cross-browser visual assertion should define browser-specific capture adapters and verify their output, not pretend every driver has identical full-page support.

2. Capture a Full Page Natively with Firefox

Add the current Selenium 4 selenium-java dependency and ensure Firefox is available. Selenium Manager supports common geckodriver discovery and setup. The following complete program generates a tall in-memory page, captures it through HasFullPageScreenshot, writes a durable PNG, and validates that the image is taller than the viewport.

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.nio.file.Files;
import java.nio.file.Path;
import javax.imageio.ImageIO;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.HasFullPageScreenshot;

public class FirefoxFullPageScreenshot {
  public static void main(String[] args) throws Exception {
    WebDriver driver = new FirefoxDriver();
    try {
      driver.manage().window().setSize(new Dimension(1280, 800));

      String html = """
          <!doctype html>
          <html lang='en'>
            <style>
              body { margin: 0; font-family: sans-serif; }
              section { height: 700px; padding: 32px; box-sizing: border-box; }
              section:nth-child(odd) { background: #e8f0fe; }
            </style>
            <body>
              <section><h1>Release report</h1></section>
              <section><h2>Quality metrics</h2></section>
              <section><h2>Open risks</h2></section>
              <section><h2>Sign-off</h2></section>
            </body>
          </html>
          """;
      driver.get("data:text/html;charset=utf-8;base64,"
          + Base64.getEncoder().encodeToString(html.getBytes(StandardCharsets.UTF_8)));

      byte[] png = ((HasFullPageScreenshot) driver)
          .getFullPageScreenshotAs(OutputType.BYTES);

      Path output = Path.of("artifacts", "firefox-full-page.png");
      Files.createDirectories(output.getParent());
      Files.write(output, png);

      BufferedImage image = ImageIO.read(new ByteArrayInputStream(png));
      if (image == null || image.getHeight() <= 800) {
        throw new AssertionError("Expected a full-page PNG taller than the viewport");
      }
      System.out.printf("Saved %s (%dx%d)%n",
          output.toAbsolutePath(), image.getWidth(), image.getHeight());
    } finally {
      driver.quit();
    }
  }
}

Using OutputType.BYTES avoids temporary-file lifecycle confusion. OutputType.FILE is also valid, but Selenium documents that it is a temporary file and the caller must copy it to a durable destination.

3. Understand OutputType and Safe File Writing

Selenium's OutputType<T> determines the Java result type. Choose it based on the next consumer, not habit.

Output type Java value Best use Caution
OutputType.BYTES byte[] Write, validate, upload, or attach PNG data Keep memory limits in mind for tall pages
OutputType.BASE64 String APIs or reports that accept Base64 Decode exactly once and avoid logging it
OutputType.FILE File Quick local copying Source is temporary and must be copied

A durable write with bytes is direct:

static Path writePng(byte[] bytes, Path directory, String fileName)
    throws java.io.IOException {
  Files.createDirectories(directory);
  Path target = directory.resolve(fileName).normalize();
  if (!target.startsWith(directory.normalize())) {
    throw new IllegalArgumentException("Screenshot path escaped artifact directory");
  }
  Files.write(target, bytes);
  return target;
}

In a real utility, sanitize any test name used in fileName. Replace path separators and characters invalid on supported operating systems. Add a timestamp, retry index, browser name, and test ID to avoid collisions during parallel runs. Do not use the page title directly as a path.

If a report library accepts bytes or an input stream, attach those bytes without writing twice. If CI artifacts require files, write to the job's designated artifact directory and configure retention. Never print a Base64 screenshot to the build log. It creates huge output and may expose page data.

Validate that ImageIO.read returns a non-null image and that dimensions are plausible. A nonempty byte array alone does not prove a readable or complete PNG.

4. Capture a Full Page in Chromium with CDP

ChromeDriver and EdgeDriver extend ChromiumDriver, whose executeCdpCommand method sends a named Chrome DevTools Protocol command. The implementation below reads the document's CSS content size, supplies that rectangle as the screenshot clip, enables capture beyond the viewport, and decodes the returned PNG.

import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Base64;
import java.util.LinkedHashMap;
import java.util.Map;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chromium.ChromiumDriver;

public class ChromiumFullPageScreenshot {
  public static void main(String[] args) throws Exception {
    ChromeDriver driver = new ChromeDriver();
    try {
      driver.manage().window().setSize(new Dimension(1280, 800));
      driver.get("https://example.com");

      byte[] png = captureFullPage(driver);
      Path output = Path.of("artifacts", "chrome-full-page.png");
      Files.createDirectories(output.getParent());
      Files.write(output, png);
    } finally {
      driver.quit();
    }
  }

  @SuppressWarnings("unchecked")
  static byte[] captureFullPage(ChromiumDriver driver) {
    Map<String, Object> metrics = driver.executeCdpCommand(
        "Page.getLayoutMetrics", Map.of());

    Map<String, Object> contentSize = (Map<String, Object>)
        metrics.get("cssContentSize");
    if (contentSize == null) {
      contentSize = (Map<String, Object>) metrics.get("contentSize");
    }
    if (contentSize == null) {
      throw new IllegalStateException("CDP returned no content size");
    }

    double width = ((Number) contentSize.get("width")).doubleValue();
    double height = ((Number) contentSize.get("height")).doubleValue();

    Map<String, Object> clip = new LinkedHashMap<>();
    clip.put("x", 0);
    clip.put("y", 0);
    clip.put("width", width);
    clip.put("height", height);
    clip.put("scale", 1);

    Map<String, Object> parameters = new LinkedHashMap<>();
    parameters.put("format", "png");
    parameters.put("fromSurface", true);
    parameters.put("captureBeyondViewport", true);
    parameters.put("clip", clip);

    Map<String, Object> result = driver.executeCdpCommand(
        "Page.captureScreenshot", parameters);
    return Base64.getDecoder().decode((String) result.get("data"));
  }
}

cssContentSize is the modern CSS-pixel metric, while the fallback supports protocol responses that still expose contentSize. This is a local ChromiumDriver example. Remote providers may restrict raw CDP commands or expose a different transport. Check the provider's documented capabilities rather than forcing a cast.

Raw CDP is not a cross-browser WebDriver guarantee. Keep this method isolated, test it with supported browser versions, and prefer a standardized or Selenium-level API when one becomes available for the required browsers.

5. Compare Native, CDP, and Scroll-and-Stitch Approaches

A screenshot utility should choose a strategy based on browser capability and test purpose. There is no honest single implementation that behaves identically everywhere without validation.

Criterion Firefox native Chromium CDP Scroll and stitch
API ownership Selenium Firefox extension Browser protocol through Selenium Your code or third-party library
Manual scrolling No No Yes
Sticky header duplication Normally avoided by browser capture Normally avoided by surface capture Common unless handled
Lazy loading activation Only content already loaded Only content already loaded Scrolling can trigger loading
Browser portability Firefox Chromium family Potentially broad
Maintenance Low to moderate Protocol-aware High
Very tall page risk Browser image limits Browser image limits Memory and stitching limits
Grid support Capability and provider dependent Provider dependent Depends on screenshot and script access

Scroll and stitch takes viewport images at several scroll positions and combines them with BufferedImage. It sounds portable, but CSS makes it hard. Fixed and sticky elements appear in multiple tiles. Smooth scrolling can capture between positions. Device pixel ratio can make CSS coordinates differ from bitmap pixels. The last tile overlaps when document height is not an exact multiple of the viewport. Lazy loading changes document height while the loop runs.

Use a maintained library only after testing those cases against your application. Do not add an unreviewed dependency solely because its example produces one tall PNG. If a native browser path exists, it is usually the cleaner evidence-capture choice.

For a focused control rather than a whole page, use WebElement.getScreenshotAs. The Selenium element screenshot Java guide covers that smaller artifact.

6. Stabilize the Page Before Capture

A technically full image can still be wrong if the page is mid-transition. Wait for application-specific readiness first. Document load completion is not enough for a single-page application whose data, fonts, and images arrive later.

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

WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(15));
wait.until(d -> ((JavascriptExecutor) d)
    .executeScript("return document.readyState")
    .equals("complete"));
wait.until(d -> d.findElement(By.cssSelector("[data-testid='report']"))
    .getAttribute("data-ready").equals("true"));

Prefer a stable application signal such as data-ready, an accessible status, or a completed record state. Wait for loading overlays to become invisible and for the intended content count. The Selenium fluent wait Java guide shows custom polling patterns for compound readiness.

Web fonts can reflow text after content appears. You can wait for document.fonts.ready with an asynchronous script when the browser supports the Font Loading API. Images can be checked through their complete and naturalWidth properties. Disable animation and transitions with a temporary style only when the screenshot contract permits that intervention, then remove it afterward.

Be deliberate about lazy content. A native full-page capture does not guarantee that below-the-fold images have been requested. A scroll sweep can activate lazy loading, but it changes application state and may trigger analytics or infinite scrolling. Implement it as an explicit preparation step with a termination rule, then wait for the document height to stabilize before capture.

7. Handle Sticky UI, Lazy Loading, and Infinite Pages

Sticky headers and chat widgets are part of the rendered page. Native full-surface capture typically paints them according to browser behavior, while scroll-and-stitch can repeat them in every tile. Decide whether they belong in the artifact. Removing or restyling them can make an image easier to read, but it also makes the screenshot less representative of the user experience.

If a cookie banner covers content, handle it as the test scenario requires. Accept it through normal UI if the target state assumes consent. Do not use JavaScript to delete it silently unless the screenshot is specifically a content inventory rather than a behavioral artifact.

Lazy loading requires a bounded process. Record the current scroll height, scroll near the bottom, wait for loading to settle, and stop when height no longer changes or when a maximum iteration count is reached. Infinite feeds have no true full page. Define a capture boundary such as the first 50 items, a pagination page, or a specific section. A screenshot utility cannot turn an unbounded product into a finite artifact without a stated rule.

Fixed footers, transformed containers, nested scroll regions, and canvas content also need explicit testing. Full-document capture follows the top-level page. It may not expand an independently scrolling grid. For that component, scroll and capture the component or use product-specific export functionality.

Document these limitations in the helper API. A method named captureEntireApplicationState promises too much. captureTopLevelDocument is more precise.

8. Make Viewport, Scale, and Headless Mode Deterministic

Full-page height does not eliminate viewport dependence. Responsive breakpoints use viewport width. Text wrapping changes page height. Sticky behavior depends on viewport dimensions. Headless and headed browsers can have different available content areas unless you set them explicitly.

driver.manage().window().setSize(new Dimension(1440, 900));

Set a supported viewport before navigation or before the state under test is created. Record width, height, browser name, browser version, platform, headless mode, locale, time zone, color scheme, zoom, and device scale when visual output matters. Do not compare a 1280-wide baseline with a 1440-wide failure capture.

Java image dimensions are physical pixels. DOM layout metrics are CSS pixels. Device scale can multiply the bitmap size. The CDP example supplies a CSS-pixel clip and a scale of one, but browser output and environment settings still need validation. Do not hard-code an expected pixel height derived only from scrollHeight without accounting for scale and browser limits.

Headless mode is suitable for CI, but verify its full-page output against the supported headless implementation. Browser upgrades can alter font rasterization and rendering. Pin or record versions for visual regression. For diagnostic screenshots, exact pixel stability is less important, but reproducible layout still improves usefulness.

9. Capture Full Pages in Remote Grid Sessions

Remote WebDriver implements standard screenshot behavior, but full-page extensions depend on browser and Grid capabilities. Selenium's Augmenter can enhance an applicable remote Firefox driver with interfaces provided through augmentation, including HasFullPageScreenshot. The returned object may be a dynamic proxy, so code against interfaces rather than a concrete class.

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.HasFullPageScreenshot;
import org.openqa.selenium.remote.Augmenter;

WebDriver augmented = new Augmenter().augment(remoteDriver);
if (!(augmented instanceof HasFullPageScreenshot fullPage)) {
  throw new UnsupportedOperationException(
      "Remote session does not expose Firefox full-page screenshots");
}
byte[] png = fullPage.getFullPageScreenshotAs(OutputType.BYTES);

Do not cast a generic RemoteWebDriver to FirefoxDriver or ChromiumDriver. The Java client object is not the browser-specific local subclass. For cloud grids, use the provider's documented CDP or screenshot channel if needed, and make the adapter report unsupported capability clearly.

Transferring a very large Base64 image through Grid can be expensive and can hit provider or proxy limits. Keep page height bounded, compress only after preserving the required PNG evidence, and avoid capturing on every successful step. Screenshot on failure or at named checkpoints.

Test the exact remote matrix before depending on the feature. A capability advertised by the browser may still be restricted by an intermediary. Fail with an explicit unsupported message rather than silently falling back to a viewport image labeled as full page.

10. Attach Screenshots on Test Failure

A failure hook should preserve the first useful state without masking the original exception. It should create a collision-resistant path, capture according to capability, attach or publish the file, and report capture failure separately. Do not let a screenshot error replace the test failure.

A simple capability-aware method can choose Firefox native capture and otherwise fall back to a clearly named viewport image:

static Path captureFailure(WebDriver driver, Path directory, String testId)
    throws java.io.IOException {
  String safeId = testId.replaceAll("[^a-zA-Z0-9._-]+", "_");
  Files.createDirectories(directory);

  boolean full = driver instanceof HasFullPageScreenshot;
  byte[] png = full
      ? ((HasFullPageScreenshot) driver).getFullPageScreenshotAs(OutputType.BYTES)
      : ((org.openqa.selenium.TakesScreenshot) driver)
          .getScreenshotAs(OutputType.BYTES);

  String scope = full ? "full-page" : "viewport";
  Path target = directory.resolve(safeId + "-" + scope + ".png");
  Files.write(target, png);
  return target;
}

A production adapter can add Chromium CDP handling when the driver object supports it. Keep scope in the filename and report metadata so a reviewer knows what was captured.

With JUnit 5 or TestNG, integrate through the framework's lifecycle extension or listener and use the driver owned by that test. In parallel execution, never retrieve a different test's static driver. Attach the screenshot to Allure or the CI report, then retain the file according to policy.

The failure hook should also record URL and browser metadata, but redact sensitive query parameters. Capture before teardown and after the application has stopped changing when possible. A failure caused by a crash may make screenshots unavailable, so console and driver logs remain complementary evidence.

11. Validate and Secure Screenshot Artifacts

A successful API return does not guarantee a useful artifact. Decode the PNG, inspect dimensions, and optionally sample expected landmarks through a visual tool. For a full-page smoke check, verify that image height is greater than the known viewport when the test page is intentionally taller. Do not use that assertion for naturally short pages.

Check these artifact properties:

  1. The byte array is nonempty and decodes as an image.
  2. Width and height are positive and within infrastructure limits.
  3. The file extension matches PNG data.
  4. The filename identifies test, browser, retry, and capture scope.
  5. Parallel tests cannot overwrite each other.
  6. CI publishes the directory even when the test process fails.
  7. Retention is long enough for triage but not indefinite by accident.

Screenshots are data. They can contain typed passwords, access tokens, personal information, internal URLs, customer records, and chat content. Use synthetic test data, mask secret fields before capture when appropriate, restrict artifact access, and set retention deliberately. Do not upload screenshots to public issue trackers by default.

A full-page image has a larger exposure surface than a viewport or element image. Capture the smallest artifact that answers the debugging question. For console evidence alongside images, see the Selenium browser console logs Java guide.

12. Selenium Full Page Screenshot Java Decision Guide

Choose the implementation through explicit questions:

  1. Is a viewport image enough? Use standard TakesScreenshot and label it viewport.
  2. Is the browser Firefox? Use HasFullPageScreenshot locally or through applicable remote augmentation.
  3. Is the session a local ChromiumDriver and is browser-specific code acceptable? Use an isolated CDP adapter and validate output against supported versions.
  4. Is browser portability mandatory? Evaluate a maintained stitcher against sticky UI, scaling, overlap, and lazy content before adoption.
  5. Is the page unbounded? Define a finite content boundary instead of promising an impossible full page.
  6. Does the evidence concern one component? Prefer WebElement.getScreenshotAs.
  7. Is the image for visual regression? Pin the rendering environment and control fonts, animation, data, viewport, and browser versions.
  8. Is the image only for failure diagnosis? Favor capability-aware capture, clear scope labels, and reliable attachment over pixel-perfect normalization.

Keep the strategy behind an interface such as ScreenshotCapture. Implement FirefoxFullPageCapture, ChromiumCdpCapture, and ViewportCapture. Make unsupported full-page capture an explicit result or exception. Silent fallback creates misleading artifacts and makes cross-browser differences look like product defects.

Interview Questions and Answers

Q: Does TakesScreenshot capture the full page in Selenium Java?

Normally, the standard WebDriver screenshot represents the current viewport, not the entire scrollable document. I label it as a viewport capture. For a full page, I use a browser-supported API such as Firefox's HasFullPageScreenshot or a validated Chromium-specific adapter.

Q: What is the native Firefox full-page API?

FirefoxDriver implements HasFullPageScreenshot. I call getFullPageScreenshotAs(OutputType.BYTES) and write the returned PNG bytes to a durable path. The interface is Beta, so I isolate it behind a utility and test the supported Selenium version.

Q: How do you capture a full page in Chrome?

For a local ChromeDriver, I can use ChromiumDriver.executeCdpCommand with Page.getLayoutMetrics and Page.captureScreenshot, including a full content clip and captureBeyondViewport. It is Chromium-specific, so I do not claim cross-browser behavior and I validate it after browser upgrades.

Q: Why is scroll-and-stitch difficult?

Fixed and sticky controls can repeat in every tile, lazy content changes document height, and device scale creates coordinate differences. The final tile may overlap, and animations can create seams. I prefer native capture and test any stitcher against the application's real CSS patterns.

Q: How do you prepare a page for a screenshot?

I wait for the application's terminal state, content count, fonts, images, and loading overlay as required. I fix the viewport and environment. I trigger lazy loading only through an explicit bounded preparation step.

Q: How do full-page screenshots work on Grid?

It depends on remote capabilities. Selenium's Augmenter can expose applicable Firefox full-page support, while cloud providers may have their own CDP channel. I verify capability, avoid unsafe concrete casts, and fail clearly rather than mislabeling a viewport fallback.

Q: What makes a screenshot artifact production-ready?

It has a collision-resistant name, durable path, readable PNG bytes, plausible dimensions, browser and scope metadata, report attachment, and controlled retention. It also uses synthetic or masked data so the image does not leak secrets or personal information.

Common Mistakes

  • Calling TakesScreenshot and labeling the viewport result as a full-page screenshot.
  • Casting a generic RemoteWebDriver to FirefoxDriver or ChromiumDriver.
  • Using OutputType.FILE without copying the temporary file.
  • Capturing before asynchronous content, fonts, or images settle.
  • Scrolling an infinite feed without a maximum iteration or content boundary.
  • Adopting scroll-and-stitch without testing sticky headers, overlap, scale, and nested scroll containers.
  • Running headed locally and headless in CI without fixing viewport and recording rendering metadata.
  • Using one filename for parallel tests and overwriting failure evidence.
  • Letting a screenshot exception replace the original test failure.
  • Silently falling back to viewport capture while keeping full-page in the filename.
  • Logging Base64 PNG data or attaching sensitive application content to a public report.
  • Comparing images across different browser, font, locale, scale, or viewport settings.

Treat capture scope and browser strategy as test metadata. A reviewer should never have to guess whether the bottom of the page is absent because of a product defect or because the code captured only the viewport.

Conclusion

For a selenium full page screenshot Java implementation, use HasFullPageScreenshot with Firefox when possible, and use an isolated, validated CDP adapter for supported Chromium sessions when needed. Keep standard TakesScreenshot for viewport evidence and label it honestly.

Build one capture utility that checks capability, waits for the intended page state, writes safe PNG artifacts, validates dimensions, and reports its scope. Then test it against a tall page, sticky UI, lazy content, headless CI, and your Grid. A trustworthy screenshot is not merely tall, it is reproducible evidence of a defined browser state.

Interview Questions and Answers

What is the difference between a viewport and full-page screenshot?

A viewport screenshot contains the currently visible web content area. A full-page screenshot contains the top-level scrollable document beyond the fold. The distinction matters because standard WebDriver screenshot behavior does not universally promise the latter.

How would you implement Firefox full-page capture in Java?

I use `HasFullPageScreenshot.getFullPageScreenshotAs(OutputType.BYTES)`, create the artifact directory, and write the PNG bytes. I wait for the application state first and validate that the image decodes with plausible dimensions. I keep the Beta interface behind an adapter.

How would you implement Chrome full-page capture?

For a supported local ChromiumDriver, I read CSS content dimensions with `Page.getLayoutMetrics` and call `Page.captureScreenshot` with a full clip and capture beyond viewport. I decode the Base64 data and validate the PNG. I isolate the raw CDP dependency and retest on browser upgrades.

What problems occur with screenshot stitching?

Sticky elements repeat, the last tile overlaps, animations cause seams, and CSS-to-image scale can differ. Lazy loading can change page height during the loop. I use native capture when available and treat a stitcher as browser-rendering code that requires its own regression tests.

How do you make visual screenshots deterministic?

I control viewport, browser version, headless mode, fonts, device scale, locale, time zone, data, animation, and readiness. I record that metadata with the artifact. Pixel comparisons are meaningful only when the rendering environment is intentionally stable.

How do you avoid screenshot failures hiding test failures?

The listener catches capture errors separately, logs them as secondary evidence failures, and preserves the original exception. Capture happens before driver teardown and uses the driver owned by the current test. A screenshot is diagnostic support, not the test verdict.

What security risks do screenshots create?

Images can expose credentials, tokens, personal data, internal URLs, and customer records. I use synthetic data, mask sensitive fields when appropriate, restrict artifact access, and configure retention. I capture the smallest area that answers the debugging need.

Frequently Asked Questions

How do I take a full-page screenshot in Firefox with Selenium Java?

Use FirefoxDriver through the `HasFullPageScreenshot` interface and call `getFullPageScreenshotAs(OutputType.BYTES)`. Write the bytes to a durable PNG path after the page reaches the intended state.

Does getScreenshotAs capture the whole page?

The standard `TakesScreenshot.getScreenshotAs` call normally captures the current viewport under W3C WebDriver behavior. Do not treat it as a cross-browser full-page guarantee.

Can Selenium Java take a full-page Chrome screenshot?

A local ChromeDriver can use Chromium-specific CDP commands to capture a content clip beyond the viewport. Isolate this approach because raw CDP is browser-specific and remote providers may expose it differently.

Should I use OutputType.FILE or BYTES?

`BYTES` is convenient for durable writing, validation, and report attachment. `FILE` is valid, but Selenium creates a temporary file that your code must copy before it is removed.

Why are sticky headers duplicated in my screenshot?

This usually happens with scroll-and-stitch capture because the fixed element is painted in each viewport tile. Use native full-surface capture or configure and test the stitcher to handle fixed elements.

Why are below-the-fold images blank in a full-page screenshot?

Lazy-loaded images may not have been requested because the page was never scrolled. Use an explicit, bounded scroll preparation and wait for images and document height to settle before capture.

How do I take full-page screenshots on Selenium Grid?

Check the remote session and provider capabilities. Selenium's Augmenter can expose applicable Firefox full-page support, while Chromium CDP access depends on the Grid or provider. Fail clearly if unsupported.

Related Guides