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 one font provider for each conversion, register every font file or a controlled font directory, attach that provider to ConverterProperties, and pass the properties to HtmlConverter.convertToPdf. Your HTML and CSS must then request the registered family names and the weights and styles you actually loaded. Registering a regular face alone does not reliably provide matching bold and italic output.

The complete conversion pattern

pdfHTML resolves CSS fonts through the FontProvider assigned to the conversion properties. Registration has no effect if the provider is never attached to those properties.

  1. Create a new ConverterProperties.
  2. Create a FontProvider and register the required font files.
  3. Call properties.setFontProvider(fontProvider).
  4. Pass properties to HtmlConverter.convertToPdf.

Register a curated directory

This is convenient when a bounded directory contains all faces of the families used by the document:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import com.itextpdf.html2pdf.ConverterProperties;
import com.itextpdf.html2pdf.HtmlConverter;
import com.itextpdf.html2pdf.resolver.font.DefaultFontProvider;
import java.io.File;

public class PdfWithFonts {
    public static void main(String[] args) throws Exception {
        String src = "src/main/resources/invoice.html";
        String dest = "target/invoice.pdf";

        ConverterProperties properties = new ConverterProperties();
        DefaultFontProvider fonts = new DefaultFontProvider();
        fonts.addDirectory("src/main/resources/fonts");
        properties.setFontProvider(fonts);

        HtmlConverter.convertToPdf(new File(src), new File(dest), properties);
    }
}

Keep the directory intentionally small. The documentation notes that registration order matters when large collections are loaded, so an application-owned directory is more predictable than an unrestricted host font folder.

Register each file explicitly

Individual registration gives you the strongest control over portability and the exact faces that can be selected:

import com.itextpdf.html2pdf.ConverterProperties;
import com.itextpdf.html2pdf.HtmlConverter;
import com.itextpdf.io.font.FontProgram;
import com.itextpdf.io.font.FontProgramFactory;
import com.itextpdf.html2pdf.resolver.font.DefaultFontProvider;

import java.io.File;

public class ExplicitFonts {
    public static void main(String[] args) throws Exception {
        String[] fontPaths = {
            "src/main/resources/fonts/Inter-Regular.ttf",
            "src/main/resources/fonts/Inter-Bold.ttf",
            "src/main/resources/fonts/Inter-Italic.ttf",
            "src/main/resources/fonts/NotoSansCJK-Regular.otf"
        };

        ConverterProperties properties = new ConverterProperties();
        // These three flags disable standard, pdfHTML-shipped and system fonts.
        // Confirm the constructor signature in your installed pdfHTML version.
        DefaultFontProvider fonts = new DefaultFontProvider(false, false, false);
        for (String path : fontPaths) {
            FontProgram program = FontProgramFactory.createFont(path);
            fonts.addFont(program);
        }
        properties.setFontProvider(fonts);

        HtmlConverter.convertToPdf(
            new File("src/main/resources/document.html"),
            new File("target/document.pdf"),
            properties);
    }
}

The three-boolean constructor shown in the iText guide is version-sensitive. If your dependency does not expose it, use the constructor available in that release and verify which built-in and system fonts it enables.

Make CSS select the intended faces

Font files are metadata-bearing programs. CSS still has to request the family and style that correspond to that metadata.

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.
@font-face {
  font-family: "Inter";
  src: url("fonts/Inter-Regular.ttf");
  font-weight: 400;
  font-style: normal;
}
@font-face {
  font-family: "Inter";
  src: url("fonts/Inter-Bold.ttf");
  font-weight: 700;
  font-style: normal;
}
@font-face {
  font-family: "Inter";
  src: url("fonts/Inter-Italic.ttf");
  font-weight: 400;
  font-style: italic;
}
body { font-family: "Inter", sans-serif; }
strong { font-weight: 700; }
em { font-style: italic; }

Place regular, bold and italic files for a family together. If only the regular Cardo face is registered, pdfHTML can fall back for Roman-Bold and Roman-Italic; adding all three faces removes that ambiguity. A requested glyph can also force fallback when it is absent from the selected face.

Choose a font-loading strategy

Approach Control and portability Operational trade-off
Selected files with addFont Highest control; files can ship with the application Each required face must be configured
Curated directory with addDirectory Convenient for a known, bounded set Directory contents and registration order affect matching
System-font registration Uses fonts already installed on the host Availability differs by operating system and image
WOFF referenced by HTML Useful for web-derived documents pdfHTML may download it, making conversion network-dependent and slower

DefaultFontProvider() is described in the guide as equivalent to DefaultFontProvider(true, true, false): standard Type 1 fonts and pdfHTML-shipped fonts are enabled, while system fonts are disabled. The documented default set contains 14 standard Type 1 fonts and 12 shipped fonts, although only 24 are useful in HTML. This is a limited fallback set, not a substitute for your application fonts.

