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

Batch website screenshots and PDFs: full-page, desktop/laptop/tablet/mobile, PNG/JPEG/WebP/PDF, auto-dismisses cookie banners, lazy-load scrolling, hide elements, wait for selector. Fast single-URL mode for AI agents.

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

## Pricing

Pay per event

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 & PDF Renderer

Capture **full-page or visible-screen screenshots and PDFs** of any public web page, in bulk or one at a time. It works on desktop, laptop, tablet, mobile or a custom size, and saves PNG, JPEG, WebP or PDF. Cookie banners are dismissed automatically, lazy-loaded images are scrolled into view, and sticky headers don't repeat down the page. **You only pay for screenshots that succeed.**

### What you get

- **Full-page that actually is full-page.** The page is scrolled to load lazy images, then the Actor waits briefly for the network to settle. You can also set an extra delay or wait for a CSS selector.
- **Height control.** Set `maxHeight` (for example `1500`) to capture just the top of a page. Very tall pages are clipped at 16,384 px, and the output tells you so.
- **Sticky headers handled.** Fixed navbars, chat bubbles and banners appear once (or are hidden) instead of repeating in every screen-height slice.
- **Cookie banners dismissed.** OneTrust, Cookiebot, Didomi, Quantcast, TrustArc, Usercentrics, CookieYes, Osano, Complianz, iubenda, Sourcepoint, Google Funding Choices and common "Accept all" buttons in several languages are handled, with a CSS fallback.
- **Emoji and CJK render correctly.** Noto Color Emoji and Noto CJK fonts are installed, so you get no empty boxes.
- **Devices.** Desktop 1920×1080, laptop 1366×768, tablet 820×1180 @2x, iPhone-size mobile 390×844 @3x, or custom. Request several devices in one run.
- **Formats.** PNG, JPEG, WebP (with quality setting) and PDF (A4, Letter, Legal or A3; screen or print CSS).
- **Never charged for failures.** A charge event fires only after the file is stored. DNS errors, timeouts and blocked pages cost nothing.
- **Every input has a default.** You can paste URLs and press Start.
- **Respects your budget.** If you set a maximum cost per run, the Actor stops cleanly when it's reached.

### Use cases

- Visual archive or proof of web pages (ads, landing pages, pricing pages, legal notices).
- Responsive QA: desktop and mobile screenshots of every page in a sitemap.
- Thumbnails and previews for directories, link-in-bio pages and CMS entries.
- Feeding page images to vision AI models or agents (use the single `url` input).
- Saving articles or docs as PDF.
- Scheduled screenshots for simple visual change tracking (run on an Apify schedule).

### Input example

```json
{
  "urls": ["https://apify.com", "https://example.com"],
  "devices": ["desktop", "mobile"],
  "format": "png",
  "fullPage": true,
  "maxHeight": 8000,
  "stickyElements": "static",
  "dismissCookieBanners": true,
  "delayMs": 0
}
```

For one quick capture, `{ "url": "https://example.com", "fullPage": false }` is enough.

### Output example

Each URL and device combination gives one dataset row. The file itself is in the run's key-value store, and `fileUrl` links to it directly.

```json
{
  "url": "https://example.com/",
  "device": "desktop",
  "format": "png",
  "viewport": "1920x1080",
  "fileUrl": "https://api.apify.com/v2/key-value-stores/<storeId>/records/example.com_desktop.png",
  "httpStatus": 200,
  "title": "Example Domain",
  "width": 1920,
  "height": 1080,
  "bytes": 23817,
  "consentDismissed": null,
  "stickyElementsFixed": 0,
  "warning": null,
  "error": null,
  "finalUrl": "https://example.com/",
  "takenAt": "2026-10-14T14:30:00.000Z"
}
```

- Failed captures get a row with `error` set, and you're not charged for them.
- A `SUMMARY` record shows counts, invalid URLs, truncation and whether the budget limit stopped the run.

### Pricing (pay per event)

| Event | Price |
|---|---|
| Full-page screenshot or PDF | **$5 per 1,000** ($0.005 each) |
| Visible-screen (viewport) screenshot | **$2 per 1,000** ($0.002 each) |
| Actor start | $0.005 per GB of memory per run |

Compute is included, and failed captures are free.

### How it compares (honest)

We tested Apify's own free [Website Screenshot Generator](https://apify.com/apify/screenshot-url) side by side on the same 10 popular sites, with 4 GB memory, on 2026-10-14:

