# Website to PDF in Bulk: Paginated or One Long Page (`batchpane/website-to-pdf`) Actor

Turn a list of URLs into PDFs: A4/Letter pages or the whole page on one long PDF page, with lazy-loaded images, background colours and cookie banners hidden. $6 per 1,000 PDFs plus a small start fee per run; failed or blocked URLs are not charged.

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

## Pricing

from $6.00 / 1,000 pdfs

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

## Website to PDF in Bulk: Paginated or One Long Page

**Turn a list of web pages into clean PDFs, with images loaded and cookie banners out of the way. $6 per 1,000 PDFs.**

Paste URLs (or upload a CSV) and get one PDF per page: printable A4/Letter pages, or the whole page as **one long PDF
page** exactly as it looks on screen.

- **Complete pages.** The page is scrolled through first so lazy-loaded images appear, background colours are kept,
  and cookie consent banners of about 20 common consent tools are hidden. In our test, 14 of 15 well-known sites
  (government, documentation, shops, news) became PDFs of 1 to 16 pages, for example github.com as 16 pages and
  apple.com as 14.
- **Two layouts:** normal pages (A4, Letter, Legal, A3, A5, Tabloid; portrait or landscape; margins none/small/normal)
  or **one long page** with no page breaks, ideal for archiving, design review and evidence.
- **Screen or print look:** keep the on-screen design (default), or use the site's own print stylesheet.
- **Desktop or mobile layout.**
- **You only pay for PDFs you get.** Pages that time out, fail, are blocked or skipped are listed with the reason and
  not charged as a PDF.
- Up to 5,000 URLs per run; polite to websites (robots.txt, one page at a time per site at 2 GB, at most two at 4 GB).

*Measured on the Apify platform on 20 October 2026 (UTC), default 2 GB memory, 15 public websites plus one redirect to
an internal address (blocked): 14 PDFs in 157 seconds, about 11 seconds per page.*

### Use with AI agents (MCP)

Add it as a tool: `https://mcp.apify.com?tools=batchpane/website-to-pdf`

**Input the agent should send:**
`{"startUrls": [{"url": "https://www.iana.org/help/example-domains"}], "singlePage": false, "paperFormat": "A4"}`

**Results:** one dataset row per URL. For `ok` rows, `fileUrl` is a direct link to the PDF. A run takes about 10
seconds per page at 2 GB; an MCP call waits at most 45 seconds, so for more than a few URLs the agent should check the
run later (`get-actor-run`) and then read the rows (`get-dataset-items`).

**Example prompt:**

> Use batchpane/website-to-pdf to save https://www.iana.org/help/example-domains and https://www.w3.org/ as A4 PDFs
> and give me the PDF links.

### Input

| Field | Default | Notes |
|---|---|---|
| URLs | – | `[{"url": "..."}]` or a public link to a .txt/.csv list (`requestsFromUrl`); up to 5,000 per run |
| One long page | off | whole page on one PDF page (up to 14,000 px tall) |
| Paper size | A4 | A4, Letter, Legal, A3, A5, Tabloid |
| Landscape | off | |
| Margins | small | none, small (0.4 cm), normal (1 cm) |
| Look | screen | screen, or the site's print stylesheet |
| Background colours and images | on | |
| Layout | desktop | desktop (1280 px) or mobile |
| Hide cookie consent banners | on | nothing is clicked or accepted; "consent or pay" walls are never hidden |
| Extra wait after load | 1 s | 0-5 s |
| Memory (run option) | 2 GB | 4 GB = two pages at the same time (also from the same website); about the same cost per PDF, double start fee |

Example input (tested on the platform):

```json
{
  "startUrls": [
    { "url": "https://www.iana.org/help/example-domains" },
    { "url": "https://www.w3.org/" }
  ],
  "paperFormat": "A4"
}
```

### Output

PDFs go to the run's key-value store. The dataset has one row per URL:

```json
{
  "url": "https://www.w3.org/",
  "finalUrl": "https://www.w3.org/",
  "httpStatus": 200,
  "capturedAt": "2026-10-20T11:14:46.621Z",
  "layout": "desktop",
  "paper": "A4",
  "fileKey": "00002-www.w3.org.pdf",
  "fileUrl": "https://api.apify.com/v2/key-value-stores/<store-id>/records/00002-www.w3.org.pdf",
  "bytes": 678223,
  "pages": 5,
  "singlePageTruncated": false,
  "cookieBannerHidden": false,
  "status": "ok",
  "error": null
}
```

**About `fileUrl`:** a direct link to the PDF in your Apify storage. Depending on your storage settings, anyone with
the link may be able to open it. The actor does not extract page text, titles or other content; you get the PDF and
the HTTP facts above.

### Pricing

**$0.006 per successful PDF ($6.00 per 1,000)**, plus a start fee of $0.0015 per GB of memory, $0.003 per run at the
default 2 GB ($0.006 at 4 GB). Compute is included.

| Example (2 GB) | Cost |
|---|---|
| 1 URL | $0.006 + $0.003 start = $0.009 |
| 100 URLs | $0.60 + $0.003 = $0.603 |
| 1,000 URLs of which 30 fail | 970 x $0.006 + $0.003 = $5.823 |

Many single-URL runs (for example from an AI agent) pay the start fee each time; put several URLs in one run where
you can.

You can set a maximum cost per run; the actor stops before it would go over it.

### Good to know