System fonts can work, but relying on them makes a container or server deployment dependent on its base image. Bundle selected files when identical output across machines matters. WOFF retrieval can work for HTML content, but pre-registering local files is the faster, more deterministic option.

Unicode, multilingual text and font coverage

Standard Type 1 fonts do not provide general Unicode coverage. The guide contrasts WinAnsi, which stores one byte per character, with Identity-H, which uses two-byte character codes. For multilingual content, mixed scripts, or long-term preservation and accessibility requirements, use Unicode-capable font programs and test the actual scripts in your documents. A smaller encoding is not useful if it cannot represent the required characters; compression can also reduce the practical file-size difference.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • Check that every script used by production data exists in at least one registered font.
  • Include the bold and italic files for each script where those styles are required.
  • Test combining marks, emoji, right-to-left text and uncommon punctuation in a generated PDF, not only in a browser.
  • Confirm the font license permits server distribution and PDF embedding.

Provider lifetime and document isolation

The iText 7.2.3 API documents that a FontProvider depends on a PdfDocument because it creates PdfFont objects. It should not be reused for different PDF documents unless the matching API version explicitly supports resetting and you perform that reset correctly. Treat one provider per conversion as the safe default:

public byte[] render(byte[] html) throws Exception {
    ConverterProperties properties = new ConverterProperties();
    DefaultFontProvider fonts = new DefaultFontProvider(false, false, false);
    fonts.addDirectory("/opt/my-service/fonts");
    properties.setFontProvider(fonts);

    try (java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream()) {
        HtmlConverter.convertToPdf(new java.io.ByteArrayInputStream(html), out, properties);
        return out.toByteArray();
    }
}

If a design requires additional fonts per element, the API exposes a FontSet for that purpose. Check the API page for the exact iText core and pdfHTML versions in your build; the available constructors and reset methods differ between releases.

Diagnose missing or incorrect fonts

Everything renders in a generic face

  • Confirm setFontProvider is called on the same ConverterProperties object passed to conversion.
  • Log or validate each font path before calling createFont.
  • Check that CSS family names and numeric weights match the font metadata.

Bold or italic is unexpectedly synthetic

Register the actual bold or italic file and declare its weight or style in CSS. A regular-only registration permits fallback and does not guarantee a true bold or italic face.

Some characters become boxes or change family

The selected font lacks those glyphs. Add a Unicode-capable fallback covering the missing script and test representative text. Do not assume that a family covering Latin also covers CJK, Arabic or emoji.

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

Output changes between development and production

Remove implicit dependence on system fonts. Bundle the same files, register them in a deterministic order, and use a fresh provider for each document.

Conversion slows or fails when using WOFF

WOFF referenced by HTML may require network retrieval. Supply local files or ensure the conversion process has the necessary network access and timeouts. For reproducible server jobs, pre-register selected fonts.

Constructor or method does not compile

Match the example to your installed iText core and pdfHTML versions. The documentation set includes 7.1.3 and 7.2.3 API references but does not provide a universal compatibility matrix; do not copy a constructor signature blindly across major or minor updates.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Operational checklist

  • Declare the exact iText core and pdfHTML versions in your build.
  • Package every required font file and verify its license.
  • Register all faces used by CSS: regular, bold, italic and any additional weights.
  • Use a curated directory or explicit files instead of the entire host font set.
  • Use Unicode-capable fonts for multilingual output.
  • Create one provider per PDF conversion unless your version documents a safe reset workflow.
  • Render a test document containing every production script and style.
  • Inspect the resulting PDF on the deployment machine, not only on a developer workstation.

Or skip the browser setup

If the task is actually obtaining a clean image or PDF of a web page before feeding it into a Java pipeline, ScreenshotNeo provides a single HTTP call instead of maintaining browser automation. It accepts cookie and consent banners, removes more than 60 known consent platforms, newsletter popups and chat widgets before capture, and bills only clean shots: bot checks, CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed. Responses identify 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.

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

Use the ScreenshotNeo API documentation for authentication and options. A direct call is:

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

Equivalent examples:

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}`);

It supports PNG, JPEG, WebP and PDF output, full-page and element captures, device and viewport settings, retina scale, custom CSS and JavaScript, waits, blocking rules, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, TTL caching, signed links, asynchronous webhooks and bulk capture of up to 100 URLs per call. Every feature is available on every plan. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000. Create a free ScreenshotNeo account.

Frequently Asked Questions

Can I share one FontProvider between threads?

Treat providers as document-scoped. Create a provider for each conversion unless the exact API version documents a safe reset and synchronization strategy.

Does registering a font guarantee that pdfHTML will embed it?

No. Registration makes the program available; CSS matching, glyph coverage, fallback order and embedding permissions still determine the selected face and final PDF.

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

Should production servers register all operating-system fonts?

Usually no. A curated, application-supplied set is more portable and predictable; system registration is host-dependent.

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.