How to Render Web Fonts in DocRaptor PDFs
Use CSS @font-face to load web fonts in DocRaptor PDFs. Learn how to make font files reachable, choose a compatible pipeline, and verify the result.
To render a web font in a DocRaptor PDF, declare it with CSS @font-face, make its font file reachable by DocRaptor during rendering, and apply that family to the text. Then generate a PDF and inspect it with representative characters. WOFF2 requires DocRaptor Pipeline 8 or newer. DocRaptor’s web-font guide and custom-font tutorial document this pattern.
1. Declare the font and use it in your HTML
Use the same family name in @font-face and the CSS rule that applies the font. Declare the style and weight of the actual file; add more @font-face rules when your document uses other weights or styles.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<style>
@font-face {
font-family: "Open Sans";
font-style: normal;
font-weight: 400;
src: url("https://fonts.example.test/open-sans-regular.woff2") format("woff2");
}
@font-face {
font-family: "Open Sans";
font-style: normal;
font-weight: 700;
src: url("https://fonts.example.test/open-sans-bold.woff2") format("woff2");
}
body {
font-family: "Open Sans", Arial, sans-serif;
font-weight: 400;
}
h1, strong {
font-weight: 700;
}
</style>
</head>
<body>
<h1>A document with a web font</h1>
<p>Check punctuation, café, résumé, and the scripts your document needs.</p>
<strong>This text uses the bold face.</strong>
</body>
</html>
The example host is deliberately illustrative. Replace it with an HTTPS URL for a real font file you can use. DocRaptor’s guide demonstrates a Google-hosted Open Sans WOFF2 file, but URLs and font availability can change; verify the URL you choose. Keep a fallback family for characters the web font does not contain.
2. Submit the HTML to DocRaptor
DocRaptor accepts HTML through document_content. The following Python example uses its documented API pattern and test mode. Set the API credentials in environment variables and install the requests package first.
python -m pip install requests
export DOCRAPTOR_API_KEY='your-api-key'
export DOCRAPTOR_API_USERNAME='your-api-username'
import os
import requests
html = """<!doctype html>
<html>
<head>
<meta charset='utf-8'>
<style>
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 400;
src: url('https://fonts.example.test/open-sans-regular.woff2') format('woff2');
}
body { font-family: 'Open Sans', Arial, sans-serif; }
</style>
</head>
<body><p>Font test: café, résumé, and punctuation.</p></body>
</html>"""
response = requests.post(
"https://docraptor.com/docs",
auth=(os.environ["DOCRAPTOR_API_USERNAME"], os.environ["DOCRAPTOR_API_KEY"]),
data={
"doc[document_type]": "pdf",
"doc[name]": "web-font-check",
"doc[test]": "true",
"doc[document_content]": html,
},
timeout=90,
)
response.raise_for_status()
with open("web-font-check.pdf", "wb") as pdf:
pdf.write(response.content)
Follow the current DocRaptor API reference for authentication and request details for your account. Test mode is useful while iterating; use the appropriate production setting when you are ready to create production documents.
3. Make font URLs resolvable
The rendering service has to fetch the font file while it renders. An absolute HTTPS URL is the simplest choice. If your CSS uses a relative URL, provide a base URL with prince_options[baseurl] or use a suitable HTML <base> element, following DocRaptor’s tutorial.
The API reference documents a default external-resource fetch period of up to 10 seconds and a configurable timeout. A URL that works from your laptop can still fail from the rendering environment if it requires a login, is blocked, redirects unexpectedly, has expired, or responds too slowly. Make sure the resource is accessible to the renderer and does not depend on browser-only authentication.
4. Match font format to the DocRaptor pipeline
DocRaptor documents WOFF2 support beginning with Pipeline 8. If you use WOFF2, check the pipeline configured for your account before troubleshooting the CSS. The API reference maps Pipeline 8 to Prince 13.5 and lists later pipeline and Prince versions as well. Check the account setting and consult the current reference; do not assume every account uses the same pipeline.
| Situation | What to check |
|---|---|
| Font is WOFF2 | Use Pipeline 8 or newer, per DocRaptor’s font guide. |
| Font is another format | Confirm support for that format in the pipeline and renderer version configured for your account. |
| Relative font URL | Set a base URL or use an appropriate <base> element so the asset resolves correctly. |
| Typography changed after a pipeline upgrade | Check line height and pagination as well as font loading. Pipeline 8 release notes say Prince 13 changed line-height: normal to follow the recommended value for the current font; line-height: 1.2 restores the earlier behavior described there. |
The pipeline mapping and the line-height note are documented in the API reference and Pipeline 8 release notes.
5. Choose the right faces and fallbacks
A font family can have separate files for regular, bold, italic, and other weights. Declare each face with its matching font-style and font-weight. If only the regular face is declared but the document requests bold, the renderer may have to synthesize a style or use a fallback. Explicit declarations let it select the intended file.
@font-face {
font-family: "Report Sans";
font-style: normal;
font-weight: 400;
src: url("https://assets.example.test/report-regular.woff2") format("woff2");
}
@font-face {
font-family: "Report Sans";
font-style: italic;
font-weight: 400;
src: url("https://assets.example.test/report-italic.woff2") format("woff2");
}
@font-face {
font-family: "Report Sans";
font-style: normal;
font-weight: 700;
src: url("https://assets.example.test/report-bold.woff2") format("woff2");
}
body {
font-family: "Report Sans", Arial, sans-serif;
}
Check the font’s license before using or embedding it. Font coverage varies: test the accented characters, symbols, punctuation, and writing systems present in your actual documents. Retain suitable fallbacks for missing glyphs.
6. Verify the generated PDF
- Confirm the submitted HTML contains the
@font-facerule and the text references exactly the same family name. - Confirm each requested style and weight has a matching declaration and accessible font file.
- Open the font URL from outside your application and check that it serves the expected file over HTTPS.
- Check the account’s DocRaptor pipeline against the font format, especially for WOFF2.
- Generate a PDF containing representative text, then inspect its appearance, pagination, and glyph coverage.
- If the PDF must remain portable, inspect the resulting PDF’s font information and confirm the intended font is embedded as required.
DocRaptor exposes prince_options[no_embed_fonts] to disable font embedding and prince_options[no_subset_fonts] to disable font subsetting. Leave the defaults unless you have a specific reason to change them; verify the produced PDF when portability matters. Declaring a font does not by itself prove that every intended glyph is present or that the font is embedded.
7. Troubleshoot missing or incorrect fonts
| Symptom | Likely cause | Fix |
|---|---|---|
| The PDF uses a fallback font throughout | The family name differs between @font-face and the CSS using it, or the font URL cannot be fetched. |
Match the names exactly; test the absolute URL and make the asset publicly reachable to the renderer. |
| Regular text works but bold or italic does not | The corresponding weight or style face was not declared, or the declaration does not match the file. | Add a separate @font-face rule for each face and ensure the document requests the declared weight and style. |
| WOFF2 is ignored or fails to load | The configured pipeline is older than Pipeline 8. | Check the account pipeline and use a compatible pipeline or a format supported by that pipeline. |
| The font works locally but not in the PDF | The renderer cannot reach a local path, private URL, authenticated endpoint, or slow resource. | Use a renderer-accessible HTTPS URL or configure a base URL for relative resources; check the resource fetch timeout. |
| Some accented letters or symbols look wrong | The chosen font may not include those glyphs. | Test representative content and provide a fallback family with the necessary coverage. |
| Text spacing or page breaks changed after an upgrade | The renderer or pipeline changed font metrics or line-height behavior. | Compare the configured pipeline and inspect CSS line-height and pagination. For the documented Prince 13 change, explicitly setting line-height: 1.2 restores the previous normal behavior. |
| The PDF looks right on one machine but not another | The intended font may not be embedded, or the viewer may substitute it. | Inspect the PDF’s font information and embedding; use the embedding options only with a clear requirement and validate the output. |
8. Performance, reliability, and cost considerations
Remote fonts add external resources to the rendering path. A slow or unavailable font endpoint can delay rendering or leave the document using a fallback. Keep font URLs stable, use HTTPS, avoid unnecessary font faces, and verify that the renderer can reach every asset. DocRaptor’s documented default resource-fetch period is up to 10 seconds; consult the API reference for its configurable timeout and account behavior.
Use the same pipeline consistently when layout stability matters, and treat a pipeline upgrade as a rendering change: inspect line heights, page breaks, and font selection on representative documents. The provided documentation does not establish a universal render-time benchmark, a price for a particular font setup, or guaranteed glyph coverage, so validate these against your account, font, and document.
Or skip the browser setup
For a screenshot of a rendered web page, ScreenshotNeo provides a one-call screenshot API. This is a different output path from generating a DocRaptor PDF: use DocRaptor when you need a PDF document, and ScreenshotNeo when an image capture of a page is what you need. See the ScreenshotNeo website and API documentation.
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}`);
- Cookie banners are accepted and removed before the shot; newsletter popups and chat widgets are removed too.
- Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed; response headers report the page verdict and billing status.
- An MCP server lets AI agents use screenshot tools, including
take_screenshot,get_page_info, andcapture_pdf. - The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots.
Sign up for ScreenshotNeo’s free 1,000 screenshots a month, with no card required.
FAQ
Does a web font need to be installed on the computer that opens the PDF?
The source HTML’s CSS declaration is not enough to establish portability. Check whether the intended font is embedded in the generated PDF and inspect the file in a PDF viewer.
Can I use a Google web font?
The documented pattern supports a remotely hosted font through @font-face. Use a current, reachable font URL and verify that the selected pipeline supports its format.
Does WOFF2 work on every DocRaptor pipeline?
No. DocRaptor documents WOFF2 support for Pipeline 8 and newer.
Why might line spacing change after a pipeline upgrade?
DocRaptor’s Pipeline 8 release notes describe a Prince 13 change to line-height: normal. Set an explicit line height and review pagination if the change affects your document.


