Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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 OpenHTMLtoPDF when your input is controlled, well-formed XHTML/XML and uses supported CSS. Choose Flying Saucer’s Chrome-backed PDF module when the page depends on modern HTML5, CSS3, or browser behavior. PDFBox is useful for manipulating PDFs, but it is not an HTML renderer. A Java library is not automatically a complete browser: JavaScript, flexbox, grid, web fonts, pagination, and external assets vary by engine. Validate your real templates before selecting a production route.

Choose the renderer before writing conversion code

The right choice depends on how closely the output must match a browser.

Requirement Best starting point Important limitation or deployment concern
Pure Java, authored XHTML/XML, supported CSS OpenHTMLtoPDF It renders a reasonable subset of well-formed XML/XHTML and some HTML5, but does not execute JavaScript and does not implement many modern features, including flex and grid. Its maintainers explicitly caution that modern HTML5 cannot simply be dropped in and expected to render well.
XHTML and CSS 2.1 in the Flying Saucer family Flying Saucer PDF module Use the Java baseline for the exact release: the project README lists Java 11+ for 9.5.0, Java 17+ for 9.6.0, and Java 21+ for 10.0.0.
Modern HTML5/CSS3 or browser-like behavior Flying Saucer Chrome PDF module The module delegates PDF generation to chrome-headless-shell. You must package, locate, secure, and operate that external browser component.
PDF editing, merging, forms, images, signing, or extraction Apache PDFBox PDFBox creates and manipulates PDF documents; its official project description does not present it as an HTML/CSS renderer.

Compare candidates using the same representative pages: HTML normalization, CSS coverage, Java runtime, JavaScript needs, browser dependencies, font and image handling, page breaks, accessibility or PDF/A requirements, licensing, and the security of parsing input. The available project material does not establish a general performance winner, so do not select on an unverified speed claim.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

OpenHTMLtoPDF: a pure-Java route for controlled documents

OpenHTMLtoPDF is a good fit for invoices, reports, certificates, and other templates that you own and can author as valid XHTML/XML. Start by making the document structurally strict: close every element, use one root element, declare UTF-8, and avoid relying on browser error recovery.

Prepare markup and assets

  • Use supported CSS rather than assuming current browser CSS works. Flexbox and grid are not implemented.
  • Do not depend on JavaScript to insert content or style the page; the renderer does not execute it.
  • Use absolute, file, or classpath asset locations that your application can resolve deterministically. Test images, SVG, and fonts from the same deployment environment.
  • Prefer tables for report-like layouts. The project guidance warns that floats close to page breaks can produce poor results.

Java conversion example

The following example shows the renderer API. Resolve the current OpenHTMLtoPDF runtime modules from the project’s integration guidance rather than copying a parent POM as if it were the executable renderer dependency.

import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;

import com.openhtmltopdf.pdfboxout.PdfRendererBuilder;

public final class HtmlToPdf {
    public static void main(String[] args) throws Exception {
        Path html = Path.of("report.xhtml");
        Path pdf = Path.of("report.pdf");

        String markup = Files.readString(html);
        try (OutputStream out = Files.newOutputStream(pdf)) {
            PdfRendererBuilder builder = new PdfRendererBuilder();
            builder.useFastMode();
            builder.withHtmlContent(markup, html.toAbsolutePath().getParent().toUri().toString());
            builder.toStream(out);
            builder.run();
        }
    }
}

The base URI in withHtmlContent is significant: relative image, stylesheet, and font URLs are resolved against it. In a server, replace a user-controlled filesystem base with an allow-listed asset resolver. Never allow an arbitrary input document to read local files or internal network addresses.

Control page layout

Use print-oriented CSS that the selected engine supports. Define page size and margins with @page, keep headings with the following block where possible, and place repeatable headers or footers in the mechanism documented by your chosen release. Render pages containing long tables, large images, missing fonts, and long unbreakable strings; inspect the resulting PDF rather than trusting a successful Java call.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Flying Saucer options and Java versions

Flying Saucer’s traditional PDF module is a pure-Java XML/XHTML renderer based on CSS 2.1. Its release line matters operationally: Java 11+, 17+, or 21+ may be required depending on whether you select 9.5.0, 9.6.0, or 10.0.0. Pin the exact artifact set and verify it on the JDK used in production.

When modern HTML5/CSS3 is essential, evaluate the project’s Chrome PDF module. It delegates to chrome-headless-shell, so deployment includes browser version management, executable permissions, sandbox policy, temporary storage, process limits, and a strategy for crashes and updates. A browser-backed route is not automatically more reliable; it is simply a closer match for pages that require browser features.

Why PDFBox is usually a second step

PDFBox is appropriate after rendering when you need to merge documents, fill forms, extract or stamp content, add images, print, or sign PDFs. It can also create PDFs directly, but you would have to implement HTML layout yourself. Keep HTML rendering and PDF post-processing as separate stages so failures are diagnosable.

A production conversion pipeline

  1. Normalize input. Convert templates to well-formed XHTML/XML when using a non-browser renderer. Reject malformed or unexpectedly large documents.
  2. Resolve resources safely. Allow-list schemes and hosts, cap downloaded bytes, set connection and read timeouts, and prevent file or metadata-service access.
  3. Render in an isolated worker. Apply memory, CPU, wall-clock, and output-size limits. For a Chrome-backed module, isolate the browser process and apply its sandbox guidance.
  4. Validate the result. Check that a PDF was produced, has the expected page count and size range, and contains required text or metadata.
  5. Inspect representative pages. Test fonts, RTL text, images, SVG, tables, page breaks, landscape pages, and very long content.
  6. Record versions and licenses. Keep the JDK, renderer modules, browser binary (if any), fonts, and transitive dependencies pinned and reviewable.

