# Website Screenshot & PDF - Bulk, Full Page, No Cookie Banners (`olsols4/website-screenshot-pdf`) Actor

Capture any list of URLs as full-page PNG, JPEG or PDF. Hides cookie banners and ads, desktop/tablet/mobile, dark mode, element capture. Get a public file link per page.

- **URL**: https://apify.com/olsols4/website-screenshot-pdf.md
- **Developed by:** [Olly](https://apify.com/olsols4) (community)
- **Categories:** Developer tools, SEO tools
- **Stats:** 2 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 - Bulk, Full Page, No Cookie Banners

Turn **any list of URLs into clean screenshots or PDFs**. Cookie and consent pop-ups, ads and trackers are blocked automatically, and every capture gets a **public file link** you can drop into a sheet, a report or another app.

### Why use this instead of a basic screenshot tool

The free [Website Screenshot Generator](https://apify.com/apify/screenshot-url) is fine for a quick PNG. This Actor adds what you need for real work:

| | This Actor | Basic screenshot tools |
|---|---|---|
| **PDF output** (A4, Letter, Legal, A3, portrait or landscape) | Yes | No |
| **Device presets**: desktop, laptop, tablet, mobile (real iPhone user agent, retina) | Yes | Width only |
| **Cookie banners hidden** (OneTrust, Cookiebot, Didomi, Quantcast, Usercentrics, Osano, Termly, iubenda and more) | Yes | No |
| **Ads and trackers blocked** for cleaner, faster captures | Yes | No |
| **Dark mode** | Yes | No |
| **Capture one element** with a CSS selector (e.g. `#pricing`) | Yes | No |
| **Custom CSS** to hide chat widgets or anything else | Yes | No |
| **Public file link per page** in the dataset | Yes | Varies |
| **Dead links are free** (DNS errors, refused connections, HTTP errors) | Yes | You pay compute either way |

### Features

- **PNG, JPEG or PDF**; first screen by default, or **full page** with lazy images loaded (cut off at a height you choose so endless feeds stay sane)
- Many URLs in one run, captured in parallel in a single browser
- **Max captures** cap and your run's spending limit are both respected, so a run never costs more than you expect

### Use cases

Website archiving and compliance evidence, competitor and pricing-page tracking, SEO and design audits, client reports, thumbnails for directories, visual QA across devices.

### Input example

```json
{"urls": ["https://apify.com", "https://www.bbc.co.uk/news"], "format": "pdf", "device": "desktop"}
```

### Output

One row per URL:

```json
{"url": "https://apify.com", "title": "Apify: Full-stack web scraping and data extraction platform", "status": 200, "format": "png", "device": "desktop", "fileUrl": "https://api.apify.com/v2/key-value-stores/.../records/apify-com-1a2b3c4d.png", "bytes": 843921}
```

Pages that could not be captured get a row with an `error` instead. Files are also in the run's key-value store.

### Pricing

Pay per event, with platform usage included:

- **$0.01 per successful capture** (screenshot or PDF).
- **$0.01 per page that times out.** Pages that time out are charged like a capture because they still use browser time.
- **Dead links are free**: pages that fail fast (unknown domain, refused connection, HTTP error) are not charged.
- **$0.005 per run** to cover starting the browser.

So 100 screenshots cost about $1.01. If most pages in a run fail to load (a bad list or a blocking site), the run stops early instead of grinding through the rest, and skipped pages are free too.

### FAQ

**Am I charged for pages that fail?** Dead links are free. A page that hangs until the page timeout (default 30 s, max 60 s) is charged $0.01, the same as a capture, because it kept a browser busy the whole time. Lower *Page timeout* if you would rather give up on slow sites sooner. Each failed row's `error` says what happened, and timed-out rows have `"charged": "timeout"`.

### Tips

- Turn on **Full page** only when you need it; first-screen captures are faster.
- Use *Extra wait* for pages with animations or late-loading widgets.
- For very long pages, PDF is often smaller than PNG.
- The default 2 GB memory handles 3 pages at once. For much higher parallelism, raise memory too.
- Schedule it to capture the same pages daily for a visual history.

Questions or a feature you need? Open an issue on this Actor's page.

# Actor input Schema

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

Pages to capture.

## `maxCaptures` (type: `integer`):

Safety cap on how many URLs are captured in one run (extra URLs are skipped). Your run's spending limit is also respected.

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

File type.

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

Capture the whole scrolling page instead of just the first screen (viewport). Off by default: faster and the usual choice for thumbnails and monitoring.

## `maxHeightPx` (type: `integer`):

Full-page captures are cut off below this height. Endless feeds can otherwise get enormous.

## `device` (type: `string`):

Desktop 1440px, laptop 1280px, tablet (iPad Air), mobile (iPhone).

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

Hides common cookie and consent pop-ups (OneTrust, Cookiebot, Didomi, Quantcast and more).

## `blockAds` (type: `boolean`):

Blocks common ad networks and hides ad slots.

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

Blocks analytics/tracking scripts (Google Analytics, Tag Manager, Hotjar, Facebook pixel and more) and video/audio downloads. Faster captures; turn off only if a page breaks without them.

## `darkMode` (type: `boolean`):

Ask the site for its dark theme.

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

Wait after load before capturing, for animations and late content.

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

Page event to wait for.

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

Scrolls through the page first so lazy-loaded images appear in full-page captures.

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

Optional. Capture only this element, e.g. #pricing.

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

Optional. Overrides the device width.

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

Optional. Overrides the device height.

## `jpegQuality` (type: `integer`):

Only for JPEG.

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

Only for PDF.

## `pdfLandscape` (type: `boolean`):

Only for PDF.

## `customCss` (type: `string`):

Optional CSS injected before capture, e.g. to hide a chat widget.

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

Give up on a page after this long (max 60 s). A page that times out is charged like a capture, because it still used browser time.

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

Pages captured in parallel. 3 suits the default 2 GB memory; raise memory to 4 GB before going above 4.

## Actor input object example

```json
{
  "urls": [
    "https://apify.com",
    "https://www.bbc.co.uk/news"
  ],
  "maxCaptures": 1000,
  "format": "png",
  "fullPage": false,
  "maxHeightPx": 12000,
  "device": "desktop",
  "hideCookieBanners": true,
  "blockAds": true,
  "blockTrackers": true,
  "darkMode": false,
  "delayMs": 500,
  "waitUntil": "load",
  "scrollToLoad": true,
  "jpegQuality": 80,
  "pdfFormat": "A4",
  "pdfLandscape": false,
  "timeoutSecs": 30,
  "maxConcurrency": 3
}
```

# Actor output Schema

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

One row per URL with a public link to its file.

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

All screenshot and PDF files.

# 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://www.bbc.co.uk/news"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("olsols4/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://apify.com",
        "https://www.bbc.co.uk/news",
    ] }

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

```

## MCP server setup

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