# Bulk Website Screenshot & PDF Generator — Full Page (`paoe/bulk-website-screenshot-pdf`) Actor

- **URL**: https://apify.com/paoe/bulk-website-screenshot-pdf.md
- **Developed by:** [Rashad Flet](https://apify.com/paoe) (community)
- **Categories:** Developer tools, SEO tools, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $12.00 / 1,000 screenshot captureds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

Capture real full-page screenshots (PNG/JPEG/WebP) and optional PDFs of many URLs at once with a headless Chromium browser, so the output is what a human would actually see. One charged event per screenshot captured; a URL that fails is not billed as a capture. Built by PAOE.

Each item is processed individually and charged as its own event, so you pay only for what the run actually delivers. Results are written to the run's dataset as one JSON object per item, ready to download as JSON, CSV or Excel, or to pull through the Apify API.

### What it checks

For each URL: a real full-page screenshot captured by a headless Chromium browser (or just the viewport, if you prefer), in PNG, JPEG or WebP, at a viewport you choose. Each record carries the HTTP status, the page title, the file size, a link to the stored image, and how long the capture took. An optional A4 PDF of each page is produced alongside the image at no extra charge, and a failed PDF never invalidates the screenshot that was already captured.

### Pricing

| Event | What it covers | Price |
| --- | --- | --- |
| `screenshot-captured` | screenshot captured (primary) | $0.02 per event |

Volume tiers reduce the price automatically on higher Apify plans: Bronze 15% off, Silver 25% off and Gold or above 40% off the listed free-tier price. The charge is per item processed, not per run.

### Input

| Field | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `urls` | array | yes | `["https://example.com"]` | One URL per line. Each captured screenshot is one charged event. |
| `maxUrls` | integer | no | `100` | Hard cap on how many URLs are captured in one run. |
| `fullPage` | boolean | no | `True` | Capture the entire scrollable page instead of just the viewport. |
| `format` | string | no | `png` | png (lossless), jpeg or webp. |
| `width` | integer | no | `1440` | Browser viewport width in pixels (320-3840). |
| `height` | integer | no | `900` | Browser viewport height in pixels (240-4320). |
| `makePdf` | boolean | no | `False` | Save an A4 PDF of each page alongside the screenshot. No extra charge. |
| `waitMs` | integer | no | `0` | Additional time to wait after load, for animations or lazy content. |

Example input:

```json
{
  "urls": [
    "https://example.com"
  ],
  "maxUrls": 100,
  "fullPage": true,
  "format": "png",
  "width": 1440,
  "height": 900,
  "makePdf": false,
  "waitMs": 0
}
```

### Output

One JSON object per item in the run's dataset. Every result carries the input it came from plus the fields this Actor measures, so the output can be joined back to your own data without guessing which row is which. The final dataset entry is a `summary` object with the run's totals.

### Typical use cases

- Archive what a page looked like on a given date, for evidence.
- Capture a portfolio of sites or competitor pages in one run.
- Feed real page images into a review, a report or a QA process.
- Produce PDF copies of public pages alongside the screenshots.

### Limitations

No. Each URL is fetched as an anonymous browser session, so a page behind authentication, a paywall or an aggressive bot wall returns a login page or a challenge rather than the protected content. Those URLs are reported with their HTTP status and are not billed as captures. The capture is a viewport-level render of what a browser receives, not a claim about the site's full behaviour; very tall pages are captured in one pass with a capped viewport so the run cannot exhaust memory.

#### Does it screenshot pages behind a login?

Every limitation above is reported per item in a `findings` entry with a `level` of `fail`, `warn`, `info` or `ok`, a machine-readable `code` and a concrete `action`. If something cannot be checked it is reported as such rather than assumed to be fine.

#### Can it run on a schedule?

Yes. Save a task from this Actor with your inputs, then set a schedule on the task. Scheduled runs recur with the same inputs, which is the intended way to use it for ongoing monitoring.

#### Am I charged for URLs that fail?

No. The charge event fires only after a screenshot is actually captured and stored, so a URL that times out, returns an error, or is blocked costs nothing. The run summary reports `failed` and `withheld_unbilled` separately so the counts reconcile.

### Notes

If a site returns something unexpected, open an issue on the Actor's page with the URL and the input used, and it will be looked at.

### Related Actors

- [Bulk Broken-Link & Redirect Audit](https://apify.com/paoe/bulk-broken-link-redirect-audit)

### Keywords

website screenshot, bulk screenshot, full page screenshot, url to image, screenshot api, webpage to pdf, website screenshot generator, capture website.

# Actor input Schema

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

One URL per line. Each captured screenshot is one charged event.

## `maxUrls` (type: `integer`):

Hard cap on how many URLs are captured in one run.

## `fullPage` (type: `boolean`):

Capture the entire scrollable page instead of just the viewport.

## `format` (type: `string`):

png (lossless), jpeg or webp.

## `width` (type: `integer`):

Browser viewport width in pixels (320-3840).

## `height` (type: `integer`):

Browser viewport height in pixels (240-4320).

## `makePdf` (type: `boolean`):

Save an A4 PDF of each page alongside the screenshot. No extra charge.

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

Additional time to wait after load, for animations or lazy content.

## Actor input object example

```json
{
  "urls": [
    "https://example.com"
  ],
  "maxUrls": 100,
  "fullPage": true,
  "format": "png",
  "width": 1440,
  "height": 900,
  "makePdf": false,
  "waitMs": 0
}
```

# Actor output Schema

## `records` (type: `string`):

One JSON record per captured URL, including the stored screenshot URL.

## `summary` (type: `string`):

How many URLs were captured, failed, or withheld unbilled.

# 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("paoe/bulk-website-screenshot-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://example.com"] }

# Run the Actor and wait for it to finish
run = client.actor("paoe/bulk-website-screenshot-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://example.com"
  ]
}' |
apify call paoe/bulk-website-screenshot-pdf --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,paoe/bulk-website-screenshot-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/Sc3rkRBBfPEuV7Zt8/builds/Satw8sJPWzIEdEQgi/openapi.json