Security, licensing, and release notes

HTML-to-PDF conversion parses complex input and can trigger network or file access through resources. Treat untrusted HTML as hostile. Disable or restrict external fetching, sanitize where appropriate, and run conversion with least privilege. Apply the security guidance for the exact release you deploy.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

OpenHTMLtoPDF states that it is licensed under LGPL 2.1-or-later; its PDF/A testing module has a separate GPL exception and is not distributed to Maven Central. Confirm obligations for every transitive component. Flying Saucer’s changelog records recent XXE hardening in DocumentBuilderFactory usage, but that is not a blanket security guarantee for every release or application. Apache PDFBox is under Apache License 2.0. Flying Saucer’s changelog dates version 10.4.0 to July 16, 2026, with listed work including CSS transforms in PDF output, inline PDF elements, SVG fixes, and XXE-related hardening. Treat those entries as release notes, not proof that your deployment is secure.

Rank #3
Sale
Play for Java: Covers Play 2
  • Used Book in Good Condition

Common failures and fixes

Blank or nearly blank PDF

Check that the input is well-formed XML, the renderer received the intended character encoding, and the base URI points to accessible assets. Log the resolved HTML length and resource failures before debugging CSS.

Missing images, styles, or fonts

Relative URLs often resolve against the wrong directory in server code. Supply an explicit base URI or resource resolver, package fonts with the application, and verify permissions. Do not silently fetch arbitrary URLs.

Modern layout collapses

Flexbox, grid, JavaScript-generated markup, and newer CSS may not be supported by OpenHTMLtoPDF or traditional Flying Saucer. Rewrite the template using supported CSS, or test the Chrome PDF module against the exact page.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Text overlaps or page breaks are wrong

Reduce reliance on floats, test table-based layout, set print margins explicitly, and remove unbreakable strings. Compare output at several content lengths; a short sample can hide pagination defects.

Runtime or class-loading errors

Check that all renderer modules match one release line and that the JDK meets that release’s requirement. A Maven parent version is not necessarily the module that supplies the runtime classes.

Conversion hangs or consumes excessive memory

Cap input and output sizes, set network and worker timeouts, limit concurrent jobs, and isolate browser processes. Capture diagnostic logs and terminate workers that exceed their budget.

XXE or server-side request risks

Do not parse untrusted XML with permissive defaults. Use the selected library’s current secure configuration, disable external entities and DTD access where applicable, and restrict every resource resolver to approved locations.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Performance and reliability choices

Pure-Java rendering avoids launching a browser and can simplify deployment, but feature limitations may force template rewrites. A Chrome-backed renderer can handle more browser-era markup while adding startup cost, memory use, process supervision, and a browser update lifecycle. Cache immutable templates and fonts, reuse safe renderer configuration, and measure your own documents. No supplied source establishes a representative benchmark, so publish workload-specific measurements only if you have actually collected them.

Or skip the browser setup

If your goal is simply to obtain a clean PDF or image of a public page rather than render a Java template, ScreenshotNeo provides a website screenshot API and MCP server. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be disabled. Bot checks or CAPTCHAs, 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 tools—take_screenshot, get_page_info, and capture_pdf—work with Claude, Cursor, and other MCP clients.

One GET request is enough:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

For Java applications, call the same endpoint with your HTTP client and save the binary response:

HttpClient client = HttpClient.newHttpClient();
String url = "https://api.screenshotneo.com/v1/shot?access_key=YOUR_API_KEY&url=https%3A%2F%2Fstripe.com";
HttpRequest request = HttpRequest.newBuilder(URI.create(url)).timeout(Duration.ofSeconds(90)).build();
HttpResponse<byte[]> response = client.send(request, HttpResponse.BodyHandlers.ofByteArray());
if (response.statusCode() / 100 != 2) throw new IOException("ScreenshotNeo HTTP " + response.statusCode());
Files.write(Path.of("shot.webp"), response.body());

See the ScreenshotNeo documentation for the 63 capture options, including PDF paper size and margins, full-page lazy-image loading, CSS selectors, device presets, retina scale, custom CSS and JavaScript, clicks, waits, blocking rules, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, TTL caching, signed links, asynchronous webhooks, bulk capture of up to 100 URLs per call, usage API, and OpenAPI support. Plans include 1,000 screenshots per month free with no card; paid plans start at $5 for 3,000, and yearly billing gives two months free. Create a free ScreenshotNeo account.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

FAQ

Can JavaScript-generated content be rendered with OpenHTMLtoPDF?

No. It does not execute JavaScript, so generate the content before conversion or use a browser-backed route.

Is Flying Saucer the same as OpenHTMLtoPDF?

No. They are related renderer families with different modules, release requirements, and feature sets. Select and test a specific release.

Should I use PDFBox instead of an HTML renderer?

Use PDFBox for PDF operations such as merging, forms, extraction, and signing. Choose an HTML renderer when the source of truth is HTML/CSS.

Frequently Asked Questions

How do I test whether my template is supported?

Build a fixture containing your real fonts, images, tables, page breaks, and CSS, then compare generated PDFs at short and long content lengths on the production JDK.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Can I convert an arbitrary public website inside a Java service?

Only with an engine and security model designed for remote pages. Restrict network access, expect JavaScript and browser dependencies, and consider a browser-backed capture service when a clean page snapshot is the actual requirement.

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.