| | This Actor | apify/screenshot-url |
|---|---|---|
| Successful captures | 10 / 10 | 7 / 10 (3 blocked) |
| Run time | 43 s | 149 s |
| What you pay | $0.05 for 10 full-page shots + start fee | about $0.033 in compute, including the failed ones |

- The other Actor is free to use: you pay only Apify compute, which in our test came to about $4.77 per 1,000 successful shots. If your pages are simple and you don't mind paying for failures, it can be cheaper.
- This Actor's pricing is predictable: fixed per-screenshot pricing, no charge for failures, plus cookie, sticky-header, emoji and height handling.
- Heavy single-page apps can still take 30–60 s each. A few sites with aggressive bot protection may still fail, and those are free.

### FAQ

**Can it take screenshots behind a login?** No. It captures public pages only, with no cookies or credentials.

**Can it capture localhost or private network addresses?** No. Private, loopback and cloud-metadata addresses are blocked for security.

**What are the limits?** Up to 1,000 URLs per run (times the number of devices) and a per-page timeout of 5–90 s (default 45 s). Images are capped at 16,384 px tall.

**Why does a page show a "warning"?** The capture succeeded, but something is worth knowing. For example, the page didn't finish loading in time and you got what had rendered, the page was clipped to `maxHeight`, or it was rendered at 1x to fit the size limit.

**A banner or popup is still visible.** Add its CSS selector to `hideSelectors`.

**Hero videos look blank.** Make sure `blockMedia` is off (the default).

**How do I get the images?** Use `fileUrl` in each dataset row, or open the run's key-value store.

**Is the data stored?** Files stay in your own Apify storage according to your retention settings.

# Actor input Schema

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

Pages to capture (max 1,000 per run). Missing https:// is added.

## `url` (type: `string`):

Optional single page. Combined with URLs if both are set.

## `devices` (type: `array`):

One capture per URL per device.

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

Format.

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

Capture the whole scrollable page (clipped at 16,384px).

## `dismissCookieBanners` (type: `boolean`):

Clicks 'Accept' on common consent managers and hides leftovers.

## `scrollToLoadLazy` (type: `boolean`):

Scroll to load lazy images.

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

Navigation event to wait for. Default 'load'; after lazy-load scrolling the Actor also waits briefly for network idle.

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

Extra wait after the page has loaded and scrolled, for animations or late content.

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

Wait for CSS selector.

## `hideSelectors` (type: `array`):

Hide elements (CSS selectors).

## `quality` (type: `integer`):

JPEG/WebP quality.

## `pdfPageFormat` (type: `string`):

PDF page size.

## `pdfPrintMedia` (type: `boolean`):

PDF: use print stylesheet.

## `customWidth` (type: `integer`):

Custom width.

## `customHeight` (type: `integer`):

Custom height.

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

Per-page timeout (s).

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

Max URLs.

## `locale` (type: `string`):

Browser locale.

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

Max parallel pages.

## `maxHeight` (type: `integer`):

Full-page captures are clipped to this many CSS pixels from the top. Set e.g. 1500 to capture just the upper part.

## `stickyElements` (type: `string`):

Stops sticky navbars, chat bubbles and banners repeating down full-page screenshots.

## `blockMedia` (type: `boolean`):

Faster and cheaper, but hero videos render as empty boxes.

## Actor input object example

```json
{
  "urls": [
    "https://apify.com",
    "https://example.com"
  ],
  "devices": [
    "desktop"
  ],
  "format": "png",
  "fullPage": true,
  "dismissCookieBanners": true,
  "scrollToLoadLazy": true,
  "waitUntil": "load",
  "delayMs": 0,
  "quality": 85,
  "pdfPageFormat": "A4",
  "pdfPrintMedia": false,
  "customWidth": 1280,
  "customHeight": 800,
  "timeoutSecs": 45,
  "maxUrls": 1000,
  "locale": "en-US",
  "maxHeight": 16384,
  "stickyElements": "static",
  "blockMedia": false
}
```

# Actor output Schema

## `captures` (type: `string`):

One row per URL x device.

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

Counts, failures, truncation.

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

// Run the Actor and wait for it to finish
const run = await client.actor("contented_catwalk/website-screenshot-pdf-renderer").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://apify.com",
        "https://example.com",
    ] }

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

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,contented_catwalk/website-screenshot-pdf-renderer"
        }
    }
}
```

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/LXzGphef99B2KHkQb/builds/eInPqpgpKNRZtXwOG/openapi.json
