Back to blog
PDF GenerationAPIWeb Development

Turning URLs into PDFs: Picking the Right API for the Job

What to look for in a generate PDF from URL API — rendering quirks, auth, performance, and code examples you can drop into production today.

2026-05-265 min read

Generating a PDF from a URL sounds trivial until you actually try it. Fonts go missing, JavaScript-heavy pages render half-empty, paywalls block your crawler, and headers spill into the body of every page. A good generate PDF from URL API handles these edge cases so you can ship invoices, reports, and archived snapshots without babysitting a headless browser fleet.

This post walks through what actually matters when choosing one, with concrete code you can paste into a project today.

Why not just run Puppeteer yourself?

Spinning up Chromium in a Lambda or a Docker container is a valid first instinct. It works fine for a prototype. Then production happens:

  • Cold starts on serverless platforms add 2–5 seconds per request.
  • Memory limits — Chromium needs 512MB minimum, often 1GB+ for complex pages.
  • Font rendering on minimal Linux images produces ugly fallbacks for anything non-Latin.
  • Concurrency — one container handles maybe 2–3 simultaneous renders before it thrashes.
  • Maintenance — Chromium ships security patches roughly every two weeks.

If you're generating more than a handful of PDFs a day, the operational cost of running your own renderer outpaces what a managed API charges. That's the calculus.

What to evaluate in a PDF API

Rendering fidelity

Test your actual pages, not the vendor's demo. Sites with lazy-loaded images, web fonts loaded from third parties, or client-side routing are where APIs differ most. Specifically check:

  • Does the API wait for networkidle or just load?
  • Can you pass a custom wait condition (selector, timeout, or JS expression)?
  • Are web fonts embedded or substituted?
  • How does it handle @media print CSS rules?

Page control

You almost always need control over paper size, margins, and orientation. Look for parameters like format (A4, Letter), landscape, margin, and printBackground. Headers and footers with page numbers should be templatable via HTML, not just static text.

Authentication and cookies

Rendering a logged-in dashboard requires either passing cookies, custom headers, or basic auth credentials. If the API can't forward these, you're stuck pre-rendering pages server-side and feeding HTML in — which defeats half the purpose.

Latency and concurrency

For user-facing flows (e.g. "Download as PDF" buttons), sub-3-second response times matter. For batch jobs, throughput matters more than per-request latency. Check whether the API supports async/webhook delivery for large jobs.

A working example with PxShot

Here's a minimal call to generate a PDF from any public URL. PxShot returns the binary directly, so you can stream it to a user or save it to S3.

curl -X GET "https://api.pxshot.dev/v1/pdf?url=https://example.com&format=A4&printBackground=true"   -H "Authorization: Bearer YOUR_API_KEY"   -o output.pdf

In Node.js, saving the result to disk:

import fs from 'fs';
import fetch from 'node-fetch';

const res = await fetch(
  'https://api.pxshot.dev/v1/pdf?url=https://example.com&format=A4',
  { headers: { Authorization: `Bearer ${process.env.PXSHOT_KEY}` } }
);

const buffer = Buffer.from(await res.arrayBuffer());
fs.writeFileSync('output.pdf', buffer);

For authenticated pages, pass cookies as a header:

const res = await fetch(
  `https://api.pxshot.dev/v1/pdf?url=${encodeURIComponent(targetUrl)}&cookies=session=abc123`,
  { headers: { Authorization: `Bearer ${process.env.PXSHOT_KEY}` } }
);

Common use cases and how to handle them

Invoices and receipts

The cleanest pattern is to render an HTML invoice on a private route (e.g. /invoices/123/print), then point the API at that URL with a signed token. Style it with a print stylesheet:

@media print {
  .no-print { display: none; }
  body { font-size: 11pt; }
  .page-break { page-break-after: always; }
}

This keeps invoice logic in your app, not in a templating service.

Reports and dashboards

Dashboards with charts (Recharts, Chart.js, D3) need a wait condition because charts render after data fetches. Use a wait-for-selector option like waitFor=.chart-loaded and add a CSS class to your container once data is ready.

Archived snapshots

For compliance or audit trails, you want a pixel-accurate snapshot of how a page looked at a specific moment. PDFs preserve text, links, and metadata in a way images don't — useful when you later need to search archived content. Combine with timestamped storage in S3 or R2.

Multi-page documents

If you need a single PDF combining multiple URLs (e.g. a customer's monthly statement plus terms), generate each PDF separately and merge with pdf-lib or pdfkit on your end. Most APIs don't merge for you.

Pricing patterns to watch for

  1. Per-request pricing is straightforward but punishes high-volume use. Typical range: $0.001–$0.01 per PDF.
  2. Tiered monthly quotas work well if your volume is predictable. Look for overage rates that don't 10x once you cross the threshold.
  3. Bandwidth fees — some vendors charge for PDF size or storage on top of generation. Read the fine print.
  4. Free tiers matter for development. You want enough headroom to test edge cases without burning credits.

PxShot's free tier is designed for exactly this kind of integration testing — enough volume to validate your rendering pipeline against real pages before you commit.

Failure modes to plan for

  • Timeouts — set a sane upper bound (15–30s) and surface a user-friendly error instead of hanging.
  • Blocked pages — sites with aggressive bot detection (Cloudflare challenges) may return a CAPTCHA page. Test your target domains before going live.
  • Oversized PDFs — a single long-scroll page can produce a 50MB PDF. Cap page count or warn users.
  • Rate limits — implement exponential backoff. Burst traffic on a Monday morning report email will hit limits otherwise.

Quick integration checklist

  1. Pick three real pages from your product, including one behind auth.
  2. Test rendering with default settings, then tweak wait conditions and margins.
  3. Compare PDF output across two or three providers — fidelity differences are real.
  4. Wire up retries and a fallback path (e.g. queue for later, email when ready).
  5. Log request IDs from the API so you can debug failures with vendor support.
  6. Set up monitoring on PDF generation latency, not just success rate.

If you want to try this end-to-end, grab a free key at pxshot.dev and run the curl example above against one of your own URLs. The free tier covers enough requests to prove out invoice generation, report exports, or whatever PDF workflow you're building before you write a line of integration code.