Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Capture the screenshot before the WebDriver session closes, copy Selenium’s temporary image to a durable file, then attach that file to the appropriate ExtentReports test or log entry. Use test.addScreenCaptureFromPath(path) for a test-level image, or MediaEntityBuilder.createScreenCaptureFromPath(path).build() when the screenshot belongs to a specific log event.
The examples below use Selenium Java’s TakesScreenshot API and ExtentReports’ documented path-based methods. ExtentReports 4 and 5 have versioned documentation, so confirm the methods and reporter setup against the version your project actually uses rather than mixing major-version examples.
Capture, save, and attach the screenshot
Selenium’s OutputType.FILE returns a temporary screenshot file. Copy it to a stable location before the JVM exits; do not give ExtentReports the temporary path and assume it will remain available. For file-based reports, ExtentReports references the image path rather than embedding the image file, so keep the image with the generated report when you publish or archive it.
- Capture while the browser is still open. Call
((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE)while the page state you need is still present. - Copy the temporary file. Create a screenshot directory under the test output and copy the temporary file to it. Use a unique name for each test or failure, particularly when tests may run concurrently.
- Attach the saved image. Pass the saved path to
addScreenCaptureFromPathor toMediaEntityBuilder.createScreenCaptureFromPath, depending on whether the image describes the test or one log event. - Keep the asset with the report. When moving a file-based HTML report, move the referenced screenshot files too, and preserve the relative directory layout if the report uses relative paths.
Complete capture-and-attach example
This framework-neutral fragment assumes a live Selenium WebDriver named driver and an ExtentReports ExtentTest named test. It uses Java NIO to create the directory and copy the image. The test-framework hook—JUnit, TestNG, Cucumber, or another runner—must call it before the driver is quit.
#1 Best Overall
import com.aventstack.extentreports.ExtentTest;
import com.aventstack.extentreports.MediaEntityBuilder;
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;
import java.util.UUID;
public final class ExtentScreenshot {
private ExtentScreenshot() {}
public static Path save(WebDriver driver, String testName) throws IOException {
File temporary = ((TakesScreenshot) driver)
.getScreenshotAs(OutputType.FILE);
Path directory = Paths.get("target", "extent-media");
Files.createDirectories(directory);
String safeName = testName.replaceAll("[^a-zA-Z0-9._-]", "_");
Path saved = directory.resolve(safeName + "-" + UUID.randomUUID() + ".png");
Files.copy(temporary.toPath(), saved);
return saved.toAbsolutePath();
}
public static void attachFailure(
WebDriver driver, ExtentTest test, String testName, Throwable failure)
throws IOException {
Path image = save(driver, testName);
test.fail("Test failed: " + failure.getMessage(),
MediaEntityBuilder.createScreenCaptureFromPath(image.toString()).build());
}
}
Call attachFailure from the failure-handling point where both the failing test’s driver and its corresponding ExtentTest are still available. If you prefer a test-level attachment rather than an image on a particular log event, use the same save method and call test.addScreenCaptureFromPath(image.toString()).
Preserve the original test failure
A screenshot or file-copy problem should not silently replace the test’s original assertion or exception. In your runner’s failure hook, handle capture errors separately: record that the image could not be attached, retain the original failure, and continue the normal test cleanup. The code above exposes IOException to make that handling explicit; adapt the hook to your framework’s failure and reporting conventions.
Choose test-level or log-level attachment
Test-level image
Use test.addScreenCaptureFromPath(path) when the screenshot is intended to represent the overall test result. This keeps the association on the test object and is appropriate when your failure hook already has the saved path.
Log-level image
Use MediaEntityBuilder.createScreenCaptureFromPath(path).build() as the media argument to a log call when the image documents a specific event, such as a failed assertion or a step that could not complete. For example:
Rank #3
test.fail("Login assertion failed", MediaEntityBuilder
.createScreenCaptureFromPath(savedPath)
.build());
ExtentReports 5 documentation also demonstrates the media-builder pattern on a test event. Check the API available in your project’s dependency version before adopting the sample; do not assume every example from a different major version matches your setup.
File path or Base64?
| Approach | How it works | Practical consideration |
|---|---|---|
| File path | Selenium returns a file with OutputType.FILE; copy it and pass its path to ExtentReports. |
Simple for file-based reports, but the image asset must travel with the report and remain at the referenced location. |
| Base64 | Selenium can return OutputType.BASE64; ExtentReports provides addScreenCaptureFromBase64String and MediaEntityBuilder.createScreenCaptureFromBase64String. |
Avoids passing a separate image path in the attachment call. Check report size and downstream storage or serving behavior in your own setup. |
Choose a path when you already package report assets together and want separate image files. Consider Base64 when avoiding a separate attachment path better fits your report workflow; verify the resulting report’s size and handling before using it at scale. Neither option changes the need to capture while the relevant browser state still exists.
Base64 example
The corresponding Selenium capture value is a string rather than a file:
String image = ((TakesScreenshot) driver)
.getScreenshotAs(OutputType.BASE64);
test.fail("Test failed", MediaEntityBuilder
.createScreenCaptureFromBase64String(image)
.build());
Use the Base64 method supported by the ExtentReports version in your project. If the report is later exported, uploaded, or processed by another system, check that the resulting HTML and embedded media remain usable there.
Recommended Free Tools
Put capture at the right point in the test lifecycle
The capture belongs in a location that can access both the active WebDriver session and the matching ExtentReports test object. A runner’s failure callback or a test’s exception-handling block can provide that point, but the exact integration differs among JUnit, TestNG, Cucumber, and other frameworks. The topic does not specify a runner, so there is no single listener or annotation that applies to every project.
- Capture before calling
driver.quit(); after the session ends, the page state you wanted may no longer be accessible. - Associate the image with the same test object that records the result. In parallel execution, avoid sharing mutable test or driver references across tests.
- Use a unique filename per capture. A fixed name such as
failure.pngcan be overwritten when multiple tests save to the same directory. - Keep the capture location inside the artifacts you actually retain. A local temporary directory that is discarded after a CI job will not help someone opening the report later.
Troubleshoot missing or unusable screenshots
No image appears in the report
- Check whether the temporary image was copied.
OutputType.FILEis temporary and is deleted when the JVM exits. Save it before attaching it. - Check the path passed to ExtentReports. Attach the saved file’s path, not a path that was never created or points to the temporary source.
- Check the generated report’s location. A referenced image may fail to load if the report was moved without its image directory or if the referenced path no longer matches the asset location.
- Check that the capture ran before browser shutdown. If the driver is already closed, move the capture to an earlier failure hook or exception-handling point.
The wrong test shows the image, or an image is overwritten
- Verify test-object association. Ensure the failure hook attaches the screenshot to the failing test’s
ExtentTest, rather than a shared or stale object. - Use unique output names. Include a test identifier and a unique suffix, as in the UUID-based example, so parallel captures do not overwrite one another.
- Keep driver and report objects scoped to the correct test. The framework-specific wiring determines how those objects are assigned; the generic attachment calls cannot correct a mismatched test context.
The capture or attachment throws an error
- For a copy error, check that the destination directory can be created and written to, and handle the reported
IOException. - For a screenshot error, check that the active driver implements Selenium’s
TakesScreenshotinterface and that the browser session is still usable. - For a method or type mismatch, check the actual Selenium and ExtentReports dependency versions and compare the call with documentation for those versions. ExtentReports 4 and 5 examples are versioned; a snippet from another major version may not match your project.
- For an error while reporting a failure, keep screenshot handling separate from the original test exception so an attachment problem does not hide the failure being diagnosed.
Performance, reliability, and report storage
The cited APIs establish how to capture and associate an image, not a benchmark for capture time, report size, or throughput. Treat screenshot capture, file copying, and report rendering as work your test pipeline must accommodate; measure them in your own browser, runner, and artifact setup if runtime or storage is critical.
Path-based screenshots produce separate assets to retain and package. Base64 avoids a separate image path in the call, but the encoded image becomes part of the report content, so inspect report size and downstream handling rather than assuming it is more efficient. Use stable output paths, unique names, and explicit error handling to make report artifacts easier to preserve and diagnose.
Or skip the browser setup
If you need a screenshot of a URL rather than the exact live state inside a Selenium test, ScreenshotNeo offers a website screenshot API and MCP server. It is not a replacement for capturing a test’s active WebDriver state: use Selenium for that. ScreenshotNeo can be useful when your separate task is to capture a URL without configuring browser automation. Its clean-shot options accept consent banners like a visitor and remove more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and responses say which outcome occurred in X-Page-Verdict and X-Billed headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf for AI agents and MCP clients.
Free tools Windows power users keep installed
One-click scans. No signup required.
One GET request returns an image or PDF. For example, this cURL command saves a WebP screenshot of Stripe; see the ScreenshotNeo API documentation for parameters and response details:
Quick Recap
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Cookie banners, popups, and chat widgets are removed before the shot; bot checks, blank pages, and failed loads are never billed; the MCP server lets AI agents take screenshots; and 1,000 screenshots per month are free with no card, with paid plans starting at $5 for 3,000. Sign up for the free plan.
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.

