Use the URL to PDF Converter when you want the file without installing anything. The steps below are the detail.
The direct way to convert HTML to PDF in Java, and keep modern CSS, is a real Chromium. Playwright’s Java library drives that browser. page.pdf prints the page. Libraries that never start a browser, including Flying Saucer and OpenHTMLtoPDF, belong later on this page. They render a smaller slice of CSS.
Install Playwright and Chromium
Maven Central listed com.microsoft.playwright:playwright 1.64.0 when this was written. Confirm the version on the day you install, then add it:
<dependency>
<groupId>com.microsoft.playwright</groupId>
<artifactId>playwright</artifactId>
<version>1.64.0</version>
</dependency>
Install Chromium once, from the project directory:
mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI -D exec.args="install chromium"
Convert an HTML string
page.pdf uses print CSS unless you switch the media type first. Backgrounds are off until setPrintBackground(true). The default paper is Letter. Margins default to zero. This example writes an A4 file with a 12mm margin.
import com.microsoft.playwright.Browser;
import com.microsoft.playwright.Page;
import com.microsoft.playwright.Playwright;
import com.microsoft.playwright.options.Margin;
import java.nio.file.Paths;
public class HtmlToPdf {
public static void main(String[] args) {
String html = """
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
body { font-family: sans-serif; font-size: 12pt; }
h1 { background: #eef2ff; padding: 8px; }
</style>
</head>
<body>
<h1>October report</h1>
<p>Generated with Playwright for Java.</p>
</body>
</html>
""";
try (Playwright playwright = Playwright.create()) {
Browser browser = playwright.chromium().launch();
Page page = browser.newPage();
page.setContent(html);
page.pdf(new Page.PdfOptions()
.setPath(Paths.get("report.pdf"))
.setFormat("A4")
.setPrintBackground(true)
.setMargin(new Margin()
.setTop("12mm")
.setRight("12mm")
.setBottom("12mm")
.setLeft("12mm")));
browser.close();
}
}
}
The text block above is a Java text block, so the project needs Java 15 or newer. On an older JDK, pass a normal string.
Convert a public URL
The page has to be reachable from the machine running Java. Playwright will not sign in for you, and it will not pass a paywall.
import com.microsoft.playwright.options.WaitUntilState;
page.navigate(
"https://example.com",
new Page.NavigateOptions().setWaitUntil(WaitUntilState.DOMCONTENTLOADED));
page.pdf(new Page.PdfOptions().setPath(Paths.get("page.pdf")).setFormat("A4"));
Print CSS and screen CSS
Call emulateMedia before pdf when the layout you want is the screen layout. The Playwright Java docs show this:
import com.microsoft.playwright.options.Media;
page.emulateMedia(new Page.EmulateMediaOptions().setMedia(Media.SCREEN));
page.pdf(new Page.PdfOptions().setPath(Paths.get("report.pdf")).setFormat("A4"));
Leave that call out when you want @media print. The same print rules are explained, without Java, in print from CSS to PDF.
Add page numbers
Turn on the header and footer, and give the footer a real font size. Chrome does not use the page’s CSS inside those templates. An empty header still needs an element, or Chrome inserts the date and the title. Leave room in the bottom margin.
page.pdf(new Page.PdfOptions()
.setPath(Paths.get("report.pdf"))
.setFormat("A4")
.setDisplayHeaderFooter(true)
.setHeaderTemplate("<span></span>")
.setFooterTemplate(
"<div style='font-size:10px; width:100%; text-align:center;'>"
+ "<span class='pageNumber'></span> / <span class='totalPages'></span>"
+ "</div>")
.setMargin(new Margin().setTop("12mm").setRight("12mm").setBottom("18mm").setLeft("12mm")));
Chrome does not draw CSS @page margin boxes. setPreferCSSPageSize(true) is what makes an @page { size } rule win over setFormat. It defaults to false.
Where the other Java libraries fit
Flying Saucer, usually with OpenPDF, renders XHTML through its own engine. OpenHTMLtoPDF does the same kind of job on top of PDFBox: no JavaScript, no flexbox, and no grid. Use one of those when you cannot ship a browser. iText’s pdfHTML add-on is a different product, under the AGPL or a commercial license. Read that license before you depend on it. This page does not split those into more tutorials.
The same Chromium call in other languages is HTML to PDF in Node and HTML to PDF in Python.
Skip the install
The URL to PDF converter runs headless Chrome for a public URL, an HTML file, or pasted markup. It uses screen media, so print-only rules are skipped, and the paper size comes from the form. The file is deleted after download. There is no signup and no watermark.