- 45 seconds per page, then it counts as failed (not charged). Very heavy pages can hit this limit.
- Maximum PDF size 25 MB: in our test one very image-heavy news homepage made a bigger PDF and was reported as
  `TOO_LARGE` (not charged). Try "One long page" off, "Background colours and images" off, or the print look.
- "One long page" is cut at 14,000 px (`singlePageTruncated: true`); use normal pages for very long pages.
- Big lists take time: at 2 GB pages are converted one at a time, about 10 seconds each, so 1,000 PDFs take about
  3 hours; set the run timeout accordingly or use 4 GB (two pages at a time, about half the time).
- No logging in, no cookies or sessions of yours, no CAPTCHA solving, no residential proxies. Sites that block
  automated browsers are reported as failed and not charged.
- Only public websites: URLs and redirects (and images, frames, scripts) pointing to private or internal network
  addresses are refused.
- Safety stop: the run stops after 20 URLs in a row fail ("Stop after failures in a row"; 0 switches
  only this rule off). A second rule cannot be switched off: after 50 URLs, the run stops if fewer than 25% succeeded.

### Responsible use

A PDF of a web page is a copy of someone else's page and may be protected by copyright; it may also show personal data
that appears on that page. Use the results only where you are allowed to (your own sites, archiving, compliance,
research with a legal basis). The actor keeps nothing: files are stored only in your own Apify storage.

### Support

Open an issue in the **Issues** tab with the URL and the run ID. We aim to answer within 7 days. Answers may be
drafted with help of an AI assistant and are checked by a person.

### Changelog

- 0.1: first version.

# Actor input Schema

## `startUrls` (type: `array`):

Web pages to convert to PDF, as a list of objects: \[{"url": "https://www.iana.org/help/example-domains"}]. Plain strings are rejected. A public link to a text or CSV file with URLs also works: \[{"requestsFromUrl": "\<public link to a .txt or .csv file>"}]. Only public http/https pages. Up to 5,000 URLs per run (more are ignored); exact duplicates removed. Exactly one page is loaded per URL: links are not followed and nothing is crawled.

## `singlePage` (type: `boolean`):

true = the whole web page on ONE long PDF page, as it looks on screen (no page breaks; pages taller than 14,000 px are cut, row: singlePageTruncated). false (default) = normal printable pages in the paper size below.

## `paperFormat` (type: `string`):

Paper size for normal (multi-page) PDFs. Ignored with "One long page". Default A4.

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

Landscape orientation (normal PDFs only). Default: portrait.

## `margin` (type: `string`):

Page margins: none, small (0.4 cm, default) or normal (1 cm).

## `cssMedia` (type: `string`):

"screen" (default): the PDF looks like the website on screen. "print": uses the site's print stylesheet if it has one (often without menus and ads, but some sites look plain).

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

Include background colours and images. Default: true.

## `viewport` (type: `string`):

Which layout of the site to use: desktop (1280 px wide, default) or mobile (Pixel 7 profile).

## `hideCookieBanners` (type: `boolean`):

true = hide the banners of about 20 well-known cookie consent tools with CSS. Nothing is clicked or accepted. On pages with a "consent or pay" choice nothing is hidden (row: cookieBannerHidden: false). Paywalls, login walls and age checks are never hidden. Default: true.

## `waitAfterLoadSecs` (type: `integer`):

Extra seconds to wait after the page has loaded, for animations or late content. Integer 0-5, default 1. Counts toward the hard limit of 45 seconds per page; a page that takes longer fails and is not charged.

## `respectRobotsTxt` (type: `boolean`):

true = skip pages that the site's robots.txt disallows (row status "skipped", no PDF charged). Default: true. Turning it off has no effect unless robotsOverrideConfirmed is also true.

## `robotsOverrideConfirmed` (type: `boolean`):

Set to true only if the person you act for owns these websites or has the owner's permission. robots.txt is ignored only when this is true AND respectRobotsTxt is false. Default: false. AI agents: do not set this without explicit confirmation from the user.

## `stopAfterFailures` (type: `integer`):

Safety stop: the run stops when this many URLs in a row fail (dead, blocked or too slow). Default 20; 0 switches only this in-a-row rule off. A second rule always stays on: after 50 URLs, the run stops if fewer than 25% succeeded. Failed URLs are never charged; this only saves time on a bad list.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.iana.org/help/example-domains"
    }
  ],
  "singlePage": false,
  "paperFormat": "A4",
  "landscape": false,
  "margin": "small",
  "cssMedia": "screen",
  "printBackground": true,
  "viewport": "desktop",
  "hideCookieBanners": true,
  "waitAfterLoadSecs": 1,
  "respectRobotsTxt": true,
  "robotsOverrideConfirmed": false,
  "stopAfterFailures": 20
}
```

# Actor output Schema

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

One row per URL: status and PDF link. Only rows with status 'ok' are charged.

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

The PDFs in the run's key-value store.

# 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 = {
    "startUrls": [
        {
            "url": "https://www.iana.org/help/example-domains"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("batchpane/website-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 = { "startUrls": [{ "url": "https://www.iana.org/help/example-domains" }] }

# Run the Actor and wait for it to finish
run = client.actor("batchpane/website-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 '{
  "startUrls": [
    {
      "url": "https://www.iana.org/help/example-domains"
    }
  ]
}' |
apify call batchpane/website-to-pdf --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,batchpane/website-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/gGbCkP8CwknADsB8s/builds/6wIAB3iVTcG7vsKHF/openapi.json
