Browser Rendering
PDF API
Generate PDFs from any webpage with Cloudflare Browser Rendering - HTML/URL to PDF API at the edge
Generate a PDF from any URL using Browser Rendering and Puppeteer's page.pdf() API.
API Reference
GET /pdf
Renders the specified URL in a headless browser and returns a PDF document.
Prop
Type
Example Request
curl "https://your-worker.workers.dev/pdf?url=https://www.cloudflare.com" \
--output page.pdfSuccess Response
Returns a PDF file with the following headers:
Content-Type: application/pdf
Cache-Control: public, max-age=60Error Response
{
"error": "Missing or invalid query parameter: url",
"code": "INVALID_URL"
}Error Codes
400- Missing or invalidurlparameter (not http/https)502- PDF generation failed (PDF_ERROR)
Use Cases
- Convert web pages to printable PDF documents
- Archive rendered page content with styles
- Generate invoices or reports from HTML pages
- Learn Browser Rendering PDF generation with Workers bindings
Limitations
- Requires Browser Rendering enabled on your Cloudflare account
- Local development needs
npx wrangler dev --remote - Navigation timeout; complex or infinite-scroll pages may fail
- Fixed viewport; no PDF margin, format, or page-size options
Use in your project
Copy these files into an existing Worker. Prefer Deployment to try the full experiment first. Source: apps/experiments/pdf-api.
DependenciesNoneBindingsBrowser RenderingPlatformWorkers runtime
import puppeteer from "@cloudflare/puppeteer";import type { Page } from "@cloudflare/puppeteer";import { DEFAULT_VIEWPORT, NAVIGATION_TIMEOUT_MS } from "../constants/defaults";export async function withBrowserPage<T>( browserBinding: Fetcher, url: string, fn: (page: Page) => Promise<T>): Promise<T> { let browser: Awaited<ReturnType<typeof puppeteer.launch>> | null = null; try { browser = await puppeteer.launch(browserBinding); const page = await browser.newPage(); await page.setViewport(DEFAULT_VIEWPORT); await page.goto(url, { waitUntil: "networkidle0", timeout: NAVIGATION_TIMEOUT_MS, }); return await fn(page); } finally { if (browser) { try { await browser.close(); } catch { /* ignore close errors */ } } }}export async function generatePdf(browserBinding: Fetcher, url: string): Promise<Uint8Array> { return withBrowserPage(browserBinding, url, async (page) => { const pdf = await page.pdf({ printBackground: true }); return new Uint8Array(pdf); });}Deployment
Enable Browser Rendering
This experiment requires Browser Rendering on your Cloudflare account. See the Browser Rendering docs.
Test your deployment
curl "https://your-worker.workers.dev/pdf?url=https://www.cloudflare.com" \
--output page.pdfLocal Development
cd apps/experiments/pdf-api
npm install
npm run devnpm run dev uses wrangler dev --remote so a real browser instance is available. Local dev without --remote will not work.
Test locally:
curl "http://localhost:8787/pdf?url=https://www.cloudflare.com" --output test.pdfCloudflare Features Used
- Workers - Edge compute runtime
- Browser Rendering - Headless Chromium via
@cloudflare/puppeteer - Puppeteer
page.pdf()- PDF generation from rendered pages