← GrabShot Blog

Website to PDF API: Convert Any URL to PDF Programmatically

February 19, 2026 · 10 min read

You need to turn a web page into a PDF. Maybe it's for archiving, generating reports, creating invoices from a dashboard, or letting users download a "print-friendly" version of your content. Whatever the reason, you have two broad options: run a headless browser yourself, or call a website to PDF API.

This guide covers both approaches with working code, then explains when each one makes sense.

Why Converting Websites to PDF Is Harder Than It Looks

On the surface, "save as PDF" sounds trivial. In practice, you run into a long list of edge cases:

A good website to PDF API handles all of this for you. If you self-host, you'll need to solve each problem yourself.

Option 1: Use a Website to PDF API

The fastest path. Send a URL (or raw HTML), get a PDF back. No browser infrastructure to manage.

curl

curl "https://pdf.grabshot.dev/v1/pdf?url=https://example.com&format=A4&margin=20mm" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -o output.pdf

That's it. The API spins up a Chromium instance, loads the page, waits for fonts and images, and returns a PDF. You get a production-quality document without installing anything.

Node.js

const fs = require('fs');

async function websiteToPdf(url) {
  const apiKey = process.env.GRABSHOT_API_KEY;
  const params = new URLSearchParams({
    url,
    format: 'A4',
    margin: '20mm',
    printBackground: 'true'
  });

  const res = await fetch(
    `https://pdf.grabshot.dev/v1/pdf?${params}`,
    { headers: { 'X-Api-Key': apiKey } }
  );

  if (!res.ok) throw new Error(`PDF API error: ${res.status}`);

  const buffer = Buffer.from(await res.arrayBuffer());
  fs.writeFileSync('output.pdf', buffer);
  console.log('PDF saved: output.pdf');
}

websiteToPdf('https://example.com');

Python

import requests
import os

def website_to_pdf(url: str, output: str = "output.pdf"):
    api_key = os.environ["GRABSHOT_API_KEY"]
    response = requests.get(
        "https://pdf.grabshot.dev/v1/pdf",
        params={
            "url": url,
            "format": "A4",
            "margin": "20mm",
            "printBackground": "true",
        },
        headers={"X-Api-Key": api_key},
    )
    response.raise_for_status()

    with open(output, "wb") as f:
        f.write(response.content)
    print(f"PDF saved: {output}")

website_to_pdf("https://example.com")

Option 2: Self-Hosted with Puppeteer

If you want full control (or you're converting hundreds of thousands of pages per month), running Puppeteer yourself is the way to go.

const puppeteer = require('puppeteer');

async function urlToPdf(url) {
  const browser = await puppeteer.launch({
    headless: 'new',
    args: ['--no-sandbox', '--disable-setuid-sandbox']
  });
  const page = await browser.newPage();

  await page.goto(url, { waitUntil: 'networkidle0', timeout: 30000 });

  const pdfBuffer = await page.pdf({
    format: 'A4',
    margin: { top: '20mm', bottom: '20mm', left: '15mm', right: '15mm' },
    printBackground: true
  });

  require('fs').writeFileSync('output.pdf', Buffer.from(pdfBuffer));
  await browser.close();
}

urlToPdf('https://example.com');

This works, but now you're responsible for:

Converting Raw HTML to PDF

Sometimes you don't have a URL. You have an HTML string — an invoice template, a report, an email receipt. Most PDF APIs accept raw HTML too:

curl -X POST "https://pdf.grabshot.dev/v1/pdf" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "html": "<h1>Invoice #1042</h1><p>Amount: $299.00</p>",
    "format": "A4",
    "margin": "20mm"
  }' \
  -o invoice.pdf

This is particularly useful for invoice generation, ticket PDFs, and report exports where you're building the HTML from a template engine (Handlebars, Jinja2, EJS).

For a deeper dive into invoice generation specifically, see our guide on generating PDF invoices with Node.js.

Advanced Options You'll Actually Use

Most website to PDF APIs expose options that map to Chromium's PDF generation. Here are the ones that matter:

OptionWhat it doesExample
formatPaper sizeA4, Letter, Legal
marginPage margins20mm, 0.5in
printBackgroundInclude CSS backgroundstrue (default: false in most browsers)
landscapeOrientationtrue for wide tables/dashboards
scaleZoom level0.8 to fit more content per page
headerTemplateCustom header HTMLCompany logo, page numbers
footerTemplateCustom footer HTML<span class="pageNumber"></span>
waitForWait for selector/timeout#chart-loaded or 3000 (ms)

Common Use Cases

1. Report Generation

Build a dashboard page, convert it to PDF, email it to stakeholders every Monday morning. This is probably the most common use case for website to PDF APIs. You design the report once in HTML/CSS (which is much easier than fighting with PDF libraries), then convert it.

2. Archiving and Compliance

Regulated industries need to archive web content as it appeared at a specific point in time. A PDF is a legally recognized document format. Screenshot APIs give you visual proof; PDF APIs give you selectable text and proper pagination.

3. E-commerce Receipts

Generate a PDF receipt from an HTML template after each purchase. Attach it to the confirmation email. Customers love having a proper PDF instead of "view receipt in browser."

4. Content Export

Let users download articles, documentation, or course materials as PDF. Add a "Download as PDF" button that hits your backend, which calls the PDF API and streams the result back.

API vs Self-Hosted: When to Use Which

PDF APISelf-Hosted Puppeteer
Setup time5 minutes1-2 hours
MaintenanceNoneOngoing (updates, crashes, scaling)
Cost at low volumeFree tier or ~$9/moServer costs ($5-20/mo minimum)
Cost at high volumeCan get expensiveCheaper per-PDF
CustomizationAPI parametersFull Chromium control
Best forMost teams, MVPs, steady volumeHigh volume, custom rendering needs

If you're converting fewer than 10,000 PDFs per month, an API is almost always the right call. The engineering time you save pays for itself many times over.

Tips for Better PDF Output

  1. Always set printBackground: true — without it, your carefully designed backgrounds and colored sections disappear.
  2. Use @media print CSS — hide navigation, footers, cookie banners. Add page-break-before and page-break-inside: avoid to control pagination.
  3. Test with real content — PDFs that look perfect with placeholder text often break with real data (long names, large tables, missing images).
  4. Set explicit widths — responsive layouts can produce unexpected results in PDF. Consider a fixed-width layout for your PDF template.
  5. Wait for dynamic content — if your page has charts (Chart.js, D3) or lazy images, use the waitFor parameter to ensure everything renders before conversion.

Try PDFMagic by GrabShot

Convert any URL or HTML to PDF with a single API call. Free tier included.

Get Your API Key →

Wrapping Up

Converting websites to PDF programmatically is a solved problem in 2026. If you want speed and simplicity, use a website to PDF API like PDFMagic. If you need maximum control and you're running at scale, self-host Puppeteer.

Either way, the key is handling the edge cases: JavaScript rendering, font loading, print stylesheets, and proper pagination. Get those right and your PDFs will look professional every time.

For screenshot capture instead of PDF, check out our screenshot API playground or read the guide on capturing screenshots programmatically.