Free tools Windows power users keep installed
One-click scans. No signup required.
Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Capture the Appium image as PNG bytes, pass those bytes to Apache POI’s XWPFRun.addPicture, and write the resulting XWPFDocument as a .docx file. Using OutputType.BYTES avoids a temporary screenshot file and is the simplest path when the image only needs to be embedded in Word.
What you need
- A running Appium session and the official Appium Java client. The Appium Java client is built on Selenium, so Selenium’s
TakesScreenshotAPI supplies the capture operation. - Apache POI’s
poi-ooxmldependency for creating modern Word.docxfiles. - A Java test or utility process that can access the active Appium driver.
Use versions that are compatible with your Java runtime, Appium server, driver, and Selenium dependency. The APIs below are the relevant interfaces; dependency versions should come from the release lines supported by your project.
Complete Java example: capture bytes and create a DOCX
This example assumes driver is an already-connected Appium driver and that the desired screen is visible. It captures a PNG in memory, inserts it into a paragraph, and saves appium-screenshot.docx.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
import io.appium.java_client.AppiumDriver;
import java.io.ByteArrayInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.Document;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
public final class AppiumWordScreenshot {
public static void save(AppiumDriver driver, String outputPath)
throws IOException {
byte[] png = ((TakesScreenshot) driver)
.getScreenshotAs(OutputType.BYTES);
// These dimensions are examples. Change them to fit your page.
int widthEmu = Units.inchesToEMU(6.0);
int heightEmu = Units.inchesToEMU(10.0);
try (XWPFDocument document = new XWPFDocument();
ByteArrayInputStream image = new ByteArrayInputStream(png);
FileOutputStream output = new FileOutputStream(outputPath)) {
XWPFParagraph paragraph = document.createParagraph();
XWPFRun run = paragraph.createRun();
run.addPicture(image, Document.PICTURE_TYPE_PNG,
"appium-screenshot.png", widthEmu, heightEmu);
document.write(output);
}
}
}
Call it after navigation and any waits required by your test:
#1 Best Overall
AppiumWordScreenshot.save(driver, "artifacts/appium-screenshot.docx");
addPicture expects an input stream, a picture type, a filename, and dimensions in English Metric Units (EMUs). Document.PICTURE_TYPE_PNG matches the PNG returned by the Appium/Selenium screenshot call.
Preserve the screenshot’s aspect ratio
The sample uses six inches wide and ten inches high only to show the API. A phone screenshot may be taller or wider, and forcing arbitrary dimensions can stretch it. Obtain the image’s pixel width and height with an image reader, choose the maximum width that fits your page, and calculate the other dimension:
double targetWidth = Units.toEMU(6.0);
double ratio = (double) imagePixelHeight / imagePixelWidth;
int widthEmu = (int) targetWidth;
int heightEmu = (int) (targetWidth * ratio);
In production, decode the PNG with ImageIO.read, check for a null image, and calculate from the decoded dimensions before calling addPicture.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →Where to place the capture in an Appium test
- Start the Appium server and create the driver with the desired capabilities.
- Switch to the required context. Appium can capture a native context or a web context, but the visible viewport and driver support determine what is returned.
- Wait for the screen or element state your evidence requires. A screenshot taken before an asynchronous transition finishes can be valid technically but wrong for the test report.
- Call
getScreenshotAs(OutputType.BYTES). - Insert the bytes into the Word run and close the document after writing.
If you need one document containing several screenshots, create one XWPFDocument, create a new paragraph and run for each image, and call document.write once at the end. Reusing the document avoids producing a separate file for every step.
Rank #2
Choosing Selenium’s screenshot output type
| Output type | Best use | Important detail |
|---|---|---|
BYTES |
Direct insertion into POI | Keeps the PNG in memory; wrap it in ByteArrayInputStream. |
FILE |
A file-oriented pipeline | The returned file is temporary. Copy it promptly if it must remain after the JVM exits. |
BASE64 |
Text transports or APIs | Decode the Base64 value back to image bytes before passing it to POI. |
Using OutputType.FILE
File temporary = ((TakesScreenshot) driver)
.getScreenshotAs(OutputType.FILE);
Path permanent = Path.of("artifacts", "appium-screenshot.png");
Files.copy(temporary.toPath(), permanent,
StandardCopyOption.REPLACE_EXISTING);
Do not treat Selenium’s temporary file as a durable artifact. If your final deliverable is the Word document, BYTES generally removes this extra copy step.
Adding useful report text
A paragraph can contain a label before the image, and additional paragraphs can record the test name, timestamp, platform, or screen under test. Keep metadata separate from the image insertion so a failed capture does not produce a misleading report.
XWPFParagraph heading = document.createParagraph();
heading.createRun().setText("Checkout screen");
XWPFParagraph imageParagraph = document.createParagraph();
XWPFRun imageRun = imageParagraph.createRun();
imageRun.addPicture(image, Document.PICTURE_TYPE_PNG,
"checkout.png", widthEmu, heightEmu);
For a complete report, create the document before the test steps, append evidence after each successful state, and write it in a cleanup path. If the test fails before a screenshot is available, record the failure separately rather than inserting an empty picture.
Recommended Free Tools
Troubleshooting
ClassCastException when casting the driver
The object must implement Selenium’s TakesScreenshot. Use an Appium driver implementation that supports screenshots and cast the actual driver instance, not a wrapper that exposes only a limited interface.
Rank #3
- Used Book in Good Condition
The Word file is created but Word reports corruption
Make sure the document is written before its output stream closes and that the same XWPFDocument is not written concurrently. Use try-with-resources as shown, and do not append arbitrary text to the binary .docx stream.
addPicture throws an invalid-format or image error
Ensure the bytes are a real PNG and that the picture type is Document.PICTURE_TYPE_PNG. A Base64 string must be decoded first; passing its characters as if they were PNG bytes will fail.
The image is stretched or extends beyond the page
Recalculate the second EMU dimension from the source aspect ratio. Also account for page margins: a standard page’s usable width is smaller than its paper width.
The screenshot is blank or the wrong screen
- Wait for navigation, animations, and asynchronous content before capturing.
- Confirm the current native or web context.
- Verify that the driver is attached to the intended device and window.
- Check platform security restrictions. Android’s
FLAG_SECUREis an example of a setting that can prevent screenshots; support and behavior vary by platform and driver version.
The screenshot call fails on a protected app
Some applications deliberately block screenshots. Remove the restriction only in an authorized test build or use an approved test environment; do not attempt to bypass a production application’s security controls.
Rank #4
Large documents consume too much memory
BYTES keeps each image in memory until it is inserted and released. For many or very large captures, process one image at a time, avoid retaining byte arrays, and consider the temporary-file route while copying each file immediately. Downsize images only when reduced resolution is acceptable for the evidence.
Native Appium capture versus browser screenshot services
Appium is the right tool when the subject is a native or mobile-web session on a connected device. A browser screenshot API addresses a different workflow: rendering a URL on a remote browser and returning an image or PDF. Do not substitute one for the other when device state, gestures, permissions, or native controls are part of the evidence.
Or skip the browser setup:
For a URL rather than a live Appium device, ScreenshotNeo returns a PNG, JPEG, WebP, or PDF from one request. Its cleanup steps accept cookie or consent banners and remove more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be disabled. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the page verdict and billing status in headers. It also provides an MCP server with take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients.
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallOutdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchcurl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo documentation for output and option details. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Java, Python, and Node.js request examples
If your pipeline needs a hosted URL capture alongside Java-generated Word files, these equivalent calls use the same endpoint.
Best Value
Python
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
Node.js
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
These hosted captures are separate from the Appium code above: they do not capture a connected mobile device’s native screen.
Operational checklist
- Confirm the desired screen is visible and the correct context is selected.
- Capture with
OutputType.BYTESunless a durable image file is also required. - Use PNG type and EMU dimensions in
addPicture. - Preserve the source aspect ratio and fit within page margins.
- Close the image stream, document, and output stream with try-with-resources.
- Keep a copy of any
FILEoutput that must survive the JVM. - Check security settings when captures are blank or rejected.
Frequently Asked Questions
Can I insert an Appium screenshot into an existing Word template?
Yes. Open the template with POI, locate or create the target paragraph and run, and call the same addPicture method with the PNG stream and EMU dimensions before writing the modified document.
Does this workflow require saving a PNG first?
No. OutputType.BYTES returns the image in memory, so POI can consume a ByteArrayInputStream directly.
Can one DOCX contain screenshots from multiple devices?
Yes. Append each capture to the same XWPFDocument, adding labels or page breaks as needed, then write the document once.
Quick Recap
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.

