# Website Screenshot & PDF: Bulk, No Cookie Banners (`jfaro19/website-screenshot`) Actor

Take screenshots or PDFs of web pages in bulk. Full page or visible screen, desktop/laptop/tablet/mobile, PNG/JPEG/PDF, dark mode, single-element capture. Hides cookie banners and blocks ads. Returns a public image URL plus page title and HTTP status. Pay only for successful captures.

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

## Pricing

from $4.00 / 1,000 screenshots

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

### What does Website Screenshot & PDF do?

**Website Screenshot & PDF** captures screenshots of any list of URLs in bulk: the **visible screen or the full scrolling page**, emulating **desktop, laptop, tablet or mobile**, saved as **PNG, JPEG or PDF**.

**Cookie banners and consent popups are hidden automatically** (OneTrust, Cookiebot, Usercentrics, Didomi, Quantcast and 40+ others), and **ads and trackers are blocked**, so screenshots look like the real page. You pay only for screenshots that succeed.

Each result includes a **direct link to the image** plus the page title, final URL and HTTP status. Download the list as CSV, Excel or JSON, or use the Apify API, scheduler, and integrations with Make, Zapier, n8n and Google Sheets.

### Why use Website Screenshot & PDF?

- **Agencies and sales teams**
  - Put a screenshot of a prospect's website in outreach emails or audit reports.
  - Show before/after redesigns.
- **Monitoring and QA**
  - Schedule daily captures of landing pages, pricing pages or competitors to see what changed.
  - Check mobile layouts.
- **Archiving and compliance**
  - Keep dated full-page PNG or PDF records of web pages, ads or terms and conditions.
- **Datasets and AI**
  - Generate page thumbnails for directories, link previews or vision-model pipelines.

**What makes it different**

- Cookie banners and popups are hidden with CSS. No consent is clicked on anyone's behalf.
- Ads, trackers and empty ad placeholders are removed for clean captures.
- Full-page mode scrolls first so lazy-loaded images appear, and it handles very long pages instead of failing.
- Mobile emulation uses a real iPhone profile (viewport, user agent, touch).
- You can capture a single element (`#pricing`, `header`), wait for a selector, add a delay, or use dark mode.
- **Failed pages are free.**

### How to take website screenshots in bulk

1. Click **Try for free**.
2. Paste your URLs into the **URLs** field, one per line (`example.com` works too).
3. Choose a **Device**, whether you want a **Full page**, and the **Output format**.
4. Click **Start**.
5. Open the **Output** tab to see thumbnails, or download the list with image links.

### Input

| Field | Default | Description |
|---|---|---|
| `urls` | – | Pages to capture (domains or full URLs) |
| `device` | `desktop` | `desktop` (1920×1080), `laptop` (1366×768), `tablet` (iPad), `mobile` (iPhone 13) |
| `fullPage` | `false` | Capture the entire scrollable page |
| `format` | `png` | `png`, `jpeg` or `pdf` (A4 with backgrounds) |
| `hideCookieBanners` | `true` | Hide cookie-consent banners and common popups |
| `blockAds` | `true` | Block ad and tracking scripts and hide empty ad slots |
| `darkMode` | `false` | Emulate `prefers-color-scheme: dark` |
| `delaySeconds` | `0` | Extra wait after the page loads |
| `waitForSelector` | – | Wait for this CSS selector before capturing |
| `elementSelector` | – | Capture only this element |
| `jpegQuality` | `80` | JPEG quality (1–100) |
| `viewportWidth` / `viewportHeight` | – | Custom viewport size |
| `maxConcurrency` | `6` | Pages captured in parallel |

```json
{
  "urls": ["https://apify.com", "example.com"],
  "device": "mobile",
  "fullPage": true,
  "format": "jpeg"
}
```

### Output

One item per URL (real output from a full-page run):

```json
{
  "url": "https://apify.com",
  "status": "ok",
  "screenshotUrl": "https://api.apify.com/v2/key-value-stores/…/records/apify.com-7c0cb881.png?signature=…",
  "screenshotKey": "apify.com-7c0cb881.png",
  "finalUrl": "https://apify.com/",
  "httpStatus": 200,
  "title": "Apify: Marketplace of ready-to-run tools for AI",
  "device": "desktop",
  "fullPage": true,
  "format": "png",
  "bytes": 928570,
  "loadTimeMs": 67665
}
```

