API Reference
The PDFRender API lets you generate PDFs and screenshots from HTML or URLs with a single HTTP request. All endpoints are served over HTTPS at:
Requests and responses use JSON, except for the /v1/pdf endpoint which returns binary PDF data in synchronous mode.
All API requests require authentication via Bearer token. Rate limits and available features depend on your plan.
Authentication
Every request must include your API key in the Authorization header:
Authorization: Bearer pk_live_xxxxxxxxxxxxxxxxAPI keys come in two flavours:
pk_live_Production key
Full access, no watermarks. Use in your production app.
pk_test_Test key
PDFs include a watermark. Use for development and testing.
You receive both keys when you register. Keys are shown only once — store them securely. You can generate additional keys by logging in.
Generate PDF
/v1/pdfRender HTML or a URL to a pixel-perfect PDF. Returns binary PDF data by default, or accepts an async webhook.
Request Body
| Parameter | Type | Description |
|---|---|---|
| source | string | HTML string to render. Provide this or url. |
| url | string | URL to navigate to and render. Provide this or source. |
| options | object | Rendering options (see below). |
Options Object
| Parameter | Type | Description |
|---|---|---|
| format | string | Page format: A4, Letter, Legal, Tabloid. Default: A4. |
| width | string | Custom width (e.g. "210mm"). Overrides format. |
| height | string | Custom height (e.g. "297mm"). Overrides format. |
| orientation | string | portrait or landscape. Default: portrait. |
| margin | object | { top, right, bottom, left } in CSS units. Default: 20mm/15mm. |
| printBackground | boolean | Include CSS backgrounds. Default: true. |
| scale | number | Scale factor 0.1–2.0. Default: 1. |
| preferCSSPageSize | boolean | Use @page CSS from HTML. Default: false. |
| waitFor | string | load | domcontentloaded | networkidle | selector. |
| waitForSelector | string | CSS selector to wait for before rendering. |
| waitForTimeout | number | Max wait time in ms. Capped by your plan limit. |
| javascript | boolean | Execute JS. Set false for faster static rendering. |
| displayHeaderFooter | boolean | Show header/footer. Default: false. |
| headerTemplate | string | HTML template for page header. |
| footerTemplate | string | HTML template for page footer. Supports <span class='pageNumber'> and <span class='totalPages'>. |
| pageRanges | string | Page range to render, e.g. "1-5" or "1,3,5". |
| css | string | Extra CSS to inject before rendering. |
| js | string | Extra JS to evaluate before rendering. |
| compress | boolean | Auto-compress PDF with Ghostscript. Growth+ plans. |
| filename | string | Filename in Content-Disposition header. Default: document.pdf. |
| webhook | string | URL for async delivery. Growth+ plans. |
| metadata | object | { title, author, subject } PDF metadata. |
Example — Synchronous
curl -X POST https://api.pdfrender.co/v1/pdf \
-H "Authorization: Bearer pk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"source": "<html><body><h1>Invoice #1042</h1><p>Amount: $250.00</p></body></html>",
"options": {
"format": "A4",
"margin": { "top": "20mm", "bottom": "20mm" },
"compress": true
}
}' \
-o invoice.pdfResponse: Binary PDF with informational headers:
Content-Type: application/pdf
Content-Disposition: attachment; filename="invoice.pdf"
X-PDFRender-Pages: 1
X-PDFRender-Size: 48210
X-PDFRender-Time: 847ms
X-RateLimit-Remaining: 97Example — Async (Webhook)
Pass a webhook URL to receive the result asynchronously. Available on Growth and Business plans.
{
"source": "<html>...</html>",
"options": {
"webhook": "https://myapp.com/webhook/pdf-done",
"compress": true
}
}{
"id": "job_abc123",
"status": "processing",
"webhook": "https://myapp.com/webhook/pdf-done"
}{
"id": "job_abc123",
"status": "completed",
"pages": 3,
"size": 145232,
"time": 1204
}Screenshot
/v1/screenshotGenerate PNG or JPEG screenshots from HTML or URLs. Same API key, same speed. Perfect for OG images, thumbnails, and visual testing.
Request Body
| Parameter | Type | Description |
|---|---|---|
| source | string | HTML string to render. Provide this or url. |
| url | string | URL to navigate to and capture. Provide this or source. |
| options | object | Screenshot options (see below). |
Options Object
| Parameter | Type | Description |
|---|---|---|
| viewport | object | { width, height, deviceScaleFactor }. Default: 1280×720 @1x. |
| type | string | Image format: png or jpeg. Default: png. |
| quality | integer | JPEG quality 0–100. Only applies when type is jpeg. |
| fullPage | boolean | Capture entire scrollable page. Default: false. |
| omitBackground | boolean | Transparent background (PNG only). Default: false. |
| darkMode | boolean | Emulate dark color scheme. Default: false. |
| clip | object | Clip region: { x, y, width, height }. |
| waitFor | string | load | domcontentloaded | networkidle | selector. |
| waitForSelector | string | CSS selector to wait for before capturing. |
| waitForTimeout | number | Max wait time in ms. Capped by your plan limit. |
| css | string | Extra CSS to inject before capturing. |
| js | string | Extra JS to evaluate before capturing. |
| filename | string | Filename in Content-Disposition header. Default: screenshot.png. |
Example
curl -X POST https://api.pdfrender.co/v1/screenshot \
-H "Authorization: Bearer pk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"options": {
"type": "png",
"viewport": { "width": 1280, "height": 720, "deviceScaleFactor": 2 },
"fullPage": false,
"darkMode": false
}
}' \
-o screenshot.pngResponse: Binary image with informational headers:
Content-Type: image/png
Content-Disposition: attachment; filename="screenshot.png"
X-PDFRender-Size: 284530
X-PDFRender-Time: 612ms
X-RateLimit-Remaining: 96Register
/v1/auth/registerCreate a new account and receive your API keys. No credit card required.
| Parameter | Type | Description |
|---|---|---|
| string | Your email address. | |
| password | string | Password (min 8 characters). |
curl -X POST https://api.pdfrender.co/v1/auth/register \
-H "Content-Type: application/json" \
-d '{"email": "dev@company.com", "password": "securepass123"}'{
"user_id": "usr_a1b2c3d4",
"email": "dev@company.com",
"plan": "free",
"api_key": "pk_live_xxxxxxxxxxxxxxxx",
"test_api_key": "pk_test_xxxxxxxxxxxxxxxx",
"message": "Save your API keys — they cannot be shown again."
}Login
/v1/auth/loginAuthenticate and generate a new API key. Existing keys remain active.
| Parameter | Type | Description |
|---|---|---|
| string | Your email address. | |
| password | string | Your password. |
{
"user_id": "usr_a1b2c3d4",
"email": "dev@company.com",
"plan": "starter",
"new_api_key": "pk_live_yyyyyyyyyyyyyyyy",
"keys": [
{ "id": "key_1", "key_prefix": "pk_live_yyyyyyyy...", "name": "Key 2026-02-17" },
{ "id": "key_2", "key_prefix": "pk_live_xxxxxxxx...", "name": "Default" }
]
}Usage
/v1/usageCheck your current billing period usage. Requires authentication.
{
"plan": "starter",
"period": {
"start": "2026-02-01",
"end": "2026-03-01"
},
"conversions": {
"used": 342,
"limit": 2000,
"remaining": 1658
},
"breakdown": [
{
"type": "pdf",
"count": 340,
"total_size": 48102400,
"avg_render_time": 723
},
{
"type": "screenshot",
"count": 2,
"total_size": 204800,
"avg_render_time": 450
}
]
}Billing Checkout
/v1/billing/checkoutCreate a Stripe Checkout session to subscribe to a paid plan. Returns a redirect URL. Requires authentication.
| Parameter | Type | Description |
|---|---|---|
| plan | string | Plan name: starter, growth, or business. |
| success_url | string | Redirect after successful payment. |
| cancel_url | string | Redirect if the user cancels. |
{
"url": "https://checkout.stripe.com/c/pay/cs_test_...",
"session_id": "cs_test_abc123",
"type": "checkout"
}If the user already has an active subscription, a Stripe Billing Portal URL is returned instead (type: "portal").
Health Check
/healthCheck service status. No authentication required.
{
"status": "ok",
"checks": {
"chromium": "ready",
"database": "ready",
"redis": "ready"
}
}Rate Limits
Rate limits are enforced per API key based on concurrent requests and monthly conversions. Current limits are returned in response headers.
| Plan | Conversions/mo | Concurrent | Timeout | Max HTML |
|---|---|---|---|---|
| Free | 100 | 2 | 30s | 1 MB |
| Starter | 2,000 | 5 | 60s | 5 MB |
| Growth | 10,000 | 10 | 120s | 10 MB |
| Business | 50,000 | 25 | 5 min | 20 MB |
Response headers include X-RateLimit-Remaining with your remaining monthly conversions. Overage on paid plans is billed at $0.005 per extra conversion.
Error Codes
All errors return a consistent JSON structure:
{
"error": {
"code": "UNAUTHORIZED",
"message": "Invalid or missing API key"
}
}| HTTP | Code | Description |
|---|---|---|
| 400 | BAD_REQUEST | Missing or invalid parameters |
| 400 | VALIDATION_ERROR | Request body failed schema validation |
| 401 | UNAUTHORIZED | Missing or invalid API key |
| 403 | FORBIDDEN | Feature not available on your plan |
| 404 | NOT_FOUND | Endpoint or resource not found |
| 429 | RATE_LIMIT_EXCEEDED | Too many concurrent requests |
| 429 | USAGE_LIMIT_EXCEEDED | Monthly conversion limit reached |
| 500 | RENDER_ERROR | PDF rendering failed |
| 500 | INTERNAL_ERROR | Unexpected server error |
SDKs
Official client libraries with TypeScript types and async support.
Node.js
npm install @pdfrender/clientimport PDFRender from '@pdfrender/client';
import fs from 'fs';
const client = new PDFRender('pk_live_xxx');
// Generate PDF from HTML
const pdf = await client.pdf({
source: '<h1>Invoice #1042</h1><p>Amount: $250</p>',
options: {
format: 'A4',
compress: true,
margin: { top: '20mm', bottom: '20mm' }
}
});
fs.writeFileSync('invoice.pdf', pdf);
// Generate PDF from URL
const report = await client.pdf({
url: 'https://myapp.com/reports/monthly',
options: { format: 'A4', waitFor: 'networkidle' }
});
fs.writeFileSync('report.pdf', report);Python
pip install pdfrenderfrom pdfrender import PDFRender
client = PDFRender('pk_live_xxx')
# Generate PDF from HTML
pdf = client.pdf(
source='<h1>Invoice #1042</h1><p>Amount: $250</p>',
options={
'format': 'A4',
'compress': True,
'margin': {'top': '20mm', 'bottom': '20mm'}
}
)
with open('invoice.pdf', 'wb') as f:
f.write(pdf)
# Async support
import asyncio
async def main():
pdf = await client.async_pdf(
source='<h1>Hello World</h1>'
)
asyncio.run(main())Need help? Contact us at hello@pdfrender.co