# Website Screenshot & URL to PDF API (Bulk, Full Page) (`sunburst077/website-screenshot-pdf`) Actor

Capture website screenshots (PNG, JPEG, WebP) and PDFs from a list of URLs. Files are stored in the default key-value store with public URLs. Failures become error rows; the run never fails as a whole.

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

## Pricing

from $2.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.

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 Screenshot & URL to PDF API (Bulk, Full Page)

Capture full-page website screenshots and convert any URL to PDF, in bulk, from a list of URLs. Formats are PNG, JPEG, WebP and PDF. The Actor opens each page in headless Chromium, writes the files to the default key-value store, and returns one dataset row per URL × format with a public file URL.

A failure on one URL becomes an **error row**. The run continues and finishes successfully.

### What you get

- Screenshots in PNG, JPEG, or WebP, plus print-style PDFs
- Full-page or viewport captures, or a single CSS element
- Device presets: desktop 1920×1080, laptop 1366×768, iPhone 390×844, iPad 820×1180
- Cookie-banner heuristic (CSS/JS only — no paid consent service)
- Optional lazy-load scroll and optional tracker blocking
- Works on the Apify **FREE** plan with proxy left off. Apify Proxy is used only if you enable it.

### Input

| Field | What it does |
| --- | --- |
| `urls` | List of page URLs. Default and prefill: `https://example.com`, `https://docs.apify.com`. |
| `startUrls` | Optional Crawlee-style list (`{ "url": "..." }`). Merged with `urls`. |
| `outputs` | One or more of `png`, `jpeg`, `webp`, `pdf`. Default: `png` and `pdf`. |
| `fullPage` | Capture the full scrollable page for images. Default: `true`. |
| `devicePreset` | `desktop`, `laptop`, `iphone`, `ipad`, or `custom`. |
| `viewportWidth` / `viewportHeight` | Override the preset, or set size when `devicePreset` is `custom`. |
| `waitUntil` | `load`, `domcontentloaded`, or `networkidle`. |
| `delayMs` | Extra wait after load, banners, and scroll. |
| `selector` | CSS selector to screenshot one element (images only). |
| `hideCookieBanners` | Hide or click common consent banners. |
| `scrollToLoad` | Scroll the page so lazy images can load. |
| `blockTrackers` | Abort common analytics and ad-pixel hosts. |
| `imageQuality` | JPEG/WebP quality, 1–100. PNG ignores this. |
| `pdfFormat` | `A4` or `Letter`. |
| `landscape` | Landscape PDF. |
| `printBackground` | Include CSS backgrounds in the PDF. |
| `timeoutSecs` | Navigation timeout per URL. Timed-out navigations are retried once. |
| `maxConcurrency` | Parallel pages. Keep at 1–2 on 1024 MB. |
| `proxyConfiguration` | Defaults to **no proxy**. Enable Apify Proxy only if you need it. |

Every input field has a description in the Actor console.

### Example

```json
{
    "urls": ["https://example.com", "https://docs.apify.com"],
    "outputs": ["png", "pdf"],
    "fullPage": true,
    "devicePreset": "desktop",
    "hideCookieBanners": true,
    "proxyConfiguration": { "useApifyProxy": false }
}
```

iPhone screenshot of one element:

```json
{
    "urls": ["https://example.com"],
    "outputs": ["png"],
    "devicePreset": "iphone",
    "selector": "h1",
    "fullPage": false
}
```

### Sample output

One dataset row per URL × format:

```json
{
    "url": "https://example.com",
    "finalUrl": "https://example.com/",
    "statusCode": 200,
    "title": "Example Domain",
    "format": "png",
    "fileKey": "capture-0001-example.com.png",
    "fileUrl": "https://api.apify.com/v2/key-value-stores/<STORE_ID>/records/capture-0001-example.com.png",
    "previewUrl": "https://api.apify.com/v2/key-value-stores/<STORE_ID>/records/capture-0001-example.com.png",
    "width": 1920,
    "height": 1080,
    "pageCount": null,
    "fileSizeBytes": 48210,
    "loadTimeMs": 1842,
    "capturedAt": "2026-10-31T17:10:00.000Z",
    "status": "ok",
    "error": null
}
```

Error rows keep the same shape. File fields are `null`, `status` is `"error"`, and `error` holds the message. Those rows are not charged.

The Output tab has an **Overview** view and an **Errors** view.

### Pricing

Pay-per-event. Apify platform usage (compute) is included in the event prices, so you pay only for the events below. Error rows are free.

| Event | When it fires | Price |
| --- | --- | --- |
| `run-start` | Once when the run begins | $0.0001 |
| `screenshot` | Each successful PNG, JPEG, or WebP | $0.002 |
| `pdf` | Each successful PDF | $0.003 |

