formepdf
Python SDK for Forme — a page-native PDF rendering engine. Build documents from a component DSL and render them to PDF locally, in-process, with no browser, no headless Chromium, and no system libraries — the engine ships as a single WebAssembly module and runs anywhere Python runs (including serverless).
- Local rendering via
wasmtime— no API key, no network calls. - Real print features — flexbox layout, tables with headers that repeat across pages, fixed headers/footers, page breaks, watermarks.
- Accessible & archival — tagged PDF, PDF/UA-1, and PDF/A produced locally, the same conformance the engine gives everywhere.
- Charts, QR codes, barcodes, and fillable form fields built in.
- Local digital signing (PKCS#7 / X.509).
Installation
pip install formepdf[local]
The [local] extra adds wasmtime; the engine WASM is bundled in the wheel. That's
all you need — no cairo, no pango, no fonts to install.
Quick start
from formepdf import Document, Page, View, Text
doc = Document(
Page(
View(
Text("Invoice #001", font_size=24, font_weight="bold"),
Text("Acme Corp", font_size=14, color="#666"),
flex_direction="column", gap=8,
),
),
title="Invoice #001",
)
pdf = doc.render() # -> bytes
with open("invoice.pdf", "wb") as f:
f.write(pdf)
Accessible & archival output
The conformance options live on Document — no extra pipeline, no external validator
step to produce them:
doc = Document(
Page(Text("Annual Report 2026", font_size=20)),
title="Annual Report 2026",
lang="en",
tagged=True, # structure tree (BDC/EMC marked content)
pdf_ua=True, # PDF/UA-1 (accessibility)
pdfa="2b", # PDF/A-2b (archival); also "2u", "2a", "3b", "3u", "3a"
)
pdf = doc.render()
Document options: title, author, subject, lang, tagged, pdf_ua, pdfa,
flatten_forms.
Components
| Component | Description |
|---|---|
Document(*children) |
Root container. .render() returns PDF bytes. Options: title, author, subject, lang, tagged, pdf_ua, pdfa, flatten_forms |
Page(*children) |
Page container. Options: size (e.g. "A4", "Letter"), margin |
View(*children) |
Flex/grid container. Options: all style kwargs (flex_direction, gap, padding, etc.) |
Text(content) |
Text element. Options: font_size, font_weight, color, text_align, etc. |
Image(src) |
Image (file path, URL, or data URI). Options: width, height, alt |
Table(*rows) |
Table with auto-repeating headers. Options: columns |
Row(*cells) |
Table row. Options: header=True for repeat-on-page-break |
Cell(*children) |
Table cell. Options: col_span, row_span |
Svg(content) |
Inline SVG. Options: width, height |
QrCode(data) |
Vector QR code. Options: size, color |
Barcode(data) |
1D barcode. Options: format ("Code128", "Code39", "EAN13", etc.), width, height |
BarChart(data) |
Bar chart. Options: width, height, color, title |
LineChart(series, labels) |
Line chart. Options: width, height, show_points, title |
PieChart(data) |
Pie/donut chart. Options: width, height, donut, title |
AreaChart(series, labels) |
Area chart. Options: width, height, title |
DotPlot(groups) |
Scatter plot. Options: width, height, title |
TextField(name) |
Fillable text field. Options: value, placeholder, multiline |
Checkbox(name) |
Fillable checkbox. Options: checked |
Dropdown(name, options) |
Fillable dropdown. Options: value |
RadioButton(name, value) |
Radio button. Options: checked |
Watermark(text) |
Rotated watermark. Options: font_size, color, angle |
PageBreak() |
Force a page break |
Fixed(*children) |
Fixed-position element. Options: position ("header", "footer") |
Local digital signing
Apply a PKCS#7 / X.509 signature to an existing PDF, offline:
import json
from formepdf.wasm import certify_pdf
with open("document.pdf", "rb") as f:
pdf = f.read()
config = json.dumps({
"certificate_pem": open("cert.pem").read(),
"private_key_pem": open("key.pem").read(),
"reason": "Approved",
})
certified = certify_pdf(pdf, config)
Self-hosted render server (optional)
The package also ships a thin HTTP client, Forme, for a self-hosted Forme render
server — the public hosted API has been retired, so point base_url at your own
deployment. It exposes server-side operations the local WASM engine doesn't:
render stored templates by slug (render / render_async / get_job), true redaction
(redact), merge, rasterize, and extract.
from formepdf import Forme
client = Forme("forme_sk_...", base_url="https://pdf.your-company.com")
pdf = client.render("invoice", {"customer": "Acme", "total": 245})
Requirements
- Python 3.8+
wasmtimefor local rendering (pip install formepdf[local])- No system libraries, no browser.
Metadata
Release files for formepdf 0.23.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| formepdf-0.23.0.tar.gz | 2.9 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| formepdf-0.23.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 5.8 MB
Release files / formepdf-0.23.0.tar.gz
| Download URL | formepdf-0.23.0.tar.gz |
|---|---|
| Size | 2.9 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e103b31cbdbdfb13f9717d9e96a87a56384f6ee8c0fe0b04152c1dd01537e100
|
|
BLAKE2b-256 checksum How to use checksums |
5fd5b5c738b6093d3531c0e0f0ead156187a626631eee17450e4ddc729fddcac
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.12
|
Release files / formepdf-0.23.0-py3-none-any.whl
| Download URL | formepdf-0.23.0-py3-none-any.whl |
|---|---|
| Size | 2.9 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e524a920c2ce2cdab4710672fc2ee0475ff2a665902acea88d926b5c389e9a6e
|
|
BLAKE2b-256 checksum How to use checksums |
ef123ded93569830192825377325f23efd032eb6d5232bf820b61ceb77d1243e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.12
|