HTML → PDF

Developer API Docs

Programmatic HTML to PDF conversion. Free tier: 10 conversions. Premium: $5 AUD/year for unlimited.

Overview

The programmatic API converts HTML to PDF and returns hosted URLs to the generated files. It's designed for developers who need PDF generation embedded in their applications, scripts, or pipelines.

Base URL
https://www.htmltopdfconverter.com.au
Auth
Bearer JWT (API key)
Free tier
10 conversions, 1 API key
Premium
$5 AUD/year — unlimited
Rate limit
10 requests/minute per user

Free tier

Every new account includes 10 free API conversions and the ability to generate 1 API key — no payment required. This lets you evaluate the API in your own workflow before committing to a subscription.

FreePremium ($5 AUD/yr)
API keys1Unlimited
Conversions10 totalUnlimited
Rate limit10 req/min10 req/min
Key generationDashboard or APIDashboard or API

Once you exhaust your free conversions, subscribe via the Dashboard to continue using the API.

Getting started

1. Sign up

Create a free account at htmltopdfconverter.com.au/auth/signup. You'll immediately receive 10 free API conversions.

Required: name, email, password (min 12 characters).

2. Generate an API key

You can generate a key in two ways:

  • Dashboard: Click Generate New API Key on your Dashboard
  • Programmatically: POST /api/programmatic/api-key/generate with your email and password (see below)
  • Keys are valid for 7 days
  • Free tier: 1 key. Premium: unlimited keys
  • Old keys can be revoked from the Dashboard

Store your key securely. It cannot be retrieved after the page closes — if you lose it, generate a new one.

3. Convert HTML to PDF

Use your API key to call POST /api/programmatic/pdf/generate. See the endpoint docs and code examples below.

4. Upgrade to Premium (optional)

Once you've used your 10 free conversions, go to your Dashboard and click Subscribe Now. The annual plan is $5 AUD/year for unlimited conversions and unlimited API keys.

Authentication

All programmatic API requests require a valid API key passed as a Bearer token in the Authorization header:

Authorization: Bearer <your_api_key>

Requests without this header, or with an expired or revoked key, return 401 Unauthorized.

POST /api/programmatic/api-key/generate

Generate an API key programmatically using your account credentials. This enables a fully scriptable two-step workflow: generate a key, then use it to convert PDFs.

No Bearer token neededEmail + password auth

Request

POST /api/programmatic/api-key/generate
Content-Type: application/json

{
  "email": "you@example.com",
  "password": "your_password"
}

Response — 200 OK

{
  "apiKey": "eyJhbGciOiJIUzI1NiIs...",
  "expiresAt": "2026-03-15T12:00:00.000Z",
  "expiresIn": "7 days",
  "message": "JWT API key generated successfully"
}

cURL example:

curl -X POST https://www.htmltopdfconverter.com.au/api/programmatic/api-key/generate \
  -H "Content-Type: application/json" \
  -d '{"email":"you@example.com","password":"your_password"}'
StatusReason
400Missing email or password
401Invalid credentials
403Free trial exhausted or free-tier key limit reached (1 key)
500Internal server error

POST /api/programmatic/pdf/generate

Converts one or more HTML files to PDF. Returns hosted URLs to the generated PDFs.

Auth requiredBearer token (free tier or active subscription)

Option A — Multipart file upload

Send one or more .html or .htm files as multipart/form-data. Optionally include an options form field containing a JSON object to control the output (see PDF options).

POST /api/programmatic/pdf/generate
Authorization: Bearer <your_api_key>
Content-Type: multipart/form-data

files: invoice.html
files: report.html
options: {"format":"A4","orientation":"portrait","margins":"normal","scale":1}

Constraints:

  • Field name must be files
  • HTML files only (.html / .htm)
  • Maximum 10 files per request
  • Maximum 50 MB per file
  • The options field is optional; any omitted keys fall back to their defaults

cURL example:

curl -X POST https://www.htmltopdfconverter.com.au/api/programmatic/pdf/generate \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "files=@invoice.html" \
  -F "files=@report.html" \
  -F 'options={"format":"Letter","orientation":"landscape","margins":"wide","scale":1}'

Option B — Raw HTML body

Send raw HTML as the request body with Content-Type: text/html. With this mode, pass output options as query-string parameters instead of a JSON field.

POST /api/programmatic/pdf/generate?format=Letter&orientation=landscape&margins=wide&scale=1
Authorization: Bearer <your_api_key>
Content-Type: text/html

<!DOCTYPE html>
<html><body><h1>Hello, PDF</h1></body></html>

cURL example:

curl -X POST "https://www.htmltopdfconverter.com.au/api/programmatic/pdf/generate?format=Letter&orientation=landscape&margins=wide&scale=1" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: text/html" \
  --data-binary @invoice.html

PDF options

All options are optional. In multipart requests they go in the options JSON field; with a raw HTML body they go in the query string.

OptionValuesDefault
formatA4 | Letter | Legal | A3A4
orientationportrait | landscapeportrait
marginsnone (0) | tight (6mm) | normal (12mm) | wide (25mm)normal (12mm)
scale0.1 – 21