Set a maximum total charge on the run if you want a hard cap. The Actor stops new paid captures when that cap is reached.

Typical cost for the default input (two URLs × PNG + PDF): one `run-start`, two screenshots, two PDFs — **$0.0101** in total, platform usage included.

### Limitations

- Cookie-banner hiding is a heuristic. Some consent dialogs, especially those inside closed shadow roots or custom iframes, will remain.
- Sites that block datacenter IPs or detect headless Chromium may return a challenge page. Enabling Apify Proxy can help on paid plans; it is off by default so FREE-plan runs work.
- Very long full-page screenshots use more memory and produce large files. Prefer a selector or a viewport capture for endless feeds.
- Login walls, CAPTCHA, and bot-management interstitials are not solved.
- `networkidle` can time out on pages that keep sockets open. Prefer `load` unless you need the extra wait.
- WebP is encoded from a PNG capture. Quality is controlled by `imageQuality`.
- The Actor memory range is 1024–2048 MB. High `maxConcurrency` on huge pages can run out of memory.

### FAQ

**Does this work on the Apify FREE plan?**\
Yes, with proxy left disabled (the default). Do not turn on Apify Proxy unless your account can use it.

**What happens if one URL fails?**\
That URL × format is stored as an error row. Other URLs keep going. The run status stays succeeded.

**How do I download the file?**\
Use `fileUrl` on the dataset row, or open the record key (`fileKey`) in the run’s default key-value store.

**Can I capture only one element?**\
Set `selector` to a CSS selector. Image formats use that element. PDF still prints the full document.

**Why is my screenshot blank or missing images?**\
Increase `delayMs`, turn on `scrollToLoad`, or switch `waitUntil` to `networkidle`. Some images never load without a logged-in session.

**Will tracker blocking change the page?**\
It can, if the layout depends on those scripts. Leave `blockTrackers` off unless you want the speed tradeoff.

**How is time measured?**\
Each row’s `loadTimeMs` is the time to produce that file after the page is ready. The log also prints per-capture durations.

### More actors from this developer

