PDFSpark API Documentation
Convert HTML and URLs to pixel-perfect PDFs using Chromium with full JavaScript, CSS3, and web font rendering. The API is completely free — no API keys, no authentication, no signup.
https://pdfspark.dev/api/v1
Authentication
No authentication is required. Simply make HTTP requests to the endpoints below. All responses return the PDF binary directly (application/pdf).
POST /pdf/from-html
Convert raw HTML content to PDF. Supports inline CSS, JavaScript, images via data URIs or external URLs, and web fonts.
Request Body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
html |
string | required | The HTML content to convert (max 5MB) |
options |
object | optional | PDF generation options (see Options) |
Example Request
curl -X POST "https://pdfspark.dev/api/v1/pdf/from-html" \
-H "Content-Type: application/json" \
-d '{
"html": "<h1>Hello World</h1><p>Generated by PDFSpark</p>",
"options": {
"format": "A4",
"margin": { "top": "20mm", "bottom": "20mm" }
}
}' \
-o document.pdfResponse
Returns the PDF file directly as application/pdf binary. Use -o filename.pdf in cURL to save it.
POST /pdf/from-url
Convert a public webpage to PDF. The URL is loaded in Chromium with full JavaScript execution, just like a real browser.
Request Body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
url |
string | required | The URL to convert (must be http/https, no private IPs) |
options |
object | optional | PDF generation and navigation options (see Options) |
Example Request
curl -X POST "https://pdfspark.dev/api/v1/pdf/from-url" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"options": {
"format": "A4",
"printBackground": true,
"waitUntil": "networkidle"
}
}' \
-o example.pdfPOST /pdf/merge
Merge multiple PDF documents into a single PDF. Accepts an array of base64-encoded PDF strings and returns the combined document with all pages preserved in order.
Request Body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
pdfs |
string[] | required | Array of base64-encoded PDF strings (min 2, max 20, total max 50MB) |
Example Request
const pdf1 = btoa(await (await fetch('/api/v1/pdf/from-html', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ html: '<h1>Cover Page</h1>' })
})).text());
const pdf2 = btoa(await (await fetch('/api/v1/pdf/from-html', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ html: '<h1>Chapter 1</h1><p>Content...</p>' })
})).text());
const merged = await fetch('/api/v1/pdf/merge', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ pdfs: [pdf1, pdf2] })
});
const blob = await merged.blob();
// merged PDF with all pages from both documentsResponse
Returns the merged PDF as application/pdf binary with metadata headers.
POST /pdf/split
Extract specific pages from a PDF document. Accepts a base64-encoded PDF and a page range string, returns a new PDF containing only the specified pages.
Request Body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
pdf |
string | required | Base64-encoded PDF string (max 50MB) |
pages |
string | required | Page range to extract, e.g. "1-3,5,8-10". Pages are 1-indexed. |
Page Range Syntax
| Example | Description |
|---|---|
"1" | Extract only page 1 |
"1-3" | Extract pages 1 through 3 |
"1,3,5" | Extract pages 1, 3, and 5 |
"1-3,7-9" | Extract pages 1-3 and 7-9 |
"2-4,1" | Extract pages 1-4 (duplicates removed, sorted) |
Example Request
curl -X POST https://pdfspark.dev/api/v1/pdf/split \
-H "Content-Type: application/json" \
-d '{
"pdf": "<base64-encoded-pdf>",
"pages": "1-3,5"
}' \
--output extracted.pdfResponse
Returns the extracted pages as application/pdf binary with metadata headers.
POST /pdf/info
Extract metadata, page count, page dimensions, and file size from an existing PDF document. No browser required — fast, lightweight parsing using pdf-lib.
Request Body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
pdf |
string | required | Base64-encoded PDF string (max 50MB) |
Example Request
curl -X POST https://pdfspark.dev/api/v1/pdf/info \
-H "Content-Type: application/json" \
-d '{
"pdf": "<base64-encoded-pdf>"
}'Response (JSON)
{
"pages": 3,
"size": 45210,
"metadata": {
"title": "My Document",
"author": "John Doe",
"subject": "Example",
"keywords": "pdf, test",
"creator": "PDFSpark",
"producer": "pdf-lib",
"creationDate": "2026-01-15T10:30:00.000Z",
"modificationDate": "2026-03-01T14:00:00.000Z"
},
"pageDimensions": [
{ "page": 1, "width": 595.28, "height": 841.89 },
{ "page": 2, "width": 595.28, "height": 841.89 },
{ "page": 3, "width": 841.89, "height": 595.28 }
],
"processingDurationMs": 12
}Response Metadata Headers
All PDF endpoints (/pdf/from-html, /pdf/from-url, /pdf/merge, /pdf/split) include these metadata headers in successful responses for observability and integration with monitoring tools:
| Header | Type | Description |
|---|---|---|
X-Render-Duration-Ms | number | Time taken to generate or merge the PDF in milliseconds |
X-Page-Count | number | Total number of pages in the resulting PDF |
X-Pdf-Size-Bytes | number | Size of the PDF file in bytes |
X-Render-Duration-Ms to track performance and X-Page-Count to verify document completeness.
GET /status
Returns service status and available endpoints.
{
"service": "PDFSpark",
"version": "1.0.0",
"status": "operational",
"endpoints": [
{ "method": "POST", "path": "/api/v1/pdf/from-html" },
{ "method": "POST", "path": "/api/v1/pdf/from-url" },
{ "method": "POST", "path": "/api/v1/pdf/merge" },
{ "method": "POST", "path": "/api/v1/pdf/split" },
{ "method": "POST", "path": "/api/v1/pdf/info" },
{ "method": "GET", "path": "/api/v1/status" }
]
}Page Format Options
| Option | Type | Default | Description |
|---|---|---|---|
format | string | "A4" | Page format: A3, A4, A5, Letter, Legal, Tabloid |
width | string | — | Custom page width (e.g. "8.5in"). Overrides format. |
height | string | — | Custom page height (e.g. "11in"). Overrides format. |
landscape | boolean | false | Landscape orientation |
printBackground | boolean | true | Print background graphics and colors |
scale | number | 1 | Scale factor (0.1 to 2.0) |
pageRanges | string | "" | Page ranges to print (e.g. "1-3, 5") |
preferCSSPageSize | boolean | false | Use CSS @page size instead of format |
Margin Options
| Option | Type | Default | Description |
|---|---|---|---|
margin.top | string | "10mm" | Top margin (CSS units: mm, in, px, cm) |
margin.right | string | "10mm" | Right margin |
margin.bottom | string | "10mm" | Bottom margin |
margin.left | string | "10mm" | Left margin |
Header & Footer Options
| Option | Type | Default | Description |
|---|---|---|---|
displayHeaderFooter | boolean | false | Enable header and footer |
headerTemplate | string | "" | HTML template for header. Supports: date, title, url, pageNumber, totalPages |
footerTemplate | string | "" | HTML template for footer (same classes as header) |
<span class="pageNumber"></span>, <span class="totalPages"></span>, <span class="date"></span>, <span class="title"></span>, <span class="url"></span>.
Navigation Options (URL mode)
| Option | Type | Default | Description |
|---|---|---|---|
waitUntil | string | "domcontentloaded" | load, domcontentloaded, or networkidle |
waitForSelector | string | — | Wait for a CSS selector to appear before PDF generation |
delay | number | 0 | Additional delay in ms after page load (max 10000) |
timeout | number | 30000 | Navigation timeout in ms (max 60000) |
css | string | — | Custom CSS to inject before PDF generation |
javascript | boolean | true | Enable/disable JavaScript execution |
viewport.width | number | 1280 | Viewport width in pixels |
viewport.height | number | 720 | Viewport height in pixels |
Custom HTTP Headers (URL mode)
Pass custom HTTP headers to the target URL when using /pdf/from-url. Useful for accessing authenticated pages or passing API tokens.
| Option | Type | Default | Description |
|---|---|---|---|
headers | object | {} | Key-value pairs of HTTP headers sent with the page request. Max 20 headers. |
Host, Cookie, Set-Cookie, Origin, Referer, Proxy-Authorization, Transfer-Encoding, Content-Length.
Example: Authenticated URL
curl -X POST "https://pdfspark.dev/api/v1/pdf/from-url" \
-H "Content-Type: application/json" \
-d '{
"url": "https://app.example.com/dashboard",
"options": {
"headers": {
"Authorization": "Bearer eyJhbGci...",
"X-Custom-Header": "my-value"
},
"waitUntil": "networkidle"
}
}' \
-o dashboard.pdfMedia Type Emulation
Control which CSS @media rules apply during PDF generation. Use "print" to activate print stylesheets for cleaner, ink-friendly PDFs, or "screen" to force screen styles.
| Option | Type | Default | Description |
|---|---|---|---|
emulateMediaType | string | — | "print" or "screen". When set, triggers the corresponding CSS @media rules. |
@media print stylesheets that hide navigation, ads, and non-essential elements. Use "print" to generate cleaner PDFs automatically.
Example: Print-optimized PDF
curl -X POST "https://pdfspark.dev/api/v1/pdf/from-url" \
-H "Content-Type: application/json" \
-d '{
"url": "https://en.wikipedia.org/wiki/PDF",
"options": {
"emulateMediaType": "print",
"format": "A4"
}
}' \
-o article.pdfPDF Metadata
Set document properties (title, author, subject, keywords) that appear in PDF reader info panels. PDFs without metadata show as “Untitled” in most readers.
| Option | Type | Max Length | Description |
|---|---|---|---|
metadata.title | string | 500 chars | Document title shown in PDF reader title bar |
metadata.author | string | 200 chars | Document author |
metadata.subject | string | 500 chars | Document subject/description |
metadata.keywords | string[] | 20 items | Array of keyword strings for document discovery |
metadata.creator | string | 200 chars | Application that created the content |
metadata.producer | string | 200 chars | Application that produced the PDF |
Example: Invoice with metadata
curl -X POST "https://pdfspark.dev/api/v1/pdf/from-html" \
-H "Content-Type: application/json" \
-d '{
"html": "<h1>Invoice #1234</h1><p>Total: $99.00</p>",
"options": {
"format": "A4",
"metadata": {
"title": "Invoice #1234",
"author": "Acme Corp",
"subject": "Monthly invoice for March 2026",
"keywords": ["invoice", "acme", "march-2026"],
"creator": "Acme Billing System"
}
}
}' \
-o invoice.pdfText Watermark
Add a diagonal text watermark across every page of the generated PDF. Useful for marking documents as “DRAFT”, “CONFIDENTIAL”, “COPY”, or “PAID”.
| Option | Type | Default | Description |
|---|---|---|---|
watermark.text | string | — | Watermark text (required, max 200 chars) |
watermark.fontSize | number | 48 | Font size in points (8–200) |
watermark.opacity | number | 0.3 | Opacity (0.01–1.0) |
watermark.rotation | number | -45 | Rotation angle in degrees (-360 to 360) |
watermark.color | object | {r:0.5, g:0.5, b:0.5} | RGB color with values 0–1 (e.g. {r:1, g:0, b:0} for red) |
Example: Draft watermark
curl -X POST "https://pdfspark.dev/api/v1/pdf/from-html" \
-H "Content-Type: application/json" \
-d '{
"html": "<h1>Invoice #1234</h1><p>Total: $99.00</p>",
"options": {
"format": "A4",
"watermark": {
"text": "DRAFT",
"fontSize": 72,
"opacity": 0.15,
"rotation": -45,
"color": { "r": 1, "g": 0, "b": 0 }
}
}
}' \
-o draft-invoice.pdfImage Watermark
Overlay a PNG or JPEG image on every page of the generated PDF. Ideal for company logos, approval stamps, “CONFIDENTIAL” badges, or branding marks.
| Option | Type | Default | Description |
|---|---|---|---|
imageWatermark.image | string | — | Base64-encoded PNG or JPEG image data (required, max 2MB) |
imageWatermark.type | string | "png" | Image format: "png" or "jpg" |
imageWatermark.opacity | number | 0.3 | Opacity (0.01–1.0) |
imageWatermark.scale | number | 0.5 | Scale factor (0.1–5.0). 1.0 = original image size. |
imageWatermark.position | string | "center" | Placement on page: "center", "top-left", "top-right", "bottom-left", "bottom-right" |
Example: Logo watermark
curl -X POST "https://pdfspark.dev/api/v1/pdf/from-html" \
-H "Content-Type: application/json" \
-d '{
"html": "<h1>Quarterly Report</h1><p>Company results...</p>",
"options": {
"format": "A4",
"imageWatermark": {
"image": "<base64-encoded-png>",
"type": "png",
"opacity": 0.15,
"scale": 0.3,
"position": "bottom-right"
}
}
}' \
-o branded-report.pdfPassword Protection
Encrypt the generated PDF with a password. Recipients must enter the password to open the document. Supports AES-256 (recommended) and RC4 128-bit (legacy readers) encryption.
| Option | Type | Default | Description |
|---|---|---|---|
password.userPassword | string | — | Password required to open the PDF (required, max 128 chars) |
password.ownerPassword | string | same as user | Password for managing permissions (editing restrictions) |
password.algorithm | string | "AES-256" | "AES-256" (PDF 2.0, recommended) or "RC4" (128-bit, legacy readers) |
password.permissions.printing | boolean | true | Allow printing the document |
password.permissions.copying | boolean | true | Allow copying text and images |
password.permissions.modifying | boolean | true | Allow modifying content |
password.permissions.annotating | boolean | true | Allow adding annotations |
password.permissions.fillingForms | boolean | true | Allow filling in forms |
password.permissions.extraction | boolean | true | Allow accessibility text extraction |
password.permissions.assembly | boolean | true | Allow document assembly |
Example: Password-protected PDF
curl -X POST "https://pdfspark.dev/api/v1/pdf/from-html" \
-H "Content-Type: application/json" \
-d '{
"html": "<h1>Confidential Report</h1><p>Q1 Financial Summary</p>",
"options": {
"format": "A4",
"password": {
"userPassword": "secret123",
"ownerPassword": "admin456",
"algorithm": "AES-256",
"permissions": {
"printing": true,
"copying": false,
"modifying": false
}
}
}
}' \
-o confidential-report.pdf/pdf/from-html and /pdf/from-url endpoints. Use "AES-256" for maximum security (PDF 2.0 standard). Use "RC4" only if recipients use older PDF readers that don’t support AES.
Output Options
Control the output filename and response format for all PDF endpoints.
| Option | Type | Default | Description |
|---|---|---|---|
filename | string | "document.pdf" | Custom filename for Content-Disposition header (max 255 chars). Auto-appends .pdf if missing. Unsafe characters are sanitized. |
responseFormat | string | "binary" | "binary" returns PDF as application/pdf. "base64" returns a JSON object with the PDF encoded as a base64 string. |
Base64 Response Format
When responseFormat is set to "base64", the response is a JSON object instead of binary PDF:
{
"data": "JVBERi0xLjcK...",
"filename": "invoice.pdf",
"pages": 1,
"size": 24576,
"renderDurationMs": 320
}filename and responseFormat options work on all PDF endpoints: /pdf/from-html, /pdf/from-url, /pdf/merge, and /pdf/split.
Example: Custom filename with base64
curl -X POST "https://pdfspark.dev/api/v1/pdf/from-html" \
-H "Content-Type: application/json" \
-d '{
"html": "<h1>Invoice #1234</h1><p>Total: $99.00</p>",
"options": {
"format": "A4",
"filename": "invoice-1234.pdf",
"responseFormat": "base64"
}
}'Error Codes
| Status | Meaning |
|---|---|
400 | Bad Request — Missing or invalid input (HTML, URL, or options) |
404 | Not Found — Endpoint does not exist |
413 | Payload Too Large — HTML exceeds 5MB, or merged/split PDFs exceed 50MB |
422 | Unprocessable Entity — PDFs in merge/split request could not be parsed, or invalid page range |
429 | Too Many Requests — Rate limit exceeded (20/min) |
500 | Internal Server Error — PDF generation failed |
503 | Service Unavailable — Server busy (too many concurrent requests) |
Error responses are JSON:
{
"error": "Missing HTML",
"message": "Provide an \"html\" field in the request body"
}Rate Limits
| Limit | Value |
|---|---|
| Requests per minute | 20 per IP address |
| Max concurrent PDFs | 5 server-wide |
| Max HTML size | 5MB |
| Navigation timeout | 60s max |
RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset.
cURL Examples
# Convert HTML to PDF
curl -X POST "https://pdfspark.dev/api/v1/pdf/from-html" \
-H "Content-Type: application/json" \
-d '{"html": "<h1>Invoice #1234</h1><p>Total: $99.00</p>"}' \
-o invoice.pdf
# Convert URL to PDF (landscape A3)
curl -X POST "https://pdfspark.dev/api/v1/pdf/from-url" \
-H "Content-Type: application/json" \
-d '{
"url": "https://github.com",
"options": { "format": "A3", "landscape": true }
}' \
-o github.pdfJavaScript Example
// Convert HTML to PDF
const response = await fetch('https://pdfspark.dev/api/v1/pdf/from-html', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
html: '<h1>Hello World</h1><p>From PDFSpark</p>',
options: { format: 'A4', margin: { top: '20mm', bottom: '20mm' } }
})
});
const blob = await response.blob();
const url = URL.createObjectURL(blob);
window.open(url); // or save with a download link
// Convert URL to PDF
const urlResponse = await fetch('https://pdfspark.dev/api/v1/pdf/from-url', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ url: 'https://example.com' })
});
const pdfBlob = await urlResponse.blob();
// Use pdfBlob as needed...Python Example
import requests
# Convert HTML to PDF
response = requests.post(
'https://pdfspark.dev/api/v1/pdf/from-html',
json={
'html': '<h1>Invoice #1234</h1><p>Total: $99.00</p>',
'options': {'format': 'A4', 'printBackground': True}
}
)
with open('invoice.pdf', 'wb') as f:
f.write(response.content)
# Convert URL to PDF
response = requests.post(
'https://pdfspark.dev/api/v1/pdf/from-url',
json={'url': 'https://example.com'}
)
with open('example.pdf', 'wb') as f:
f.write(response.content)MCP Integration
PDFSpark ships with a built-in Model Context Protocol (MCP) server. Connect PDFSpark directly to Claude, VS Code, Cursor, or any MCP-compatible AI client to generate PDFs from your assistant.
Installation
Add the following to your MCP client configuration:
{
"mcpServers": {
"pdfspark": {
"command": "npx",
"args": ["-y", "pdfspark-api"]
}
}
}Available Tools
| Tool | Description | Parameters |
|---|---|---|
html_to_pdf |
Convert raw HTML content to a PDF document | html (string, required), format, landscape, margin, printBackground, scale, pageRanges, displayHeaderFooter, headerTemplate, footerTemplate |
url_to_pdf |
Convert a public webpage URL to a PDF document | url (string, required), format, landscape, margin, printBackground, scale, pageRanges, waitUntil, delay, timeout |
Environment Variables
| Variable | Default | Description |
|---|---|---|
PDFSPARK_BASE_URL |
https://pdfspark.dev |
Override the base URL for API requests (e.g., for self-hosted instances) |