Responses

Success — 200 OK

{
  "success": true,
  "pdfs": [
    {
      "filename": "invoice_1234567890.pdf",
      "url": "https://blob.vercel-storage.com/..."
    },
    {
      "filename": "report_9876543210.pdf",
      "url": "https://blob.vercel-storage.com/..."
    }
  ]
}

url points to the generated PDF hosted on Vercel Blob at an unguessable public URL. Download it promptly and store it in your own storage if you need long-term or guaranteed access — treat the returned URL as a delivery link rather than permanent hosting.

Error responses

StatusReason
400Validation error — no files, empty HTML body, more than 10 files, a non-HTML file, or a file over 50 MB (message echoes the specific error)
401Missing, invalid, expired or revoked API key; or subscription inactive and free trial exhausted
403Free tier — requested more files than free conversions remaining
415Unsupported Content-Type (must be multipart/form-data or text/html)
429Rate limit exceeded (10 requests/minute)
500Internal server error during PDF generation

API key lifecycle

EventDetail
GeneratedVia Dashboard or POST /api/programmatic/api-key/generate
Expiry7 days from creation (JWT exp claim)
RevocationDelete from Dashboard at any time
Re-generationPremium: generate unlimited keys. Free: 1 key at a time
Free tier limit10 total conversions; key still works until conversions are exhausted or key expires
Subscription lapseKey validation fails when subscription becomes inactive and free conversions are exhausted

PDF rendering details

PropertyValue
EnginePuppeteer + Chromium
Page sizeA4 (default), Letter, Legal or A3 — see PDF options
OrientationPortrait (default) or landscape
Marginsnone / tight / normal (default) / wide
Scale0.1–2 (default 1)
CSS supportFull — flexbox, grid, custom fonts, media queries, backgrounds
ImagesInline and base64 data URIs supported
JavaScriptExecuted before capture — dynamic content renders

Rate limits

  • 10 requests/minute per user
  • Limit is keyed to your user account, not IP address
  • Exceeding the limit returns 429 Too Many Requests
  • The window resets every 60 seconds

Code examples

Two-step workflow (cURL)

Generate a key and convert a PDF in two commands — no browser needed.

# Step 1 — Generate an API key
API_KEY=$(curl -s -X POST https://www.htmltopdfconverter.com.au/api/programmatic/api-key/generate \
  -H "Content-Type: application/json" \
  -d '{"email":"you@example.com","password":"your_password"}' \
  | jq -r '.apiKey')

# Step 2 — Convert HTML to PDF (with optional output options)
curl -X POST https://www.htmltopdfconverter.com.au/api/programmatic/pdf/generate \
  -H "Authorization: Bearer $API_KEY" \
  -F "files=@invoice.html" \
  -F 'options={"format":"A4","orientation":"portrait","margins":"normal","scale":1}'

Node.js (fetch)

Uses the native FormData and Blob globals available in Node 18+. Do not set Content-Type yourself — fetch adds the multipart boundary automatically.

const fs = require("fs/promises");

const html = await fs.readFile("invoice.html", "utf8");

const form = new FormData();
form.append("files", new Blob([html], { type: "text/html" }), "invoice.html");

// Optional: control the output. Omit to use defaults (A4, portrait, normal, scale 1).
form.append(
  "options",
  JSON.stringify({
    format: "A4",
    orientation: "portrait",
    margins: "normal",
    scale: 1,
  })
);

const response = await fetch(
  "https://www.htmltopdfconverter.com.au/api/programmatic/pdf/generate",
  {
    method: "POST",
    headers: {
      Authorization: "Bearer YOUR_API_KEY",
    },
    body: form,
  }
);

const { pdfs } = await response.json();
console.log(pdfs[0].url); // publicly accessible PDF URL

Python (requests)

import json
import requests

with open("invoice.html", "rb") as f:
    response = requests.post(
        "https://www.htmltopdfconverter.com.au/api/programmatic/pdf/generate",
        headers={"Authorization": "Bearer YOUR_API_KEY"},
        files={"files": ("invoice.html", f, "text/html")},
        # Optional output options (omit to use defaults)
        data={"options": json.dumps({
            "format": "A4",
            "orientation": "portrait",
            "margins": "normal",
            "scale": 1,
        })},
    )

data = response.json()
print(data["pdfs"][0]["url"])

PHP (cURL)

<?php
$ch = curl_init("https://www.htmltopdfconverter.com.au/api/programmatic/pdf/generate");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer YOUR_API_KEY"]);
curl_setopt($ch, CURLOPT_POSTFIELDS, [
    "files" => new CURLFile("invoice.html"),
    // Optional output options (omit to use defaults)
    "options" => json_encode([
        "format" => "A4",
        "orientation" => "portrait",
        "margins" => "normal",
        "scale" => 1,
    ]),
]);

$response = json_decode(curl_exec($ch), true);
curl_close($ch);

echo $response["pdfs"][0]["url"];

Ready to start?

Try 10 free conversions — no credit card required. Then $5 AUD/year for unlimited.