- [PDF to Markdown: DOCX, PPTX, XLSX, OCR & RAG Chunks](https://apify.com/sunburst077/document-to-markdown-rag): PDF, DOCX, PPTX, XLSX and HTML to clean Markdown and RAG-ready chunks.
- [Google Trends Scraper & API: Interest, Related, Trending](https://apify.com/sunburst077/google-trends-reliable): interest over time, by region, and related queries from Google Trends.
- [Google News Scraper: Full-Text Articles to Markdown](https://apify.com/sunburst077/google-news-to-markdown): Google News articles as Markdown and RAG chunks for any topic or company.
- [Greenhouse, Lever, Ashby & Workable Jobs API](https://apify.com/sunburst077/multi-ats-jobs-feed): one clean jobs feed from company job boards, with salaries when posted.
- [Wayback Machine API: Snapshots & Archived Pages](https://apify.com/sunburst077/wayback-machine-snapshots): every archived capture of a URL or domain, the snapshot closest to a date, and archived pages as Markdown.

### Local development

Requires Python 3.10+ and Playwright Chromium.

```bash
pip install -r requirements-dev.txt
playwright install chromium
pytest
```

To run the Actor locally (writes to a local `storage` folder):

```bash
python -m src
```

Without Apify input, the same defaults as the Store form are used: example.com and docs.apify.com as PNG + PDF, full page.

This Actor does not deploy itself. Publish it from your Apify account when you are ready.

# Actor input Schema

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

Pages to capture. Accepts a list of http(s) URLs. If omitted, the default list is used so Apify daily tests produce a non-empty dataset. You can also pass startUrls (Crawlee request-list format); both lists are merged and de-duplicated.

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

Optional Crawlee-style start URL list (objects with a url field, or plain strings). Merged with urls. Use this if you are wiring the Actor from a crawler task. requestsFromUrl entries are ignored.

## `outputs` (type: `array`):

One or more formats to produce for every URL. Each URL × format pair becomes one dataset row and one key-value store file. PNG is lossless. JPEG and WebP use imageQuality. PDF uses the paper options below.

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

When enabled, image captures include the full scrollable document instead of only the viewport. Ignored when selector is set (element capture is always the element's box). PDF always renders the print layout of the full document.

## `devicePreset` (type: `string`):

Viewport, user-agent, and touch settings. desktop is 1920×1080, laptop is 1366×768, iphone is 390×844 (3× scale), ipad is 820×1180 (2× scale). Custom uses viewportWidth and viewportHeight with a desktop Chrome user-agent.

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

Browser viewport width in CSS pixels. Applied when devicePreset is custom, or when you set a value other than the 1920×1080 default to override a preset. Typical range is 320–3840.

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

Browser viewport height in CSS pixels. Applied when devicePreset is custom, or when you set a value other than the 1920×1080 default to override a preset. Typical range is 240–2160.

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

Playwright navigation wait condition. load waits for the load event (good default). domcontentloaded is faster but may miss late resources. networkidle waits until there are no more than two network connections for 500 ms — more complete, but can time out on pages with long-polling or analytics.

## `delayMs` (type: `integer`):

Milliseconds to wait after navigation (and after cookie-banner / lazy-scroll steps) before taking the capture. Use this for animations, late hero images, or client-rendered charts.

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

Maximum seconds allowed for navigation of a single URL. A navigation timeout is retried once. Other failures become an error row and the Actor continues.

## `selector` (type: `string`):

Optional CSS selector. When set, image captures screenshot only the first matching element instead of the page. If the selector matches nothing, that URL × format is recorded as an error row. PDF still renders the full document.

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

Best-effort CSS and JavaScript heuristic that dismisses or hides common consent banners (OneTrust, Cookiebot, Quantcast, Didomi, Complianz, CookieYes, and generic cookie/consent dialogs). No third-party consent API is used. Some sites will still show a banner.

## `scrollToLoad` (type: `boolean`):

Scroll through the page in viewport-sized steps so lazy-loaded images and infinite placeholders can fetch before capture. Then scrolls back to the top. Adds time on long pages.

## `blockTrackers` (type: `boolean`):

Optionally abort requests to common analytics, tag-manager, and ad-pixel hosts (Google Analytics, GTM, Facebook, Hotjar, and similar). Can speed up capture and cut noise. Leave off if the page depends on those scripts to render.

## `imageQuality` (type: `integer`):

Compression quality for JPEG and WebP captures, from 1 (smallest) to 100 (least compressed). PNG is always lossless and ignores this value.

## `pdfFormat` (type: `string`):

Paper size used when outputs includes pdf. A4 is 210×297 mm. Letter is 8.5×11 in. Dimensions in the dataset row are reported in CSS pixels at 96 DPI.

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

Print the PDF in landscape orientation. Ignored for image formats.

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

Include CSS backgrounds and colors in the PDF. Turn off for a printer-friendly, mostly text document.

## `maxConcurrency` (type: `integer`):

How many pages to capture in parallel. The Actor reuses one Chromium browser. Keep this low on 1024 MB runs (1–2). Higher values use more memory and can OOM on 2048 MB if pages are huge.

## `proxyConfiguration` (type: `object`):

Proxy used by the browser. Defaults to no proxy so the Actor works on the Apify FREE plan. Automatic Apify Proxy is used only if you enable it here. On the FREE plan, Apify Proxy works only from Actors running on the platform (not from your laptop). Custom proxy URLs are also supported.

## Actor input object example

```json
{
  "urls": [
    "https://example.com",
    "https://docs.apify.com"
  ],
  "startUrls": [
    {
      "url": "https://example.com"
    },
    {
      "url": "https://docs.apify.com"
    }
  ],
  "outputs": [
    "png",
    "pdf"
  ],
  "fullPage": true,
  "devicePreset": "desktop",
  "viewportWidth": 1920,
  "viewportHeight": 1080,
  "waitUntil": "load",
  "delayMs": 0,
  "timeoutSecs": 30,
  "hideCookieBanners": true,
  "scrollToLoad": false,
  "blockTrackers": false,
  "imageQuality": 80,
  "pdfFormat": "A4",
  "landscape": false,
  "printBackground": true,
  "maxConcurrency": 2,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

Dataset rows: url, finalUrl, title, format, status, fileUrl, dimensions, page count, file size, timing, and error for failed captures.

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

Captured screenshot and PDF files stored in the default 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 = {
    "urls": [
        "https://example.com",
        "https://docs.apify.com"
    ],
    "startUrls": [
        {
            "url": "https://example.com"
        },
        {
            "url": "https://docs.apify.com"
        }
    ],
    "outputs": [
        "png",
        "pdf"
    ],
    "fullPage": true,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("sunburst077/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",
        "https://docs.apify.com",
    ],
    "startUrls": [
        { "url": "https://example.com" },
        { "url": "https://docs.apify.com" },
    ],
    "outputs": [
        "png",
        "pdf",
    ],
    "fullPage": True,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("sunburst077/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",
    "https://docs.apify.com"
  ],
  "startUrls": [
    {
      "url": "https://example.com"
    },
    {
      "url": "https://docs.apify.com"
    }
  ],
  "outputs": [
    "png",
    "pdf"
  ],
  "fullPage": true,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call sunburst077/website-screenshot-pdf --silent --output-dataset

```

## MCP server setup

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