WeasyPrint as a hosted API

Send HTML, get a PDF rendered by WeasyPrint. 1 credit per render, PDF/A on paid plans, an MCP server, and no Pango stack to install.

Last updated

Endpoint POST /v1/weasyprint/render with a JSON body: html (required), filename (optional), pdf_variant (optional, paid plans)
Price 1 credit per render, whatever the page count; rejected and failed calls cost nothing
Limits per render 2 MB of HTML, 50 pages, 20 s with a key and 8 s without
MCP server /mcp/weasyprint/ on the API host, with the render_pdf tool
Engine WeasyPrint 70 with the DejaVu fonts

pagespool runs WeasyPrint, the open-source engine that lays out HTML and CSS as print pages. Send an HTML document to POST /v1/weasyprint/render, and the response body is the PDF. Print CSS works: @page, margin boxes, page counters and page breaks (CSS support). No JavaScript runs, and nothing is loaded from the network.

A render costs 1 credit, whatever its page count. Rejected and failed calls cost nothing. One render takes up to 2 MB of HTML and 50 pages, and may run 20 s with an API key or 8 s without. The paid plans add PDF/A-2b and PDF/A-3b output (pricing). The credits are the same ones every other engine here spends.

Quickstart with curl

This call works without an API key, at 10 free credits a day per IP address:

curl -X POST https://api.pagespool.com/v1/weasyprint/render \
  -H 'Content-Type: application/json' \
  -H "X-API-Key: $PAGESPOOL_KEY" \
  -d '{"html": "<h1>Invoice 1</h1><p>Thanks for your business.</p>", "filename": "invoice.pdf"}' \
  -o invoice.pdf -w '%{http_code}\n'

A status other than 200 means invoice.pdf holds a JSON error instead of a PDF (error codes). For PDF/A on a paid plan, add "pdf_variant": "pdf/a-2b" to the JSON.

Quickstart with Python

httpx or requests is the whole integration. Here the key travels as HTTP Basic, with the key as the password:

import os

import httpx

resp = httpx.post(
    "https://api.pagespool.com/v1/weasyprint/render",
    json={"html": "<h1>Report</h1><p>Generated in Python.</p>", "filename": "report.pdf"},
    auth=("x", os.environ["PAGESPOOL_KEY"]),
    timeout=30,
)
if resp.status_code != 200:
    problem = resp.json()
    raise RuntimeError(f"{resp.status_code} {problem['code']}: {problem['detail']}")
with open("report.pdf", "wb") as f:
    f.write(resp.content)

More in the Python guide and the Node.js guide.

Three ways to send the key

Every engine here takes the key in any of three forms. Pick the one your client supports:

Form What to send
Header X-API-Key: YOUR_KEY
Bearer token Authorization: Bearer YOUR_KEY
HTTP Basic The key as the password, any user name: curl -u x:YOUR_KEY or auth=("x", key)

A client that takes only a URL sends HTTP Basic when the key is in the URL: https://x:YOUR_KEY@ followed by the API host. Never put the key in the path or the query string. Keys are created in the dashboard. A missing or invalid key does not fail a render; it runs at the limit for calls without a key.

Self-hosted or hosted

WeasyPrint is open source, and you can run it yourself.

Self-hosted WeasyPrint Hosted here
Setup Python plus the Pango, HarfBuzz and font packages of your system, kept up to date One API key
Untrusted HTML WeasyPrint's docs ask you to limit render time and memory per process and to block file and network URLs Every render runs in its own process, killed at its time limit, with 768 MiB of memory at most; only data: URIs load
Memory Plan for the largest document you render, per parallel render Not your concern
PDF/A pdf_variant in your own code pdf_variant on a paid plan, checked with veraPDF on sample documents
Agents Build a tool around it The MCP server below

HTML written for this API also renders on your own WeasyPrint 70 with the DejaVu fonts, so you can move later.

MCP server and free tool

Agents call WeasyPrint through its own MCP server at https://api.pagespool.com/mcp/weasyprint/, with the render_pdf tool. It takes up to 256 KB of HTML and returns a link to the PDF that works for 15 minutes. Setup for each client is on the connect page and in the MCP guide.

To try a document first, paste it into the free tool, without an account.

WeasyPrint is a trademark of its owner; pagespool is not affiliated.

FAQ

What does a WeasyPrint render cost?
1 credit per render, whatever the page count. Rejected and failed calls cost nothing. Every account gets 10 free credits a day and the free plan 100 a month. The credits are shared by all seven engines.
Can I get PDF/A from the hosted WeasyPrint?
Yes, on the paid plans. Set pdf_variant to pdf/a-2b or pdf/a-3b. Without a paid plan, the call gets status 403 (feature_not_available) and costs nothing.
Which header carries the API key?
Any of three: X-API-Key, Authorization: Bearer, or HTTP Basic with the key as the password. A URL like https://x:YOUR_KEY@ followed by the API host sends Basic.