Skip to content
PDF API · Use case

Generate thousands of PDFs from URLs without running browsers

Bulk PDF generation usually arrives as a deadline: month-end statements, event certificates, a report per customer, a catalog per region. Running a headless browser fleet for one night a month is expensive and fragile. The PDF API takes the batch as parallel requests and returns a hosted document for each URL.

The problem

Bulk PDF generation breaks self-hosted browser pools

Ten thousand renders in an hour needs dozens of Chrome instances, memory to match, and a queue that survives crashes. One page with a runaway script stalls a worker, a leaked tab eats the instance, and the job that was meant to finish overnight is still running when customers log in.

Most teams build that pool once, watch it fail at the next peak, and rebuild it with more capacity that idles the rest of the month. PDF libraries that skip the browser avoid the fleet, and also skip the CSS, the fonts and the charts that made the page worth printing.

Microlink applies no throttling, so the batch runs as fast as your quota allows, in parallel. Each render gets its own isolated browser and a 60-second budget on Pro plans, transient failures are retried server-side with retry, and documents you request again are served from the cache.

How it works

How to generate PDFs in bulk from a list of URLs

The batch is a map over URLs. Concurrency, retries and caching are request options, not infrastructure. The production patterns guide covers rate-limit headers and backoff for long jobs.

1 · Render a batch in parallel
import createClient from 'microlink.io'

const microlink = createClient({
  apiKey: process.env.MICROLINK_API_KEY
})

const customers = await loadCustomers()

const documents = await Promise.all(
  customers.map(({ id }) =>
    microlink.pdf(`https://app.example.com/statements/${id}`, {
      headers: {
        'x-api-header-authorization': `Bearer ${process.env.APP_TOKEN}`
      },
      filename: `statement-${id}.pdf`,
      retry: 3
    })
  )
)

One request per document. The bearer token travels as a forwarded header, filename makes the output self-describing, and retry: 3 re-runs intermittent browser errors with exponential backoff. Each result carries the hosted url and the file size.

2 · Bound the concurrency on your side
import createClient from 'microlink.io'

const microlink = createClient({
  apiKey: process.env.MICROLINK_API_KEY
})

const pool = async (items, limit, worker) => {
  const results = []
  let cursor = 0
  const run = async () => {
    while (cursor < items.length) {
      const index = cursor++
      results[index] = await worker(items[index]).catch(error => ({ error }))
    }
  }
  await Promise.all(Array.from({ length: limit }, run))
  return results
}

const documents = await pool(urls, 20, url => microlink.pdf(url, { ttl: '7d' }))

Microlink does not throttle, but a bounded pool keeps your own memory and the target site comfortable. Catching per document means one failed render is logged and requeued instead of rejecting the whole batch.

3 · The same request as a URL
curl 'https://pro.microlink.io/?url=https%3A%2F%2Fapp.example.com%2Fstatements%2F42&pdf=true&meta=false&retry=3&ttl=7d' \
  -H 'x-api-key: $MICROLINK_API_KEY'

Every option is a query parameter, so any language with an HTTP client can drive the batch. For a one-off list, the bulk website to PDF converter does the same from the browser.

Parameters used
  • retry Server-side retries with exponential backoff on unexpected browser errors. Default 2.
  • ttl Keeps each response cached from 1 minute to 31 days while the batch is consumed. Default 24 hours. Pro plans.
  • cacheKey Separate cache entries for the same URL rendered per tenant or per run. Pro plans.
  • meta Set to false to skip metadata extraction on every render, the biggest single speedup.
  • filename Names each document so the batch output is self-describing. Pro plans.
  • timeout Per-request budget: 30 seconds on the free endpoint, 60 seconds on Pro.

Watch for EPDFTOOLARGE on very long documents and EPAGERANGE on invalid page ranges; both are per-request error codes that should not stop the batch. The PDF caching and performance guide lists the settings that shave seconds off each render.

Why it works

Why a managed PDF API fits batch generation

Batches are peaks by definition. Capacity that exists only when you need it is the whole point.

01 · No throttling
The batch runs at the speed of your quota.
The API does not rate-limit per second; parallel requests count against your quota and are processed as they arrive. When the quota is exhausted you get an explicit HTTP 429 with ERATE, not a silent slowdown.

Size the plan to the batch on the pricing page; every paid plan carries a 99.9% SLA, and Enterprise adds a dedicated endpoint and browser pool.

02 · Isolated and retried
One browser per document, retries included.
Every render runs in its own isolated browser instance, so a single slow page cannot stall the batch or leak a session into the next document. retry re-runs transient failures server-side with exponential backoff.

The isolation feature describes the sandbox each request gets. Log x-request-id from each response; it is the handle for support when a specific document misbehaves.

03 · Cache as a buffer
Consumers download from the cache, not from the renderer.
Each response is cached with its own ttl, so the batch renders once and the downloads, emails or previews that follow are cache hits. Cache hits do not count against your quota.

When not to: a handful of documents a day does not need a batch pattern; a single request per document as the need arises is simpler and fits the free tier. For text pipelines, bulk Markdown conversion is the lighter output.

FAQ

How many PDFs can I generate in parallel?

There is no per-second throttling; you can perform as many parallel requests as your quota allows. Use a bounded pool on your side, for example 20 concurrent requests, to keep your memory and the target site under control.

What is the time limit for each PDF in a batch?

The request timeout is 30 seconds on the free endpoint and 60 seconds on Pro plans, and values above the plan ceiling are capped. A very long or heavy page that exceeds it fails for that document only, with EPDFTOOLARGE when the PDF cannot be rendered in time. Lower pdf.scale or split the source into shorter pages.

How do I handle failures inside a bulk PDF job?

Set retry to 3 so transient browser errors are retried server-side, then catch errors per document in your code instead of letting one rejection end the batch. A failed render returns an error code such as EBRWSRTIMEOUT or EPDFTOOLARGE that you can log and requeue. Do not retry configuration errors such as EINVALURL or EAUTH.

Are the generated PDFs stored for me after the batch?

Each response is cached for its ttl: 24 hours by default and up to 31 days on Pro plans, so repeat requests return the same hosted document. Treat that as a delivery buffer, and copy the files into your own storage when you need them longer.

Do repeated PDF requests for the same URL use up my quota?

No. Cache hits do not count against your quota, so re-running a batch inside the ttl only pays for the documents that are new. Pass force to regenerate a specific PDF when the underlying page changed, and check the x-cache-status header to confirm a HIT, MISS or BYPASS.
Related use cases

Solve the next problem with the same API

PDF invoices from authenticated pages

Print the invoice page your app already renders: forward the session, hide the chrome, name the file.

PDFs of JavaScript-rendered pages

Print dashboards and single-page apps after they render: wait for the chart, open tabs and sections, then print.

PDF download links and previews

Turn the API URL into the PDF itself for one-click download links and iframe previews, with no storage pipeline.

Archive web articles as PDF

Keep readable, searchable PDFs of articles and docs, printed with their print styles and trimmed to the pages you need.

Screenshots under traffic spikes

Absorb bursts of screenshot traffic without a browser pool: no throttling, parallel requests and a cache whose hits are free.

Bulk Markdown conversion with caching

Convert thousands of URLs in parallel, cached per URL and refreshed in the background for cheap re-indexing.

Ready to render PDFs in bulk?

No browser fleet, no queue to babysit. Pick a Pro plan sized for your batch and generate your first thousand documents tonight.