How-to guides/PDF Generation

Convert HTML to PDF in Rust

PDFluent connects to a headless browser via its browser bridge to render HTML to PDF. This gives you accurate CSS rendering, web fonts, and SVG support.

rust
use pdfluent::HtmlToPdf;

fn main() -> pdfluent::Result<()> {
    let html = r#"
        <!DOCTYPE html>
        <html>
          <head>
            <style>
              body { font-family: sans-serif; padding: 40px; }
              h1   { color: #1a1a1a; }
              .total { font-weight: bold; color: #2563eb; }
            </style>
          </head>
          <body>
            <h1>Invoice #INV-2024-042</h1>
            <p>Due: 2024-05-01</p>
            <p class="total">Total: EUR 1,200.00</p>
          </body>
        </html>
    "#;

    let pdf_bytes = HtmlToPdf::new()
        .page_size_a4()
        .margin_mm(20.0)
        .render_html(html)?;

    std::fs::write("invoice.pdf", &pdf_bytes)?;
    println!("Saved invoice.pdf ({} bytes)", pdf_bytes.len());
    Ok(())
}
Install:cargo add pdfluentDownload SDK →

Step by step

1

Add PDFluent with the html feature and install the browser bridge

The html feature requires a Chromium or Chrome installation on the machine. PDFluent calls it via the Chrome DevTools Protocol (CDP). Install the browser bridge with the provided CLI helper.

rust
# Cargo.toml
[dependencies]
pdfluent = { version = "0.9", features = ["html"] }

# Install Chromium for the bridge (Linux)
apt-get install -y chromium-browser

# macOS
brew install --cask chromium

# Or set a custom Chrome path via environment variable
# PDFLUENT_CHROME_PATH=/usr/bin/google-chrome
2

Render an HTML string to PDF bytes

HtmlToPdf::new() launches a headless browser, loads the HTML, and triggers the browser print-to-PDF function. The bytes are returned in memory.

rust
use pdfluent::HtmlToPdf;

let html = "<h1>Hello, PDF</h1><p>This is a test.</p>";

let pdf_bytes = HtmlToPdf::new()
    .page_size_a4()
    .margin_mm(15.0)
    .render_html(html)?;

std::fs::write("output.pdf", &pdf_bytes)?;
3

Render a URL to PDF

render_url() navigates to a URL and waits for the page to fully load before printing. Useful for reports served from a local web server.

rust
let pdf_bytes = HtmlToPdf::new()
    .page_size_a4()
    .wait_for_idle_ms(1000)   // wait 1 s for JS to finish
    .render_url("http://localhost:3000/invoice/42")?;

std::fs::write("invoice-42.pdf", &pdf_bytes)?;
4

Render an HTML file from disk

Pass a file:// URL or use render_file(). All relative paths (images, CSS) must be resolvable from the file location.

rust
let pdf_bytes = HtmlToPdf::new()
    .page_size_a4()
    .render_file("/tmp/invoice.html")?;

std::fs::write("invoice.pdf", &pdf_bytes)?;
5

Set custom print options

Control page size, margins, header/footer, and background printing.

rust
use pdfluent::{HtmlToPdf, PageSize};

let pdf_bytes = HtmlToPdf::new()
    .page_size(PageSize::Letter)
    .margin_top_mm(15.0)
    .margin_bottom_mm(15.0)
    .margin_left_mm(20.0)
    .margin_right_mm(20.0)
    .print_background(true)
    .header_template("<div style='font-size:10px'>Report</div>")
    .footer_template("<div style='font-size:10px'>Page <span class='pageNumber'></span></div>")
    .render_html(&html)?;

Notes and tips

  • PDFluent uses the Chrome DevTools Protocol (CDP) to control the browser. Chromium or Chrome must be installed. There is no bundled browser.
  • The browser bridge is a separate process. First render takes 300-800 ms for browser startup. Subsequent renders on the same HtmlToPdf instance reuse the browser process and take 50-200 ms.
  • For server deployments without a display, run Chrome with --no-sandbox --disable-gpu flags. These are set automatically by PDFluent on Linux.
  • CSS page breaks (@page, break-before, break-after) are respected by Chromium and appear correctly in the output PDF.
  • For pure programmatic PDF generation without a browser dependency, use PdfDocument::new() and add content directly. See the Create a PDF from Scratch guide.

Why PDFluent for this

Pure Rust

No JVM, no runtime, no DLL dependencies. Ships as a single native binary or WASM module.

Memory safe

Rust's ownership model prevents buffer overflows and use-after-free. No segfaults in PDF parsing.

Runs anywhere

Same code runs server-side, in Docker, on AWS Lambda, on Cloudflare Workers, or in the browser via WASM.

Frequently asked questions