HTML to PDF in Rust
One POST, a PDF back. No headless browser to install, no Chromium to keep patched, no fonts to install on the box — the render happens on a warm browser that is already running.
Render HTML to a PDF
use serde_json::json;
use std::{env, fs, time::Duration};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(60))
.build()?;
let response = client
.post("https://api.pdfcraft.dev/v1/render")
.bearer_auth(env::var("PDFCRAFT_API_KEY")?)
.json(&json!({
"html": "<h1>Invoice 1042</h1>",
"options": { "printBackground": true }
}))
.send()
.await?
.error_for_status()?;
fs::write("invoice.pdf", response.bytes().await?)?;
Ok(())
}Read a PDF back as JSON
The same key works for extraction. Send a PDF, name the fields you want by the label printed on the page, and get them back with the raw text, a coerced value, a confidence and a bounding box.
use base64::{engine::general_purpose::STANDARD, Engine};
let encoded = STANDARD.encode(fs::read("statement.pdf")?);
let body: serde_json::Value = client
.post("https://api.pdfcraft.dev/v1/extract")
.bearer_auth(env::var("PDFCRAFT_API_KEY")?)
.json(&json!({
"file": encoded,
"schema": { "account_number": "string", "closing_balance": "currency" }
}))
.send()
.await?
.json()
.await?;
println!("{}", body["fields"]["closing_balance"]["value"]);What bites in Rust
- `.error_for_status()?` before reading the body, or a 429 gets written to disk as a PDF containing JSON.
- `response.bytes()`, not `.text()` — `.text()` is lossy UTF-8 decoding and will mangle the file.
- reqwest has no default timeout. Build the client with one rather than relying on the connection to fail.
Errors are one shape
Every failure is {"error":{"code","message","docs_url"}} with a stable code, so you can switch on error.code rather than parsing prose. The two worth handling explicitly are rate_limited — honour Retry-After — and render_failed, which means your HTML broke rather than ours did.
The same thing in another language
- HTML to PDF in Node.js
- HTML to PDF in Python
- HTML to PDF in Go
- HTML to PDF in PHP
- HTML to PDF in Ruby
- HTML to PDF in Java
- HTML to PDF in C#
- HTML to PDF in curl
- HTML to PDF in Deno
- HTML to PDF in Bun
- HTML to PDF in TypeScript
Or try it with no code at all in the playground. A free key is 100 renders a month.