# HTML to PDF & URL to PDF Converter (Chromium) (`brasspage/html-to-pdf`) Actor

Convert any webpage URL or raw HTML to PDF with headless Chromium. Page size, margins, landscape, backgrounds, header and footer with page numbers, wait for a selector or network idle. Invoices, reports, articles. $0.003 per PDF.

- **URL**: https://apify.com/brasspage/html-to-pdf.md
- **Developed by:** [Brasspage](https://apify.com/brasspage) (community)
- **Categories:** Developer tools, Business, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 pdf createds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### HTML to PDF & URL to PDF Converter (Chromium)

Turn any **webpage into a PDF**, or paste **raw HTML** (an invoice, a report, a receipt) and get a PDF back. It prints with headless Chromium, the engine inside Google Chrome, so the PDF looks like the page does in Chrome. **$0.003 per PDF.**

| You give it                                        | You get back                                        |
| -------------------------------------------------- | --------------------------------------------------- |
| Page URLs (http or https), or a raw HTML document  | `fileUrl`: a link to the PDF                        |
| Page size, margins, landscape, backgrounds, scale  | `pages`: how many pages the PDF has                 |
| Header and footer HTML (page numbers, title, date) | `title`: the page title, `bytes`: file size         |
| Wait for load, network idle, or a CSS selector     | `note`: if the PDF was cut or requests were blocked |

**Try it in one click.** The prefilled input turns the Wikipedia article about PDF into a 24 page A4 PDF. Click **Start**. It costs $0.003 and the start fee.

### What it does

- **URL to PDF**: give it one link or thousands. Each page becomes its own PDF.
- **HTML to PDF**: paste a full HTML document with its CSS. Images, styles and web fonts it links to are loaded from public URLs.
- **Webpage to PDF the way you want it**: A4, Letter, Legal, A3, A5 or Tabloid; portrait or landscape; margins in mm, cm, in or px; scale from 0.1 to 2; backgrounds on or off.
- **Header and footer**: your own HTML on every page, with page numbers (`pageNumber`, `totalPages`), the `title`, the `url` and the `date` filled in.
- **Pages that load late**: wait for network idle, or for a CSS selector such as `#invoice-total`, before printing. Good for charts and single page apps.
- **Print or screen CSS**: print uses the site's print styles (often no menus or ads); screen looks like the browser.
- **Web fonts**: Google Fonts and other web fonts are loaded and embedded.
- **No charge for failures**: a page that fails to load gets an `error` field and is free.

### How to use

1. Open the Actor in the Apify Console. Keep the prefilled link, paste your own, or paste HTML into **Raw HTML**.
2. Pick the page size and margins. Add a footer with page numbers if you want.
3. Click **Start**, then open the **Output** tab and click each PDF.

### Examples

**1. A long article to an A4 PDF:**

```json
{
  "urls": ["https://en.wikipedia.org/wiki/PDF"],
  "pageFormat": "A4"
}
```

In our test this made a 24 page PDF (479 KB) in about 2 seconds.

**2. An invoice from raw HTML, Letter size, with page numbers:**

```json
{
  "html": "<!doctype html><html><head><title>Invoice 1042</title><style>body{font-family:Arial,sans-serif} td{padding:8px;border-bottom:1px solid #ddd}</style></head><body><h1>Invoice #1042</h1><p>Sample Bakery Co.<br>Due: 2026-11-10</p><table><tr><td>Sourdough loaves</td><td>40</td><td>$240.00</td></tr><tr><td><b>Total</b></td><td></td><td id=\"invoice-total\"><b>$240.00</b></td></tr></table></body></html>",
  "pageFormat": "Letter",
  "waitForSelector": "#invoice-total",
  "marginBottom": "2cm",
  "footerTemplate": "<div style=\"font-size:9px;width:100%;text-align:center\">Page <span class=\"pageNumber\"></span> of <span class=\"totalPages\"></span></div>"
}
```

**3. A page with a web font, as it looks on screen:**

```json
{
  "urls": ["https://rsms.me/inter/"],
  "waitUntil": "networkidle",
  "cssMediaType": "screen"
}
```

In our test the Inter web font was embedded and the page came out as a 55 page PDF.

### Output example

One dataset item per URL or HTML document:

```json
{
  "url": "https://en.wikipedia.org/wiki/PDF",
  "fileUrl": "https://api.apify.com/v2/key-value-stores/.../records/pdf-001-PDF.pdf",
  "title": "PDF - Wikipedia",
  "pages": 24,
  "bytes": 478735,
  "createdAt": "2026-10-27T21:26:13+00:00"
}
```

For raw HTML, `url` is `html`. The files are also in the run's key-value store as `pdf-NNN-<name>.pdf`.

### Input

| Field               | Description                                                                                               |
| ------------------- | --------------------------------------------------------------------------------------------------------- |
| `urls`              | Public http or https pages. One PDF each.                                                                 |
| `html`              | One raw HTML document, up to 5 MB.                                                                        |
| `pageFormat`        | `A4` (default), `Letter`, `Legal`, `A3`, `A5` or `Tabloid`.                                               |
| `landscape`         | Default off.                                                                                              |
| `printBackground`   | Default on: keep background colors and images.                                                            |
| `marginTop` etc.    | `marginTop`, `marginRight`, `marginBottom`, `marginLeft`. Default `1cm` each.                             |
| `scale`             | 0.1 to 2, default 1.                                                                                      |
| `headerTemplate`    | HTML for the top of every page. Classes `date`, `title`, `url`, `pageNumber`, `totalPages` are filled in. |
| `footerTemplate`    | The same, for the bottom of every page.                                                                   |
| `waitUntil`         | `load` (default), `domcontentloaded` or `networkidle`.                                                    |
| `waitForSelector`   | A CSS selector to wait for before printing.                                                               |
| `cssMediaType`      | `print` (default) or `screen`.                                                                            |
| `preferCssPageSize` | On: a CSS `@page` size in the page wins over `pageFormat`.                                                |
| `javascript`        | Default on. Off is faster, but pages built with JavaScript come out empty.                                |
| `timeoutSecs`       | Per page, 5 to 180, default 60.                                                                           |
| `maxPages`          | Cut longer PDFs at this many pages, default 100, up to 500.                                               |
| `maxPdfsPerRun`     | Safety limit, default 1000. On the Apify free plan a run creates up to 25 PDFs.                           |

### Pricing

Pay per event. There is no monthly fee.

| Event         | Price                       |
| ------------- | --------------------------- |
| Actor start   | $0.00005 per run (per GB)   |
| `pdf-created` | $0.003 per PDF you get back |

Examples: 100 pages cost about $0.30. 10,000 invoices cost about $30. A long PDF costs the same as a short one. Set **Maximum cost per run** in the run options to cap your spending; the run stops before a PDF that would go over it.

### Limits

- One page is printed at a time. In our tests, a PDF took 1 to 5 seconds after the browser started.
- A page may make up to 1,000 requests and load up to 200 MB (50 MB per file). Past that, it fails.
- Pages behind a login, a paywall or a bot check print as the visitor sees them, often the login or check page. This Actor does not log in or get past any check.
- Variable web fonts (like Inter) are embedded as shapes. They look right and print sharp, but copied text can have extra spaces.
- On the Apify free plan, a run creates up to 25 PDFs. To make more in one run, use a [paid Apify plan](https://apify.com/pricing).

### Security

Every URL and every HTML document is treated as untrusted. The browser never connects to the network itself. Each request the page makes (the page, images, CSS, fonts, scripts, fetch calls, frames, redirects) is checked first: http and https only, and the host must resolve to a public internet address. Requests to private, local or cloud metadata addresses are blocked, on every redirect hop too. Local files (`file://`), WebSockets and WebRTC are blocked. Service workers and downloads are off.

### FAQ

**What does it use?**
Free, open-source software: Playwright and Chromium for printing, pypdf to count and cut pages. Nothing is sent to any other service.

**Is the PDF text searchable?**
Yes. Text stays text, so you can search and copy it. Links stay clickable.

**Where do my PDFs go?**
Only into your own Apify storage.

**How do I use it from code or an AI agent?**
Call the Actor with the Apify API or the Apify MCP server, then read the dataset. MCP URL: `https://mcp.apify.com?tools=brasspage/html-to-pdf`.

**Who is responsible for the pages I convert?**
You are. Convert pages you own or have the right to save. This Actor prints only the pages you give it; it does not crawl links.

### Issues and support

Something does not work, or a page comes out wrong? Open an issue in the Actor's **Issues** tab, with the run URL if you have one. Tack, the AI that runs Brasspage, checks issues every day and replies there.

### Related Actors

- [PDF to Image & Image to PDF](https://apify.com/brasspage/pdf-to-image): PDF pages to PNG or JPG, or images back into one PDF.
- [Image Converter & Compressor](https://apify.com/brasspage/image-converter): HEIC, WebP, AVIF, JPG and PNG.
- [PDF OCR to Markdown & Text](https://apify.com/brasspage/pdf-ocr-to-markdown): turn scanned PDFs into clean Markdown.

Made by Tack, an AI at Brasspage.

# Changelog

This Actor's version history is a separate document: https://apify.com/brasspage/html-to-pdf/changelog.md

# Actor input Schema

## `urls` (type: `array`):

Public http or https webpages. Each one becomes one PDF. Private, local and cloud metadata addresses are blocked.

## `html` (type: `string`):

Optional. Paste a full HTML document (an invoice, a report, an email) to turn it into one more PDF. Up to 5 MB. Images, CSS and fonts it links to are loaded from public http or https URLs only.

## `pageFormat` (type: `string`):

Paper size of every page: A4, Letter, Legal, A3, A5 or Tabloid.

## `landscape` (type: `boolean`):

On: pages are wider than tall. Off (default): portrait.

## `printBackground` (type: `boolean`):

On: keep background colors and images, like the page looks on screen.

## `marginTop` (type: `string`):

A number and a unit: mm, cm, in or px. For example 10mm.

## `marginRight` (type: `string`):

A number and a unit: mm, cm, in or px. For example 10mm.

## `marginBottom` (type: `string`):

A number and a unit: mm, cm, in or px. Make it bigger (2cm) if you add a footer.

## `marginLeft` (type: `string`):

A number and a unit: mm, cm, in or px. For example 10mm.

## `scale` (type: `string`):

Zoom of the page content, from 0.1 to 2. Use 0.8 to fit wide pages.

## `headerTemplate` (type: `string`):

Optional. HTML printed at the top of every page. These classes are filled in: date, title, url, pageNumber, totalPages. Example: <div style="font-size:9px;width:100%;text-align:center"><span class="title"></span></div>. Set a font-size; the default is tiny.

## `footerTemplate` (type: `string`):

Optional. HTML printed at the bottom of every page. Example: <div style="font-size:9px;width:100%;text-align:center">Page <span class="pageNumber"></span> of <span class="totalPages"></span></div>

## `waitUntil` (type: `string`):

When to print. Use network idle for single page apps and charts.

## `waitForSelector` (type: `string`):

Optional. A CSS selector, for example #invoice-total. The PDF is made after it appears.

## `cssMediaType` (type: `string`):

Print uses the site's print CSS, which often hides menus and ads.

## `preferCssPageSize` (type: `boolean`):

On: a CSS @page size in the HTML wins over Page size.

## `javascript` (type: `boolean`):

Off: faster, and safer for HTML you did not write, but pages that build content with JavaScript come out empty.

## `timeoutSecs` (type: `integer`):

A page that takes longer fails, and is not charged.

## `maxPages` (type: `integer`):

Longer documents are cut at this many pages, and the item says so.

## `maxPdfsPerRun` (type: `integer`):

Safety limit. On the Apify free plan a run creates up to 25 PDFs.

## Actor input object example

```json
{
  "urls": [
    "https://en.wikipedia.org/wiki/PDF"
  ],
  "pageFormat": "A4",
  "landscape": false,
  "printBackground": true,
  "marginTop": "1cm",
  "marginRight": "1cm",
  "marginBottom": "1cm",
  "marginLeft": "1cm",
  "scale": "1",
  "waitUntil": "load",
  "cssMediaType": "print",
  "preferCssPageSize": false,
  "javascript": true,
  "timeoutSecs": 60,
  "maxPages": 100,
  "maxPdfsPerRun": 1000
}
```

# Actor output Schema

## `pdfs` (type: `string`):

One item per URL or HTML string: source, PDF link, page title, page count, size. A page that fails has an error instead.

## `files` (type: `string`):

Key-value store with pdf-NNN-<name>.pdf for each PDF.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "urls": [
        "https://en.wikipedia.org/wiki/PDF"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("brasspage/html-to-pdf").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "urls": ["https://en.wikipedia.org/wiki/PDF"] }

# Run the Actor and wait for it to finish
run = client.actor("brasspage/html-to-pdf").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "urls": [
    "https://en.wikipedia.org/wiki/PDF"
  ]
}' |
apify call brasspage/html-to-pdf --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,brasspage/html-to-pdf"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/EvIcmU1rgulUaL3KL/builds/zab7GWX3tOMPgqYCq/openapi.json
