Recommended Free Tools
Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Use Chrome DevTools Protocol (CDP) Page.printToPDF with transferMode: "ReturnAsStream". Chromium returns an IO.StreamHandle instead of a base64 PDF. Read that handle in chunks with IO.read, write each decoded chunk to your final destination, and always finish with IO.close. The application never has to create a temporary PDF file, although this does not prove that Chromium or your Java CDP library uses no internal buffering.
What the streaming PDF path does
The ordinary CDP response contains PDF bytes as a base64-encoded data field. For a large document, that representation can create another large in-memory copy and usually encourages code that writes a staging file. The streaming mode changes the response shape:
Page.printToPDFreturns an emptydatafield and a stream handle.- Repeated
IO.readcalls return chunks and aneofflag. - If a chunk is marked
base64Encoded, decode it before sending it to the destination. IO.closereleases the handle, including when your sink or decoder fails.
Your sink can be an HTTP response body, an object-storage upload stream, a message-broker producer, or an output stream owned by the caller. The important boundary is your application: it does not create a temporary PDF pathname.
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minutePrerequisites and readiness
Browser and driver
Run a Chromium-family browser in headless mode and use a matching ChromeDriver. Selenium’s CDP support is temporary and depends heavily on the browser version, so pin compatible Selenium and Chromium/ChromeDriver versions rather than assuming any pair will work. The low-level executeCdpCommand API used below is available on Selenium’s ChromeDriver implementation.
#1 Best Overall
- BEST FOR SMALL BUSINESSES – Engineered for extraordinary productivity, the Brother DCP-L2640DW Monochrome (Black & White) 3-in-1 combines laser printer, scanner, copier in one compact footprint and delivers high-quality black & white prints
- FAST PRINTER WITH EFFICIENT SCANNING – Produces documents quickly with print speeds up to 36 ppm(2) and scan speeds up to 23.6/7.9 ipm(3) (black/color). A 50-page auto document feeder(4) allows for convenient, time saving multi-page scanning and copying
- FLEXIBLE CONNECTION OPTIONS – Easily navigate the changing demands of your business with secure multi-device connectivity via built-in dual-band wireless (2.4GHz / 5GHz) and Ethernet. Or connect locally to a single computer via USB interface
- BROTHER MOBILE CONNECT APP – Print, scan, and manage your wireless printer anytime, from almost anywhere from your mobile device. Order Brother Genuine Supplies, track toner usage, and complete more work on-the-go(5)
- CHOOSE BROTHER GENUINE TONER – When it’s time to replace your toner, be sure to choose Brother Genuine TN830 or TN830XL replacement toner. And with Refresh EZ Print Subscription Service, you’ll never worry about running out of toner again and you’ll enjoy savings of up to 50%(6) on Brother Genuine Toner. Get started with Refresh today with a Free Trial(1)
Page readiness
Navigation completion is not the same as visual readiness. Single-page applications may still fetch data, lazy-load images, or wait for fonts. Before printing, wait for an application-specific condition: a result element, a JavaScript readiness flag, a network-idle condition implemented by your harness, or a bounded delay as a last resort. Also wait for images and fonts that affect pagination.
Print CSS
Chromium uses print media by default. Define print styles for page breaks, hidden controls, margins, colors, and links. If the document has a CSS page size, decide whether it should override the protocol’s paper dimensions.
Complete Java example: stream directly to an output file or response
The following example uses Selenium’s low-level CDP command bridge. It writes directly to a caller-provided OutputStream; the sample main method supplies a file only to make the program easy to run. Replace that stream with your HTTP response or object-store uploader in production.
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
public final class StreamingPdf {
public static void main(String[] args) throws Exception {
ChromeOptions options = new ChromeOptions();
options.addArguments("--headless=new", "--disable-gpu", "--no-sandbox");
try (ChromeDriver driver = new ChromeDriver(options);
OutputStream out = Files.newOutputStream(Path.of("invoice.pdf"))) {
driver.get("https://example.com/invoice");
waitUntilReady(driver);
printTo(driver, out);
}
}
private static void waitUntilReady(ChromeDriver driver) throws InterruptedException {
long deadline = System.currentTimeMillis() + 30_000;
while (System.currentTimeMillis() < deadline) {
Object state = driver.executeScript("return document.readyState");
if ("complete".equals(state)) {
// Replace this with a real application condition when needed.
return;
}
Thread.sleep(100);
}
throw new IllegalStateException("The page did not become ready in 30 seconds");
}
public static void printTo(ChromeDriver driver, OutputStream destination) throws IOException {
Map<String, Object> print = new HashMap<>();
print.put("transferMode", "ReturnAsStream");
print.put("printBackground", true);
print.put("preferCSSPageSize", true);
print.put("landscape", false);
print.put("marginTop", 0.4);
print.put("marginBottom", 0.4);
print.put("marginLeft", 0.4);
print.put("marginRight", 0.4);
Map<String, Object> response = driver.executeCdpCommand("Page.printToPDF", print);
Object handleValue = response.get("stream");
if (!(handleValue instanceof String)) {
throw new IOException("Page.printToPDF did not return a stream handle: " + response.keySet());
}
String handle = (String) handleValue;
try {
boolean eof = false;
while (!eof) {
Map<String, Object> read = new HashMap<>();
read.put("handle", handle);
read.put("size", 1024 * 1024);
Map<String, Object> chunk = driver.executeCdpCommand("IO.read", read);
Object dataValue = chunk.get("data");
if (dataValue instanceof String data && !data.isEmpty()) {
boolean encoded = Boolean.TRUE.equals(chunk.get("base64Encoded"));
byte[] bytes = encoded
? Base64.getDecoder().decode(data)
: data.getBytes(java.nio.charset.StandardCharsets.ISO_8859_1);
destination.write(bytes);
}
eof = Boolean.TRUE.equals(chunk.get("eof"));
}
destination.flush();
} finally {
Map<String, Object> close = new HashMap<>();
close.put("handle", handle);
try {
driver.executeCdpCommand("IO.close", close);
} catch (RuntimeException closeFailure) {
// Preserve the original rendering/sink exception when one exists.
}
}
}
}
In a web service, pass the servlet, reactive, or storage output stream to printTo. Set the response content type to application/pdf and choose a content-disposition header appropriate to your API. Do not close a stream that your framework owns; let the framework manage its lifecycle.
Print options that change the resulting PDF
Paper, orientation, and margins
Page.printToPDF accepts paper width and height, orientation, and individual margins. Values for paper and margins are expressed in inches. If you omit them, Chromium’s defaults apply. Set them explicitly for invoices, labels, or regulatory forms.
Rank #2
- BEST FOR HOMES & HOME OFFICES – Engineered for consistent, premium print quality, the Brother HL-L2405W Monochrome (Black & White) Laser Printer delivers sharp, crisp prints at an affordable price. Prints one-sided documents at speeds up to 30ppm(2)
- COMPACT, CONNECTED PRINTER – Flexible connection options make this an ideal printer for home use and at-home offices. Securely connect to multiple devices with built-in dual-band wireless (2.4GHz/5GHz) or locally to a single computer via USB interface
- BROTHER MOBILE CONNECT APP – Manage your printer remotely and print from your mobile device anytime, from almost anywhere. Order Brother Genuine Supplies, track toner usage, and complete more work on-the-go(3)
- VERSATILE PAPER HANDLING – Enjoy seamless, reliable everyday printing with the 250-sheet paper tray(4) and a manual feed slot that enables printing on envelopes and specialty pape
- BROTHER IS AT YOUR SIDE – Backed by Brother with a 1-year limited warranty and free online, call, or live chat support for the life of your printer
CSS page size versus protocol size
preferCSSPageSize: true tells Chromium to honor an applicable CSS @page { size: ... } rule. With it disabled, content is generally scaled to fit the protocol paper dimensions. Pick one source of truth and test a representative long document.
Backgrounds, headers, and page ranges
Enable printBackground when colored panels or images are part of the document. Header and footer templates can contain page-number and date placeholders, but they run in a restricted template context; keep them simple. Use pageRanges for selected pages and validate the range before sending it to Chromium.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Repair Windows errors before they cause bigger problems3Fix the driver behind crashes, sound loss and screen glitchesPagination CSS
Use break-before, break-after, and break-inside: avoid where supported. Hide navigation, cookie notices, and interactive controls in @media print. Long unbreakable strings, tables, and replaced elements can still force unexpected page breaks, so inspect output at the largest expected data size.
Streaming versus base64: choose deliberately
| Approach | Response | Best fit | Trade-off |
|---|---|---|---|
Base64 (transferMode omitted) |
PDF in the data field |
Small PDFs and clients that already return decoded bytes | Simpler, but base64 and object copies can increase memory pressure |
Stream handle (ReturnAsStream) |
stream handle plus IO.read chunks |
Direct HTTP or object-store delivery without a staging file | Requires a read loop, decoding logic, and guaranteed cleanup |
Streaming avoids an application-created temporary file; it is not a promise of zero buffering inside Chromium, ChromeDriver, or the Java protocol implementation. Measure memory in your own deployment if document size is a hard limit.
Failure handling and operational safeguards
Always close the handle
Put IO.close in a finally block. Close it after end-of-file and also after a write error, timeout, cancellation, or decode failure. Then close the page, CDP session, and browser according to your ownership model.
Rank #3
- FAST PRINT SPEEDS: Print up to 19 pages per minute.
- COMPACT DESIGN: Space-saving, compact design fits anywhere in your home, school or small office.
- WIRELESS CONNECTIVITY: Print from almost anywhere in your workspace using your compatible mobile device.
- PAPER CAPACITY: Up to 150 sheets.
- SUSTAINABILITY: Uses less than 2 watts in Energy Saver mode.
Bound waits and output
Use a navigation/readiness deadline and a maximum document policy. A page that continually appends content can otherwise keep your job alive indefinitely. Apply back-pressure when the destination is slower than Chromium’s reads; do not accumulate every chunk in a ByteArrayOutputStream if the purpose is streaming.
Isolation and authentication
Create a separate browser context or driver for untrusted tenants. Supply cookies, headers, or an authenticated session before printing, and avoid logging sensitive page content or PDF bytes. Validate destination failures and retry at the job level only when navigation and printing are safe to repeat.
Troubleshooting
No stream field is returned
The command may have been sent to a browser/CDP version that does not support the requested transfer mode, or your wrapper may have altered the parameters. Confirm that the exact parameter is "transferMode": "ReturnAsStream" and inspect the raw response. As a fallback, omit the mode and handle the base64 data field for small documents.
The PDF is blank or missing late content
Printing occurred before asynchronous rendering completed. Wait for a specific application element, image completion, and fonts, not only document.readyState. Check that the URL is accessible from the browser’s network context and that authentication cookies were set before navigation.
Colors, backgrounds, or page breaks differ
Check print media CSS, printBackground, preferCSSPageSize, margins, and page-break rules. A CSS page size can override your assumed paper dimensions when preference is enabled.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Rank #4
- BEST FOR HOME OFFICES & SMALL TEAMS – Engineered for consistent, premium print quality, the Brother HL-L2460DW Monochrome (Black & White) Laser Printer produces documents that are clear, crisp, and easy to review and share, all at an affordable price
- COMPACT, CONNECTED, EXCEPTIONALLY EFFICIENT– Connect with built-in dual-band wireless (2.4GHz/5GHz), Ethernet, or to a single computer via USB interface. Prints at speeds up to 36ppm(2), plus automatic duplex printing saves time and reduces paper waste
- BROTHER MOBILE CONNECT APP – Manage your wireless printer remotely and print from your mobile device anytime, from almost anywhere. Order Brother Genuine Supplies, track toner usage, and complete more work on-the-go(3)
- VERSATILE PAPER HANDLING – Tackle high-volume black & white printing with the 250-sheet capacity paper tray.(4) The manual feed slot enables printing on envelopes and specialty paper
- BROTHER IS AT YOUR SIDE – Backed by Brother with a 1-year limited warranty and free online, call, or live chat support for the life of your printer
CDP command or method errors
ChromeDriver, Chromium, and Selenium must be compatible. Selenium documents its CDP layer as version-dependent and temporary; pin versions, upgrade them together, and use the generated domain for your exact browser when the low-level bridge is insufficient.
Decode or corrupted-output errors
Honor the base64Encoded flag per chunk. Decode only flagged chunks; write unencoded chunks as bytes supplied by your client. Do not concatenate text strings and convert the complete PDF through a character encoding.
Or skip the browser setup
If you need an API rather than a managed Chromium process, ScreenshotNeo provides website screenshots and PDFs through one request. It accepts consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each cleanup 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 X-Page-Verdict and X-Billed headers. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.
For the documented one-call request, see the ScreenshotNeo API documentation:
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →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}`);
The same service includes full-page capture, PDF paper and page-range controls, custom JavaScript and CSS, waits, blocking rules, authentication headers and cookies, signed webhooks for asynchronous jobs, and bulk capture for up to 100 URLs per call. Every feature is on every plan: 1,000 shots per month are free with no card, and paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account to try it.
Deployment checklist
- Pin mutually compatible Chromium, ChromeDriver, and Selenium versions.
- Define a page-specific readiness condition and timeout.
- Set paper, margins, orientation, CSS-page-size preference, and background behavior explicitly.
- Stream each
IO.readchunk directly to the final sink. - Decode only chunks marked
base64Encoded. - Call
IO.closeon success and every error path. - Test long tables, missing images, authenticated pages, and cancellation.
- Monitor browser memory and destination back-pressure; streaming is not a zero-buffer guarantee.
FAQ
Can I stream the PDF to an HTTP response?
Yes. Pass the framework-owned response output stream to the chunk loop, set application/pdf, and do not create an intermediate file.
Best Value
- FROM AMERICA'S MOST TRUSTED PRINTER BRAND – Perfect for small teams printing professional-quality black & white documents and reports. Perfect for 1-3 people
- WORLD'S SMALLEST LASER IN ITS CLASS – Precision laser printing that fits anywhere
- FAST PRINT SPEEDS – Up to 21 black-and-white pages per minute single-sided
- WIRELESS WITH SELF-RESET – Helps you stay connected
- PRINT FROM ANY DEVICE – Wireless printing from any mobile device, PC or tablet. Works with Microsoft, Mac, AirPrint, Android, Chromebook and more
Does IO.close delete a PDF file?
There is no application PDF file in this workflow. It closes the protocol stream and discards its temporary backing storage.
Is Puppeteer’s readable-stream API usable from Java?
Puppeteer documents a readable stream and byte-array PDF API for JavaScript. A Java application must use its chosen CDP client or another Java browser library.
Free tools Windows power users keep installed
One-click scans. No signup required.
Frequently Asked Questions
Can I stream the PDF to an HTTP response?
Yes. Pass the framework-owned response output stream to the chunk loop, set application/pdf, and do not create an intermediate file.
Does IO.close delete a PDF file?
There is no application PDF file in this workflow. It closes the protocol stream and discards its temporary backing storage.
Is Puppeteer’s readable-stream API usable from Java?
Puppeteer documents a readable stream and byte-array PDF API for JavaScript. A Java application must use its chosen CDP client or another Java browser library.
The Bottom Line
For Java applications that must avoid staging files, request ReturnAsStream, drain the handle with IO.read, decode each chunk correctly, and close it with IO.close in all paths. Treat readiness, print CSS, and browser/client version compatibility as part of the implementation—not as optional polish.
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.