| Field | Description |
|---|---|
| `screenshotUrl` | Direct, shareable link to the image or PDF |
| `status` | `ok` or `error` (errors are never charged) |
| `finalUrl`, `httpStatus`, `title` | Where the page ended up after redirects, and its title |
| `truncated`, `pageHeight` | Set when a very long page was cut to the maximum image height (16,000 px for PNG, 32,000 px for JPEG) |
| `bannerHidingFailed` | Set if a page refused the banner-hiding stylesheet (rare) |
| `error` | Reason for failure (timeout, DNS error, invalid selector…) |

### How much does it cost to screenshot websites?

**Pay-per-event** pricing, charged only for **successful** captures:

- **Screenshot** (visible screen or single element): see the **Pricing** tab for the price per 1,000
- **Full-page screenshot or PDF**: priced higher because it needs several times more browser time

Failed pages, timeouts and invalid URLs are free. You can set a maximum cost per run, and the Actor stops when it reaches the limit.

### Tips

- Use **JPEG** for full pages. The files are much smaller and faster than PNG.
- For pages with animations or slow widgets, add `delaySeconds: 2–3` or a `waitForSelector`.
- To monitor changes, schedule the Actor daily and compare `screenshotUrl` images over time.
- Some sites block automated browsers or cloud servers. Those pages return an error or a challenge page, and errors aren't charged.

### Works well with

- [Contact Details Scraper](https://apify.com/jfaro19/website-contact-finder): find emails, phones and social profiles for the same websites. Pay only when contacts are found.
- [Domain Intelligence](https://apify.com/jfaro19/domain-intel): see each site's CMS, analytics, email provider and SPF/DKIM/DMARC grade.

### FAQ, disclaimers and support

**Does it accept cookies on my behalf?** No. Consent banners are only hidden visually. No button is clicked and no consent is recorded.

**Is it legal?** The Actor visits public pages like a normal browser. Respect the websites' terms, and don't use screenshots in ways that infringe copyright or trademarks.

**Found a page that renders badly or a banner that isn't hidden?** Open an issue on the **Issues** tab with the URL. New banner rules are added regularly.

# Actor input Schema

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

Pages to capture. Domains (example.com) or full URLs (https://example.com/pricing). Duplicates are removed.

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

Screen to emulate. Desktop 1920×1080, Laptop 1366×768, Tablet (iPad), Mobile (iPhone 13, with mobile user agent and touch).

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

Capture the entire scrollable page instead of just the visible screen. Lazy-loaded images are triggered by scrolling first.

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

PNG (lossless), JPEG (smaller files) or PDF (A4, with backgrounds).

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

Hide cookie-consent banners (OneTrust, Cookiebot, Usercentrics, Didomi, Quantcast, and 40+ more) and common newsletter popups. Banners are hidden with CSS; no consent is given.

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

Block ad networks and tracking scripts. Pages load faster and screenshots are cleaner.

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

Emulate a dark color scheme (prefers-color-scheme: dark) for sites that support it.

## `delaySeconds` (type: `integer`):

Wait this long after the page has loaded before capturing, e.g. for animations.

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

Optional. Wait until an element matching this CSS selector appears before capturing.

## `elementSelector` (type: `string`):

Optional. CSS selector of a single element to capture (e.g. 'header' or '#pricing') instead of the page.

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

1–100, only used for JPEG.

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

Optional. Overrides the device width (set height too).

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

Optional. Overrides the device height (set width too).

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

Pages captured in parallel.

## Actor input object example

```json
{
  "urls": [
    "https://apify.com",
    "https://www.wikipedia.org"
  ],
  "device": "desktop",
  "fullPage": false,
  "format": "png",
  "hideCookieBanners": true,
  "blockAds": true,
  "darkMode": false,
  "delaySeconds": 0,
  "jpegQuality": 80,
  "maxConcurrency": 6
}
```

# Actor output Schema

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

No description

# 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.wikipedia.org"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("jfaro19/website-screenshot").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.wikipedia.org",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("jfaro19/website-screenshot").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.wikipedia.org"
  ]
}' |
apify call jfaro19/website-screenshot --silent --output-dataset

```

## MCP server setup

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

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/9QSLfpPZffs6bat7m/builds/ugGJgZJO4liUGz99z/openapi.json
