Skip to content

Python HTML to PDF API

Convert any URL into a pixel-perfect PDF with one HTTP request in Python — no wkhtmltopdf, no headless Chrome, no servers to maintain.

Convert a URL to PDF in Python

No SDK and no browser binaries — the Microlink REST API turns any URL into a hosted PDF with a single HTTP GET. Here it is with the popular requests package; the standard library works too.
Step 01 · Install requests
The most convenient way to talk to the API. Prefer zero dependencies? Skip this and use urllib from the standard library.
pip install requests
Step 02 · Convert any URL
Point it at a page, ask for a PDF, and read the hosted document URL back from the JSON response.
convert.py
import requests

res = requests.get('https://api.microlink.io', params={
    'url': 'https://example.com',
    'pdf': 'true',
    'meta': 'false'  # skip metadata extraction for a faster response
})

data = res.json()['data']
print(data['pdf']['url'])
Step 03 · Customize the document
Paper format, margins, orientation, and print CSS are all query params. Nested options use dot notation, so pdf.format maps to the format field.
options.py
res = requests.get('https://api.microlink.io', params={
    'url': 'https://example.com',
    'pdf.format': 'A4',        # A0-A6 | Letter | Legal | Tabloid
    'pdf.margin': '0.35cm',    # cm, mm, in or px
    'pdf.landscape': 'false',  # portrait (default) | landscape
    'mediaType': 'print',      # print CSS stylesheets | screen (default)
    'meta': 'false'
})

print(res.json()['data']['pdf']['url'])
Step 04 · Save it to disk
The response is a hosted PDF URL on a global CDN. Stream it to a file with a second request, or hand the URL straight to your template.
save.py
import requests

res = requests.get('https://api.microlink.io', params={
    'url': 'https://example.com',
    'pdf': 'true'
})

pdf_url = res.json()['data']['pdf']['url']

with open('document.pdf', 'wb') as file:
    file.write(requests.get(pdf_url).content)

Drop it into your framework

A view, a route, or a standalone script — the same request becomes your own PDF endpoint, perfect for invoice downloads, nightly reports, and export views in Django, Flask, or FastAPI.
  • Flask
  • Django
  • FastAPI
  • Python
from django.http import HttpResponseRedirect
import requests

# GET /pdf?url=https://example.com
def pdf(request):
    res = requests.get('https://api.microlink.io', params={
        'url': request.GET['url'],
        'pdf': 'true',
        'meta': 'false'
    })
    return HttpResponseRedirect(res.json()['data']['pdf']['url'])

Skip the wkhtmltopdf maintenance

Generating PDFs from Python means wrestling with wkhtmltopdf binaries, WeasyPrint CSS limits, or driving headless Chrome yourself. The API gives you a real browser rendering engine without any of the infrastructure.

Self-hosted PDF tooling

  • wkhtmltopdf is archived upstream — an outdated engine frozen in time
  • WeasyPrint & xhtml2pdf never execute JavaScript, so SPAs render blank
  • Driving headless Chrome means pinning drivers and a ~300 MB binary
  • Each browser eats hundreds of MB of RAM; workers crash under load
  • You build the pooling, queueing, retries and autoscaling
  • Fonts, emoji, and modern CSS break differently on every host

Microlink for Python

  • One HTTP request — works with requests or the standard library
  • Runs anywhere: serverless, containers, a cron job, your laptop
  • Autoscaled managed browser fleet with a 99.9% uptime SLA
  • Sub-second cached responses from 330+ edge locations
  • A0-A6, Letter, Legal & Tabloid — set as plain query params
  • Print stylesheets, custom CSS & DOM interaction, no extra deps

Built for the way you write Python.

