# Website Screenshot Pro — Bulk, Full Page, Mobile (`egra_van/website-screenshot-pro`) Actor

Screenshot hundreds of URLs in one run: full page or viewport, desktop/tablet/mobile, PNG, JPEG, WebP or PDF. Hides cookie banners, blocks ads, loads lazy images, dark mode, element capture. Pay only for successful screenshots.

- **URL**: https://apify.com/egra\_van/website-screenshot-pro.md
- **Developed by:** [Argentin Vazdautan](https://apify.com/egra_van) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.10 / 1,000 web page screenshots

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

## Website Screenshot Pro — Bulk, Full Page, Mobile

Take **clean screenshots of hundreds of web pages in one run**. Paste a list of URLs (or connect the results of another Actor) and get a **full-page or viewport screenshot of every page**, on **desktop, laptop, tablet or mobile**, as **PNG, JPEG, WebP or PDF**. Cookie banners and ads are removed automatically, and lazy-loaded images are loaded before the capture.

Typical uses: **website monitoring and archiving**, **visual QA** after a release, **SEO and client reports**, **competitor tracking**, **thumbnails and link previews**, and giving **AI agents** a picture of a page.

### Why this screenshot Actor

- 🧹 **Clean screenshots**: cookie and consent pop-ups hidden (OneTrust, Cookiebot, Didomi, Quantcast, TrustArc, Usercentrics, CookieYes and generic cookie bars). Nothing is clicked or accepted.
- 🚫 **Ads and trackers blocked**: faster pages, no flashing banners
- 🖼️ **Lazy images really load**: the page is scrolled before a full-page capture, so images further down are not empty boxes
- 📱 **Device presets**: Desktop 1920×1080, Laptop 1366×768, Tablet 768×1024, Mobile 390×844 (retina, touch, mobile browser) or any custom size
- 🗂️ **PNG, JPEG, WebP, plus PDF** of the same page in one run
- 🎯 **Element screenshots**: capture only `#pricing` or `.hero`
- 🌙 **Dark mode**, custom elements to hide, wait for an element, extra delay
- ⚡ **Fast in bulk**: several pages in parallel, retries with a fresh proxy IP, one ZIP with everything
- 🧾 **Honest results**: HTTP status, final URL after redirects, page title, size in pixels and bytes, clear warnings, and a plain-English reason for every failed URL
- 💸 **Pay only for successful screenshots**: invalid, broken or failed URLs are free

### Quick start

1. Paste your URLs, one per line.
2. Choose the device and whether you want the **full page**.
3. Click **Start**. Open the **Screenshots** table to see image previews and download links.

### Input example

```json
{
  "urls": ["https://apify.com", "https://www.wikipedia.org", "example.com/pricing"],
  "device": "mobile",
  "fullPage": true,
  "format": "webp",
  "quality": 80,
  "hideCookieBanners": true,
  "blockAds": true,
  "hideSelectors": ["#intercom-container"],
  "savePdf": false,
  "outputZip": true
}
```

#### Main options

| Option | What it does |
|---|---|
| `urls` | Pages to capture. `example.com` becomes `https://example.com`. Duplicates are skipped. |
| `startUrlsDatasetId` + `urlField` | Read URLs from a dataset, e.g. the results of another scraper. Nested fields use dots (`page.url`). |
| `device` | `desktop`, `laptop`, `tablet`, `mobile` or `custom` (then set `width` and `height`). |
| `scaleFactor` | Pixel density: 1 = normal, 2 = retina. Defaults to the device's own value. |
| `fullPage` | Whole page instead of the visible window. Very long pages are cut at `maxHeight` (15,000 px by default). |
| `format`, `quality` | `png` (lossless), `jpeg` or `webp` (small files). |
| `clipSelector` | Capture one element only, e.g. `#pricing`. |
| `savePdf` | Also save an A4 PDF of each page. |
| `hideCookieBanners`, `blockAds`, `hideSelectors` | Page clean-up. |
| `scrollToBottom` | Load lazy images before full-page or element captures (on by default). |
| `darkMode` | Ask the site for its dark theme. |
| `waitUntil`, `delaySecs`, `waitForSelector` | When to take the picture. A page that never finishes loading is still captured at the timeout, with a warning. |
| `timeoutSecs`, `retries` | Per-page timeout and number of retries (network errors, timeouts, HTTP 429/5xx). |
| `maxConcurrency` | Pages captured in parallel (default 3). |
| `proxyConfiguration` | Apify Proxy or your own proxies. Off by default. |
| `outputZip` | One `screenshots.zip` with every image and PDF. |

### Output

Every image is stored in the run's **key-value store** under a readable key such as `apify.com-pricing-3f9a1c2b7d.png`, with a public link. Each URL also gets one dataset item:

```json
{
  "url": "https://apify.com",
  "finalUrl": "https://apify.com/",
  "status": 200,
  "title": "Apify: Full-stack web scraping and data extraction platform",
  "screenshotUrl": "https://api.apify.com/v2/key-value-stores/abc123/records/apify.com-1f0c9e0b2d.png",
  "screenshotKey": "apify.com-1f0c9e0b2d.png",
  "pdfUrl": null,
  "format": "png",
  "device": "desktop",
  "width": 1920,
  "height": 7342,
  "fullPage": true,
  "truncated": false,
  "bytes": 1843201,
  "contentType": "text/html",
  "cookieBannersHidden": 1,
  "loadTimeMs": 3120,
  "attempts": 1,
  "warnings": [],
  "takenAt": "2026-09-27T08:00:00.000Z",
  "error": null
}
```

A failed URL looks like this (and is not charged):

```json
{ "url": "https://no-such-domain.example", "screenshotUrl": null, "error": "Domain not found (DNS lookup failed). Check the address for typos.", "errorType": "navigation-failed", "attempts": 1 }
```

The dataset has two views: **Screenshots** (with image previews) and **Failed URLs**. The `OUTPUT` record in the key-value store has a summary of the run (counts, ZIP link, charged events).

#### Good to know

- **4xx and 5xx pages are still captured** (you see the error page) and the HTTP status is recorded, which is what you want for monitoring. 429 and 5xx responses are retried first.
- **Redirects are followed**; `finalUrl` shows where you ended up.
- **Direct links to PDF or other files** are reported as "not a web page" and not charged. Direct image links are captured, with a warning.
- **Invalid URLs** are listed in the results with a reason and never stop the run.
- If the run is restarted by the platform (e.g. server migration), already captured URLs are skipped, so nothing is charged twice.

### Pricing

Pay per event, only for results:

| Event | When |
|---|---|
| `screenshot` | One page captured and saved |
| `pdf-export` | One PDF saved (only when "Also save as PDF" is on) |

Failed, invalid and skipped URLs are free. The Actor checks your **maximum cost per run** before every page and stops cleanly when the next page would not fit, so you are never charged above your limit. Pages that were not processed are listed in the log and in `OUTPUT.notProcessed`.

### Memory and speed

- **2048 MB** memory with the default 3 parallel pages is a good start for most sites.
- For large batches use **4096 MB and 6–8 parallel pages**. Rule of thumb: one parallel page per 512 MB.
- Full-page **mobile** screenshots are 3× sharper and bigger; choose JPEG or WebP to keep files small.

### Use it from code, Make, Zapier or n8n

Start the Actor through the Apify API with the JSON input above, then read the dataset items (each has `screenshotUrl`). To screenshot the pages found by another Actor, set `startUrlsDatasetId` to that run's dataset ID and `urlField` to the field with the URL.

### Limitations

- Sites with strong bot protection may show a challenge page; try a residential proxy.
- Pages that scroll inside an inner container (instead of the whole window) are captured at window height in full-page mode.
- Content behind a login is not supported.
- WebP images are at most 16,383 px tall (a limit of the WebP format); longer pages are cut, with a warning.

# Actor input Schema

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

Web pages to capture, one per line, e.g. https://apify.com. Addresses without http(s):// get https:// added. Duplicates are skipped. Objects like {"url": "https://..."} are accepted too when calling via API.

## `startUrlsDatasetId` (type: `string`):

ID or name of an Apify dataset (e.g. the results of another Actor) to read URLs from. Combined with the list above. Useful for chaining: scrape a list of pages, then screenshot them.

## `urlField` (type: `string`):

Field of each dataset item that contains the URL. Nested fields use dots, e.g. "page.url". Ignored if no dataset is set.

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

Screen size and device type. Desktop 1920×1080, Laptop 1366×768, Tablet 768×1024 (2x pixels, touch), Mobile 390×844 (3x pixels, touch, mobile browser). Choose Custom to set your own width and height.

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

Browser window width in CSS pixels. Only used when Device is "Custom size".

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

Browser window height in CSS pixels. Only used when Device is "Custom size".

## `scaleFactor` (type: `number`):

Image pixels per CSS pixel. 1 = normal, 2 = retina-sharp (4× more pixels, bigger files). Leave empty to use the device default (desktop/laptop 1, tablet 2, mobile 3).

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

Capture the whole page from top to bottom instead of only the visible window.

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

PNG is lossless (best for text and QA). JPEG and WebP are much smaller (best for archives and AI). WebP images are at most 16,383 pixels tall.

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

Compression quality from 1 to 100 for JPEG and WebP. Ignored for PNG.

## `clipSelector` (type: `string`):

CSS selector of a single element to capture instead of the page, e.g. "#pricing" or "main article". The first matching element is used.

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

Full-page screenshots taller than this (in CSS pixels) are cut here, so endless-scroll pages do not produce giant images. 0 = no limit.

## `savePdf` (type: `boolean`):

Also save each page as an A4 PDF (print version of the page, with backgrounds). Charged as a separate PDF export event.

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

Hide cookie and consent pop-ups (OneTrust, Cookiebot, Didomi, Quantcast, TrustArc, Usercentrics, CookieYes and similar, plus generic fixed cookie bars). Nothing is clicked or accepted.

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

Block requests to common ad, tracking and analytics networks and hide empty ad slots. Pages usually also load faster.

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

CSS selectors of elements to remove before capturing, e.g. chat widgets or sticky headers: "#intercom-container", ".newsletter-popup".

## `scrollToBottom` (type: `boolean`):

For full-page and element screenshots: scroll through the page first so lazy-loaded images and sections appear, then go back to the top.

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

Tell the website the visitor prefers a dark color scheme. Only sites that support dark mode change.

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

When the page counts as loaded. "Load" is best for most sites. "Network idle" waits until nothing loads for 0.5 s (good for single-page apps). If a page never reaches it, the screenshot is still taken at the timeout, with a warning.

## `delaySecs` (type: `number`):

Wait this long after the page has loaded, e.g. for animations, sliders or charts to finish.

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

CSS selector that must be visible before the screenshot, e.g. ".product-grid". If it does not appear in time, the URL is reported as failed (and not charged).

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

Maximum time for loading one page (per attempt).

## `retries` (type: `integer`):

How many times to retry a URL after a network error, timeout or HTTP 429/5xx response. Each retry uses a new proxy IP when a proxy is enabled.

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

How many pages are captured at the same time. Higher is faster but needs more memory: about 1 page per 512 MB (e.g. 4 at 2 GB, 8 at 4 GB).

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

Use a proxy for sites that block data-center traffic or show country-specific content. Apify residential proxies help with strict anti-bot sites. No proxy by default.

## `userAgent` (type: `string`):

Override the browser's User-Agent header. Leave empty to use a normal Chrome user agent that matches the chosen device.

## `outputZip` (type: `boolean`):

Bundle all screenshots (and PDFs) into one screenshots.zip in the key-value store. The download link is in the OUTPUT record.

## Actor input object example

```json
{
  "urls": [
    "https://apify.com",
    "https://www.wikipedia.org"
  ],
  "urlField": "url",
  "device": "desktop",
  "width": 1280,
  "height": 800,
  "fullPage": false,
  "format": "png",
  "quality": 80,
  "maxHeight": 15000,
  "savePdf": false,
  "hideCookieBanners": true,
  "blockAds": true,
  "scrollToBottom": true,
  "darkMode": false,
  "waitUntil": "load",
  "delaySecs": 1,
  "timeoutSecs": 60,
  "retries": 2,
  "maxConcurrency": 3,
  "proxyConfiguration": {
    "useApifyProxy": false
  },
  "outputZip": false
}
```

# Actor output Schema

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

All result items of this run.

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

Summary of the run with counts and download links.

# 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"
    ],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("egra_van/website-screenshot-pro").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",
    ],
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("egra_van/website-screenshot-pro").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"
  ],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call egra_van/website-screenshot-pro --silent --output-dataset

```

## MCP server setup

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

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/u8L0RjBNj21Su9mm7/builds/OXAljkqWeqqpsSgMk/openapi.json
