# URL to PDF Converter - Web Pages and HTML (`bite-sized-insights/url-to-pdf-converter`) Actor

Convert public web pages or your own HTML documents to PDF. Set page size, margins, orientation, scale, page ranges, headers and footers. Get a download link, page count and file size for each PDF.

- **URL**: https://apify.com/bite-sized-insights/url-to-pdf-converter.md
- **Developed by:** [bite-sized-insights](https://apify.com/bite-sized-insights) (community)
- **Categories:** Developer tools, Automation, Business
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.01 / 1,000 row returneds

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

## URL to PDF Converter - Web Pages and HTML to PDF

Turn any public web page, or HTML you generate yourself, into a print-ready PDF. Give it a list of URLs or HTML
documents; every one comes back as a PDF file with a public download link. Control page size, orientation, margins,
headers, footers and what to wait for before a page is captured.

### What this actor does

- **Converts web pages and raw HTML.** Paste URLs, pass your own HTML (invoices, reports, receipts), or both in the
  same run.
- **Real page rendering.** Pages are loaded the way a visitor sees them, including content that appears after the
  page opens, so modern sites come out complete instead of blank.
- **Print layout control.** Page format (A0-A6, Letter, Legal, Tabloid, Ledger) or a custom size, portrait or
  landscape, individual margins, scale, page ranges, background colors and images on or off.
- **Wait conditions.** Wait for the page to finish loading, for the network to go quiet, for a specific element to
  appear, or for a fixed extra moment. Each document has its own time limit.
- **Headers and footers.** Add HTML headers and footers with automatic page numbers, total pages, date, title and
  URL.
- **Public download links.** Each PDF is stored with the run and linked in the results, ready to download or to hand
  to the next step of your workflow.
- **Runs documents in parallel** and delivers results as each one finishes.

### Quick start

```json
{
    "urls": ["https://example.com"]
}
```

Click **Start**. Each PDF appears in the results as soon as it is ready, with a link in the `pdf_url` column.

#### Convert your own HTML

```json
{
    "urls": [],
    "htmlDocuments": ["<html><body><h1>Invoice 2026-001</h1><p>Total: 120.00 EUR</p></body></html>"],
    "pageFormat": "Letter",
    "marginBottom": "20mm",
    "footerHtml": "<div style=\"font-size:9px\"><span class=\"pageNumber\"></span></div>"
}
```

The URL list has an example prefilled; empty it (as above) when you only want to convert HTML.

### Input parameters

| Parameter | Type | Default | Description |
|---|---|---|---|
| `urls` | Array\[String] | `["https://example.com"]` | Public web pages to convert, up to 100. Domain or full URL. |
| `htmlDocuments` | Array\[String] | `[]` | Complete HTML documents, up to 20, each up to 1,000,000 characters. |
| `pageFormat` | String | `A4` | `A0`-`A6`, `Letter`, `Legal`, `Tabloid` or `Ledger`. |
| `pageWidth`, `pageHeight` | String | - | Custom page size, e.g. `100mm` and `150mm`. Set both; replaces the format. |
| `landscape` | Boolean | `false` | Landscape instead of portrait. |
| `marginTop`, `marginRight`, `marginBottom`, `marginLeft` | String | `10mm` | Margins, e.g. `10mm`, `1in`. |
| `scale` | Number | `1` | Content zoom, 0.1 to 2. |
| `pageRanges` | String | all pages | Keep only some pages, for example `1-3, 5`. |
| `printBackground` | Boolean | `true` | Include background colors and images. |
| `preferCssPageSize` | Boolean | `false` | Use the page size set by the page's own print styles, if it has one. |
| `mediaType` | String | `print` | `print` applies the page's print styles, `screen` keeps the screen look. |
| `headerHtml`, `footerHtml` | String | - | HTML repeated on every page. See below. |
| `waitUntil` | String | `load` | `load`, `domcontentloaded` (fastest) or `networkidle` (waits for late content). |
| `waitForSelector` | String | - | CSS selector that must be present before the page is converted. |
| `waitMs` | Integer | `0` | Extra pause in milliseconds after the page is ready, up to 10000. |
| `timeoutSeconds` | Integer | `30` | Time limit per document, 5 to 120. |
| `failOnHttpError` | Boolean | `true` | Skip the PDF when the page answers with an error status such as 404 or 500. |
| `viewportWidth`, `viewportHeight` | Integer | `1280`, `1024` | Size of the virtual window the page is laid out in. |

At least one URL or one HTML document is required. Only public http(s) addresses are accepted: entries pointing at
private or local addresses, containing credentials, or otherwise malformed are rejected as invalid input before any
work starts.

#### Headers and footers

Headers and footers are small pieces of HTML. Give them an inline font size and a top or bottom margin large enough to
hold them. These placeholders are filled in automatically when used as the class of an empty `span`:
`pageNumber`, `totalPages`, `date`, `title` and `url`.

### Output

One row per document, in the results table and the dataset. The PDF itself is stored with the run; `pdf_url` is the
public link to download it.

#### Successful conversion

```json
{
    "source": "https://example.com/",
    "source_type": "url",
    "status": "success",
    "pdf_url": "https://api.apify.com/v2/key-value-stores/xxxxxxxxxxxxxxxxx/records/pdf-0001-1a2b3c4d.pdf",
    "pdf_key": "pdf-0001-1a2b3c4d.pdf",
    "page_count": 1,
    "file_size_bytes": 92999,
    "render_seconds": 0.54,
    "final_url": "https://example.com/",
    "http_status": 200,
    "error": null
}
```

#### Document that could not be converted

```json
{
    "source": "https://example.com/missing",
    "source_type": "url",
    "status": "failed",
    "pdf_url": null,
    "pdf_key": null,
    "page_count": null,
    "file_size_bytes": null,
    "render_seconds": null,
    "final_url": null,
    "http_status": null,
    "error": "The page responded with HTTP 404"
}
```

Every row has the same keys. HTML inputs are labelled `HTML document 1`, `HTML document 2`, ... in `source`; `final_url`
and `http_status` only apply to URL inputs.

A document fails when the page cannot be reached, answers with an error status (unless `failOnHttpError` is off), is
not allowed (private or local addresses), or exceeds its time limit. Failed documents are not charged. A problem with
the run's access to the conversion service ends the run with an error message instead of producing rows.

### Pricing: pay per PDF

You pay for every PDF that was created and delivered, plus a small flat fee per run. Failed documents are free.
Apify's platform dataset-item fee ($0.00001 per row) applies to every row written to the dataset, including failed
rows.

| Event | Price |
|---|---|
| PDF created and delivered | $0.005 (about $5 per 1,000 PDFs) |
| Run start | $0.00005 |

#### Free test runs

New users on Apify's free plan get up to 5 free runs of this actor (lifetime total), each capped to 3 documents. Runs
started via the Apify Console's "Test" button are capped to 3 documents too, regardless of plan, and don't count
against the 5 free runs.

### How long does a run take?

Most pages take one to five seconds each, with up to 2 documents processed at once. Pages that load content late, or
that you ask to wait for an element or for the network to settle, take longer, up to the time limit you set. Results
stream into the dataset as each document finishes.

### FAQ

#### Can I convert pages behind a login?

No. Only publicly reachable pages can be converted. For private content, pass the page's HTML in `htmlDocuments`
instead.

#### Why is my PDF missing content that I see in my browser?

The page probably loads that content late. Try `waitUntil: networkidle`, `waitForSelector` with an element that
appears once the content is there, or a short `waitMs`. Some sites also show different content to printed pages: set
`mediaType` to `screen` to keep the on-screen look.

#### How long are the PDF links available?

The files are stored with the run, so they stay available as long as the run's data does. Download or copy them if
you need them for longer. Anyone who has the link can open the file, so treat links like the data they point to.

#### Are there size limits?

HTML documents can be up to 1,000,000 characters, and a single PDF can be up to 50 MB.

### Disclaimer

Only convert pages you are allowed to copy and store. The actor does not alter page content, and what ends up in the
PDF depends on what the page shows at the time of conversion.

***

**Need help?** Open an issue on the actor's repository or contact support through Apify Console.

# Actor input Schema

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

Public pages to convert, one PDF each. Domain or full URL. Empty it to convert only HTML.

## `htmlDocuments` (type: `array`):

Complete HTML documents, one PDF each. Images and styles: inline or public absolute URLs.

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

Paper size of the PDF. Ignored when a custom width and height are set.

## `pageWidth` (type: `string`):

Width with a unit, e.g. <code>100mm</code>. Set with the height; replaces the format.

## `pageHeight` (type: `string`):

Height with a unit, e.g. <code>150mm</code>. Set together with the width.

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

Print pages in landscape instead of portrait.

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

Margin on the top with a unit, e.g. <code>10mm</code> or <code>1in</code>.

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

Margin on the right with a unit, e.g. <code>10mm</code> or <code>1in</code>.

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

Margin on the bottom with a unit, e.g. <code>10mm</code> or <code>1in</code>.

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

Margin on the left with a unit, e.g. <code>10mm</code> or <code>1in</code>.

## `scale` (type: `number`):

Zoom factor of the page content, from 0.1 (10%) to 2 (200%).

## `pageRanges` (type: `string`):

Keep only these pages, e.g. <code>1-3, 5</code>. Leave empty to keep all pages.

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

Include background colors and images. Turn off for a plain print.

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

Use the page size set by the page's own print styles (<code>@page</code>), if any.

## `mediaType` (type: `string`):

<b>Print</b> applies the page's print styles; <b>screen</b> keeps the on-screen look.

## `headerHtml` (type: `string`):

HTML at the top of every page. Needs an inline font size and a big enough top margin.

## `footerHtml` (type: `string`):

HTML at the bottom of every page, e.g. page numbers. Needs a big enough bottom margin.

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

When a page counts as loaded. Network idle also waits for content that loads late.

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

CSS selector (e.g. <code>#content</code>) that must be on the page before it is converted.

## `waitMs` (type: `integer`):

Pause in milliseconds after the page is ready, for animations or late content.

## `timeoutSeconds` (type: `integer`):

Maximum seconds per document, including loading and waiting. Timeouts are not charged.

## `failOnHttpError` (type: `boolean`):

Skip the PDF when the page answers with an error status such as 404 or 500.

## `viewportWidth` (type: `integer`):

Width of the virtual window the page is laid out in. Responsive pages react to it.

## `viewportHeight` (type: `integer`):

Height of the virtual window the page is laid out in.

## Actor input object example

```json
{
  "urls": [
    "https://example.com"
  ],
  "htmlDocuments": [],
  "pageFormat": "A4",
  "landscape": false,
  "marginTop": "10mm",
  "marginRight": "10mm",
  "marginBottom": "10mm",
  "marginLeft": "10mm",
  "scale": 1,
  "printBackground": true,
  "preferCssPageSize": false,
  "mediaType": "print",
  "waitUntil": "load",
  "waitMs": 0,
  "timeoutSeconds": 30,
  "failOnHttpError": true,
  "viewportWidth": 1280,
  "viewportHeight": 1024
}
```

# Actor output Schema

## `results` (type: `string`):

One row per input document with a download link, page count and file size

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

All generated PDF files in the run's storage

# 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://example.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("bite-sized-insights/url-to-pdf-converter").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://example.com"] }

# Run the Actor and wait for it to finish
run = client.actor("bite-sized-insights/url-to-pdf-converter").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://example.com"
  ]
}' |
apify call bite-sized-insights/url-to-pdf-converter --silent --output-dataset

```

## MCP server setup

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

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/z42qcHw7OusTeIuuL/builds/nNzyRf1TOMCtKfpmF/openapi.json
