How to Capture Full-Page PDF Screenshots With Selenium Java and aShot
Use aShot for stitched full-page images and Selenium PrintOptions for paginated PDFs, with runnable Java examples and troubleshooting.
Short answer: aShot and Selenium page printing produce different outputs. Use aShot’s viewportPasting strategy when you need one tall, full-page image. Use Selenium’s PrintsPage.print(PrintOptions) API when you need a paginated PDF with print margins, paper size, orientation and page ranges.
aShot’s documented workflow returns a Screenshot containing an image and comparison data; its README documents image capture, not PDF encoding. Selenium’s print API asks the browser to create a PDF representation of the page. Decide which output you need before writing the capture code.
Choose the right capture method
| Requirement | aShot viewport pasting | Selenium page printing |
|---|---|---|
| Output | One tall raster image (PNG/JPEG, depending on how you save it) | Paginated PDF |
| Method | Scroll, capture viewports, then stitch them | Browser print operation using PrintOptions |
| Layout controls | Viewport and image handling | Orientation, paper size, margins, scale, backgrounds and page ranges |
| Main risks | Seams, sticky elements, animations, lazy loading and device-pixel-ratio differences | Unexpected page breaks, print CSS, scale and Chromium headless requirements |
| Best fit | Visual regression evidence or a single long image | Shareable or archival document |
References: aShot README and Selenium’s Print Page documentation.
Prerequisites and project setup
- Install a JDK supported by your Selenium release.
- Add Selenium Java and the aShot dependency.
- Use a browser driver compatible with the browser version. Selenium Manager can resolve drivers in current Selenium releases, or configure a driver explicitly in your environment.
- Run Chromium in headless mode for page printing, as required by Selenium’s Chromium printing documentation.
The aShot README shows this Maven coordinate:
<dependency>
<groupId>ru.yandex.qatools.ashot</groupId>
<artifactId>ashot</artifactId>
<version>1.5.4</version>
</dependency>
The repository page lists 1.5.2 as its latest release (December 9, 2015), while the README example uses 1.5.4. Treat 1.5.4 as the documented example and verify compatibility in your build before standardizing it.
Capture a full-page image with aShot
The documented full-page recipe uses ShootingStrategies.viewportPasting(100). The value is the example scroll timeout in milliseconds.
import java.io.File;
import javax.imageio.ImageIO;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import ru.yandex.qatools.ashot.AShot;
import ru.yandex.qatools.ashot.Screenshot;
import ru.yandex.qatools.ashot.shooting.ShootingStrategies;
public class FullPageImage {
public static void main(String[] args) throws Exception {
ChromeOptions options = new ChromeOptions();
options.addArguments("--headless=new", "--window-size=1440,1000");
WebDriver driver = new ChromeDriver(options);
try {
driver.get("https://example.com");
// Wait for your page's application state before capturing.
Screenshot screenshot = new AShot()
.shootingStrategy(ShootingStrategies.viewportPasting(100))
.takeScreenshot(driver);
ImageIO.write(screenshot.getImage(), "PNG", new File("full-page.png"));
} finally {
driver.quit();
}
}
}
Make dynamic pages settle before stitching
aShot captures repeated viewports and pastes them together. If content changes while the driver scrolls, the resulting image can contain seams, duplicated sticky headers or missing sections. Before calling takeScreenshot:
- Wait for a stable application marker such as a results container.
- Wait for lazy-loaded images to finish loading when possible.
- Disable or freeze animations with injected CSS if animation causes frame-to-frame changes.
- Use a consistent viewport size and browser scale.
- Inspect the final image for repeated fixed-position elements and stitch seams.
High-DPI and retina behavior
A historical aShot issue reported top-left-only output when device pixel ratio was 2; the project owner attributed that report to DPR and pointed to viewportRetina. This is a version- and environment-specific issue report, not a universal current fix. If output dimensions are wrong, first compare CSS viewport dimensions with screenshot pixel dimensions, then test the strategy intended for your aShot version and keep browser scaling consistent.
Generate a paginated PDF with Selenium
Selenium exposes page printing through the PrintsPage interface. ChromeDriver implements it. Configure PrintOptions, call print, and write the returned PDF content to disk.
import java.nio.file.Files;
import java.nio.file.Path;
import org.openqa.selenium.PrintsPage;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.print.PageMargin;
import org.openqa.selenium.print.PageSize;
import org.openqa.selenium.print.PrintOptions;
import org.openqa.selenium.print.Pdf;
public class FullPagePdf {
public static void main(String[] args) throws Exception {
ChromeOptions options = new ChromeOptions();
options.addArguments("--headless=new", "--window-size=1440,1000");
WebDriver driver = new ChromeDriver(options);
try {
driver.get("https://example.com");
PrintOptions printOptions = new PrintOptions();
printOptions.setOrientation(PrintOptions.Orientation.PORTRAIT);
printOptions.setPageSize(new PageSize(8.27, 11.69)); // A4, inches
printOptions.setPageMargin(new PageMargin(0.4, 0.4, 0.4, 0.4));
printOptions.setBackgroundGraphics(true);
printOptions.setScale(1.0);
Pdf pdf = ((PrintsPage) driver).print(printOptions);
Files.write(Path.of("page.pdf"), pdf.getContent());
} finally {
driver.quit();
}
}
}
Check the Selenium Java API version you use for the exact setter names available in your release. Selenium documents print orientation, page ranges, page size, margins, background output and scaling as print controls. The browser applies print CSS and pagination, so a PDF is not a single infinitely tall screenshot.
Common print options
- Orientation: portrait or landscape.
- Page size: choose a paper format appropriate for the document.
- Margins: reduce clipping and control usable content width.
- Scale: lower it when content is clipped; raise it only when readability requires it.
- Background graphics: enable when colored sections or backgrounds are part of the required evidence.
- Page ranges: print only selected pages when the document is large.
Handling sticky headers, lazy content and animations
Scroll-and-stitch and browser printing fail in different ways. For aShot, fixed headers may appear in every pasted viewport. Lazy content may load after the viewport has already been captured. For printing, print-specific CSS can hide or rearrange content, and page breaks can split cards or tables.
- Open the target page in the same browser mode used by automation.
- Wait for a page-specific readiness condition.
- Capture aShot output and inspect seams at viewport boundaries.
- Open the generated PDF and inspect page breaks, margins, backgrounds and missing fonts.
- Adjust waits, CSS, print options or viewport dimensions based on the actual failure.
If sticky elements make scroll-and-stitch unsuitable, Shutterbug documents a DevTools-based full-page mode and recommends it over its own scroll strategy for sticky elements. Attribute that behavior to Shutterbug; it is not an aShot guarantee.
Or skip the browser setup
ScreenshotNeo provides a website screenshot API and MCP server. One request returns PNG, JPEG, WebP or PDF, so you can capture a URL without maintaining Selenium, ChromeDriver and stitching code. See the ScreenshotNeo API documentation for the complete option list.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
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)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
Cookie banners, newsletter popups and chat widgets are removed before the shot. Bot checks, blank pages, failed loads and cache hits are never billed, and response headers report the page verdict and billing result. An MCP server lets Claude, Cursor and other MCP clients take screenshots. 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.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Only the viewport is captured | The driver or strategy does not provide full-page behavior | Use aShot’s viewportPasting strategy and verify the resulting image dimensions. |
| Repeated header or footer | A fixed-position element is captured in every viewport | Hide or temporarily unfix the element with CSS, or use a DevTools-based capture approach. |
| Missing images near the bottom | Lazy loading has not completed | Scroll or wait for image completion before capture; verify the page’s readiness marker. |
| Stitched seams | Animation or content layout changes during scrolling | Disable animations, wait for layout stability and increase the viewport-pasting delay. |
| Top-left-only or incorrectly scaled image | Device pixel ratio or browser scaling mismatch | Keep scale consistent, compare CSS and pixel dimensions, and investigate the retina strategy for your aShot version. |
| Print call fails or returns no PDF | Driver does not implement PrintsPage, or Chromium is not headless |
Use a compatible ChromeDriver and run Chromium headlessly as Selenium documents. |
| PDF has unexpected page breaks | Print CSS, margins or scale alter pagination | Adjust PrintOptions, inspect print styles and test representative pages. |
| Background colors are absent | Background graphics are disabled | Enable the background graphics option and verify browser print settings. |
Performance, reliability and cost considerations
Performance
- aShot’s full-page image requires multiple viewport captures, so runtime grows with page height and scroll delay.
- Large images consume memory during stitching and PNG encoding. Capture only the viewport width you need.
- PDF printing is generally one browser print operation, but rendering fonts, images and print CSS still determines total time.
- Reuse a warmed driver for batches when isolation requirements permit; always quit drivers that are no longer needed.
Reliability
- Pin compatible browser and driver versions in CI.
- Use explicit waits tied to application state instead of arbitrary sleeps where possible.
- Save failed artifacts and logs so you can distinguish navigation failures from capture defects.
- Review output after browser upgrades because print layout and device-pixel-ratio behavior can change.
Cost
Self-hosted Selenium costs compute, browser maintenance and engineering time. aShot itself is an image utility and does not provide a PDF service. ScreenshotNeo charges only for clean shots; failed loads, bot checks, blank pages, timeouts and cache hits are not billed. Plans range from 1,000 free shots monthly to paid tiers beginning at $5 for 3,000 shots.
FAQ
Does aShot create PDFs?
The aShot README documents image screenshots and a Screenshot object. Use Selenium’s page-printing API for PDF output.
Is a full-page PDF the same as a full-page screenshot?
No. A PDF is paginated according to print layout. A full-page screenshot is one tall raster image created by stitching viewports or using a browser full-page capture.
Why must Chromium run headlessly for printing?
Selenium’s browser-window documentation states that Chromium page printing requires headless mode.
Can I capture only selected PDF pages?
Yes. Selenium’s PrintOptions supports page ranges; configure the range supported by your Selenium version.
What should I use for an automated screenshot service?
Use ScreenshotNeo when you want a single API request, built-in cleanup of consent banners and popups, billing protection for failed captures, or MCP access for AI agents.


