Total: $10
", "format": "A4", "margin": "15mm", "footer_html": "
`.
### Page breaks
Use CSS: `break-before: page`, `break-inside: avoid`, `@page { size: A4; margin: 20mm }` (with `prefer_css_page_size: true`).
## GET /v1/credits
```json
{ "balance": 99, "used_total": 1, "email": "you@example.com", "unit": "1 credit = 1 PDF page", "top_up_url": "https://html-pdf.com/dashboard",
"auto_topup": { "enabled": false, "threshold": 100, "pack": { "usd": 10, "credits": 1000 }, "card": null, "settings_url": "https://html-pdf.com/dashboard#autotopup" } }
```
`auto_topup.card` is the saved card's label (e.g. `"visa •••• 4242"`), or `null` before the first purchase.
## GET /v1/conversions
Last 100 conversions: id, status, pages, bytes, duration_ms, source (`api`, `mcp`, `web`), created_at. Document content is never stored.
## POST /v1/checkout
Get a Stripe payment link for a credit pack, e.g. for an agent to send to its human. Credits are added as soon as the payment succeeds.
```bash
curl -X POST https://html-pdf.com/v1/checkout -H "Authorization: Bearer $HTML_PDF_KEY" -d '{"usd": 10}'
```
```json
{ "checkout_url": "https://checkout.stripe.com/...", "usd": 10, "credits": 1000 }
```
Packs (`usd` → credits): 10 → 1,000 · 25 → 3,000 · 50 → 7,000 · 100 → 15,000 · 250 → 50,000.
Running low? The account owner gets an email below 20 credits and at 0, and can enable **auto top-up** in the dashboard to refill automatically from a saved card.
## POST /v1/autotopup
Turn auto top-up on or off so an automation never runs out: when the balance drops below `threshold`, the card saved at the first purchase is charged for the `usd` pack (at most once every 10 minutes; it turns itself off if a payment fails). Send any of the three fields; the others keep their value. `threshold` can be at most the pack size, so one top-up always lifts the balance above it.
```bash
curl -X POST https://html-pdf.com/v1/autotopup -H "Authorization: Bearer $HTML_PDF_KEY" \
-d '{"enabled": true, "threshold": 200, "usd": 25}'
```
Returns `{"auto_topup": {...}}` as in `GET /v1/credits`. The account owner is emailed about every change. Without a saved card you get `409 no_saved_card` with a `checkout_url`: buy once, then turn it on. Agents should ask the user before turning it on.
## POST /v1/keys
Create an additional API key for the account of the key you authenticate with. Revoke keys in the dashboard.
## Errors
All errors are JSON:
```json
{ "error": { "code": "insufficient_credits", "message": "You have no credits left.", "hint": "Buy credits at ...", "top_up_url": "https://html-pdf.com/dashboard", "docs_url": "..." } }
```
| status | code | meaning |
|---|---|---|
| 400 | `missing_html`, `invalid_url`, `html_and_url`, `invalid_json`, `invalid_*` | Fix the request. |
| 400 | `disposable_email` | `POST /v1/signup` with a temporary (temp-mail) address. Use a permanent email. |
| 401 | `missing_api_key`, `invalid_api_key` | |
| 402 | `insufficient_credits` | No credits left, or the PDF has more pages than your balance (then the error has `pages` and `balance`). Not charged. `checkout_url` is a ready Stripe payment link to give the user, for the pack that fits your recent usage (from $25 for 3,000 pages, see `checkout_pack`); also `top_up_url`, or `POST /v1/checkout` for other packs. |
| 403 | `email_not_confirmed` | Free credits are added when the account's email is confirmed. Open the emailed link, then retry. |
| 409 | `account_exists` | Signup with an existing email; login link emailed. |
| 409 | `no_saved_card` | `POST /v1/autotopup` before any purchase. Pay `checkout_url` once, then retry. |
| 413 | `too_large` | Body over 20 MB. |
| 422 | `render_failed`, `max_pages_exceeded` | Not charged. |
| 429 | `rate_limited` | 120 req/min per account. Retry after `Retry-After`. |
| 503 | `busy`, `engine_unavailable` | Not charged. Retry. |
| 504 | `render_timeout` | Over 30 s. Not charged. |
Failed requests never cost credits.
## Limits
- Request body: 20 MB
- Render time: 30 s
- Rate: 120 requests/minute per account
- Download links (`response: "url"`, MCP): 24 hours
## Security note
The renderer cannot reach private networks. Treat the HTML you send like code running in a sandboxed browser: it may load public URLs and run JavaScript.
---
# MCP server
Let your AI agent create PDFs directly. Remote MCP server, Streamable HTTP transport:
```
https://html-pdf.com/mcp
```
Auth: **OAuth 2.1**. Clients like Claude.ai, ChatGPT and Claude Code open an html-pdf.com login when you connect, so there is no key to copy. You can also send the header `Authorization: Bearer hp_live_...`, or use `https://html-pdf.com/mcp?api_key=hp_live_...` in clients that only accept a URL.
No key yet? You don't need one. Add the server URL and your client opens an html-pdf.com login. New accounts get 100 free credits.
## Tools
| tool | what it does |
|---|---|
| `html_to_pdf` | Render HTML to PDF. Returns a download URL (valid 24h), page count and credits left. Same options as the [API](/docs): `html`, `filename`, `format`, `landscape`, `margin`, `css`, `header_html`, `footer_html`, `print_background`, `media`, `wait_delay`, `max_pages`. |
| `url_to_pdf` | Render a public web page (`url`) to PDF. Same options as `html_to_pdf` except `html`/`css`. |
| `get_credits` | Remaining credits, top-up link and auto top-up status. |
| `buy_credits` | Create a Stripe payment link for a credit pack (`usd`: 10, 25, 50, 100, 250) to give to the user. |
| `set_auto_topup` | Turn auto top-up on or off (`enabled`, `threshold`, `usd`) after the first purchase. The owner is emailed about every change. |
## Claude Code
```bash
claude mcp add --transport http html-pdf https://html-pdf.com/mcp \
--header "Authorization: Bearer $HTML_PDF_KEY"
```
## Claude Desktop / claude.ai
Customize → Connectors → **+** → Add custom connector (Team/Enterprise: an owner adds it under Organization settings → Connectors). Paste this URL, click **Connect** and log in with your email.
```
https://html-pdf.com/mcp
```
## Cursor
`~/.cursor/mcp.json`:
```json
{
"mcpServers": {
"html-pdf": {
"url": "https://html-pdf.com/mcp",
"headers": { "Authorization": "Bearer hp_live_..." }
}
}
}
```
## VS Code
`.vscode/mcp.json`:
```json
{
"servers": {
"html-pdf": {
"type": "http",
"url": "https://html-pdf.com/mcp",
"headers": { "Authorization": "Bearer ${input:html-pdf-key}" }
}
},
"inputs": [{ "id": "html-pdf-key", "type": "promptString", "description": "html-pdf.com API key", "password": true }]
}
```
## Codex
`~/.codex/config.toml`:
```toml
[mcp_servers.html-pdf]
url = "https://html-pdf.com/mcp"
bearer_token_env_var = "HTML_PDF_KEY"
```
## Other clients
Any client supporting remote MCP over Streamable HTTP works. For stdio-only clients use a bridge:
```bash
npx -y mcp-remote https://html-pdf.com/mcp --header "Authorization: Bearer $HTML_PDF_KEY"
```
## Prompt examples
- "Turn this invoice data into a clean A4 PDF with page numbers in the footer."
- "Generate a PDF of the weekly report as a landscape Letter page."
- "How many html-pdf credits do I have left?"
---
# Pricing
Pay once, use for years. **1 credit = 1 PDF page.** Credits never expire. No subscription.
Every new account gets **100 free credits** once you confirm your email.
| pack | pages | per page | you save | lasts at 10 pages/day |
|---|---|---|---|---|
| free | 100 | - | - | ~10 days |
| $10 | 1,000 | $0.0100 | - | ~3 months |
| $25 | 3,000 | $0.0083 | 17% | ~10 months |
| $50 | 7,000 | $0.0071 | 29% | ~2 years |
| $100 | 15,000 | $0.0067 | 33% | ~4 years |
| $250 | 50,000 | $0.0050 | 50% | ~14 years |
Need more than 50,000 pages? Buy several packs, they stack and never expire.
## How credits are counted
- A PDF with 3 pages uses 3 credits.
- Failed conversions (render errors, timeouts, `max_pages` exceeded) use 0 credits.
- A conversion needs enough credits for all its pages. If a document has more pages than your balance, you get a `402` with the page count and your balance, and nothing is charged. With auto top-up on, the document still completes and the top-up covers the difference.
- Set `max_pages` on a request to cap what it can cost.
## Never run out: auto top-up
After your first purchase, turn on **auto top-up** in the dashboard: choose a threshold (e.g. "below 200 credits") and a pack, and we charge your saved card automatically when the balance drops below it. It runs at most once every 10 minutes, and it switches itself off if a payment fails. Prefer to stay manual? You get an email when you drop below 20 credits and when you run out.
## Compared to monthly plans
Monthly plans reset unused conversions every month. Here a $10 pack of 1,000 pages lasts until you use it, whether that's next week or in three years.