A REST API that feels native in Python — one HTTP call, JSON back, and at home in any runtime from a Django app to an AWS Lambda. Read the PDF guide to go deeper.

  • No Binaries to Install

    Skip wkhtmltopdf and headless Chrome entirely. There is no rendering engine to download, patch, or keep in sync across hosts.
  • requests or Standard Library

    Use the popular requests package or the built-in urllib — it is a plain HTTP GET either way, with no extra dependencies required.
  • Framework Friendly

    Drop it into Django, Flask, or FastAPI as a view or route in a few lines. The same request works everywhere.
  • Serverless Ready

    No browser layer to bundle. Deploy to AWS Lambda, Google Cloud Functions, or any container with zero binaries.
  • Real Browser Rendering

    Pages render in Headless Chrome, so JavaScript-driven dashboards and charts come out right — the blind spot of WeasyPrint and xhtml2pdf.
  • Zero Infrastructure

    No Chrome to pin to a driver version and no browser pool inside your workers. Your app stays a plain HTTP client.
  • Custom Paper & Layout

    Every layout option is a query param: pdf.format, pdf.margin, pdf.landscape, pdf.scale, and pdf.pageRanges.
  • Screen & Print Media

    Pass mediaType="print" in the same params dict to apply print stylesheets, or keep the default screen layout.
  • Generous Free Tier

    Start with 25 requests per day — no account, no credit card. Point at pro.microlink.io with an x-api-key header when you scale.
  • No Binaries to Install

    Skip wkhtmltopdf and headless Chrome entirely. There is no rendering engine to download, patch, or keep in sync across hosts.
  • requests or Standard Library

    Use the popular requests package or the built-in urllib — it is a plain HTTP GET either way, with no extra dependencies required.
  • Framework Friendly

    Drop it into Django, Flask, or FastAPI as a view or route in a few lines. The same request works everywhere.
  • Serverless Ready

    No browser layer to bundle. Deploy to AWS Lambda, Google Cloud Functions, or any container with zero binaries.
  • Real Browser Rendering

    Pages render in Headless Chrome, so JavaScript-driven dashboards and charts come out right — the blind spot of WeasyPrint and xhtml2pdf.
  • Zero Infrastructure

    No Chrome to pin to a driver version and no browser pool inside your workers. Your app stays a plain HTTP client.
  • Custom Paper & Layout

    Every layout option is a query param: pdf.format, pdf.margin, pdf.landscape, pdf.scale, and pdf.pageRanges.
  • Screen & Print Media

    Pass mediaType="print" in the same params dict to apply print stylesheets, or keep the default screen layout.
  • Generous Free Tier

    Start with 25 requests per day — no account, no credit card. Point at pro.microlink.io with an x-api-key header when you scale.

Try it live in the playground

Paste a URL and see the exact API request before you write a line of Python.

Python PDF FAQ

What Python developers ask before integrating. For formats, limits, and SLA, see the PDF API overview.

Do I need wkhtmltopdf or a headless browser?

No. It is a plain HTTP request to the Microlink API — there is no wkhtmltopdf binary to ship and no Chromium to download. The Headless Chrome fleet runs on Microlink's side.
That also means JavaScript-heavy pages render correctly — unlike WeasyPrint or xhtml2pdf, which never execute scripts.

Does it work with asyncio?

Yes. Nothing about the call is Python-specific — it is one HTTP GET, so httpx or aiohttp take the same parameters inside a coroutine. With requests, run it in a thread executor to avoid blocking the loop.
The rendering happens on Microlink's side either way, so your worker only ever waits on the network.

Should I use requests or the standard library?

Either. requests is the most convenient, but urllib from the standard library works with zero dependencies — both just issue an HTTP GET and read JSON back.

Does it work with Django, Flask, and FastAPI?

Yes. Because it is just an HTTP call, it drops into any view or route handler in a few lines — see the tabs above for Flask, Django, and FastAPI, or the PDF guide.

How do I authenticate from Python?

Two things change together: send your key as the x-api-key header, and point the request at pro.microlink.io instead of api.microlink.io. Sending the header to the free endpoint returns an EPRO error.
With requests that is requests.get('https://pro.microlink.io', params=…, headers={'x-api-key': KEY}). See the authentication docs and pricing.

How do I convert a batch of URLs?

Each conversion is an independent stateless request, so a ThreadPoolExecutor or a task queue like Celery parallelises it without any coordination on your side.
Concurrency is bounded by your plan rather than your hardware — check the rate limit docs before fanning out widely.

Start converting in Python

Get 25 requests/day with zero commitment — no account, no credit card. Paste the snippet into a view and ship a PDF today.
No login needed
25 reqs/day free
No credit card