# Website Screenshot Generator (full page, mobile, PDF) (`mvkdata/website-screenshot`) Actor

Website screenshot API for any list of URLs: full-page or viewport webpage screenshots on desktop, tablet or mobile, as PNG, JPEG, WebP or URL to PDF. Cookie banners, popups and ads removed, lazy images loaded. Bulk-ready; pay only per successful screenshot, failed URLs are free.

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

## Pricing

from $1.50 / 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.
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 Generator

Take screenshots of any list of web pages: **full page or visible window, desktop, tablet or phone, PNG, JPEG, WebP or PDF**.
Cookie banners, popups and ads are removed for you, lazy-loaded images are loaded, and every screenshot gets a direct link.

**You pay only for screenshots that worked.** URLs that fail to load, or where the site shows an error or bot-block page
(HTTP 4xx/5xx), are listed in the results with the reason and are **not charged**.

### What you get

- **Full-page screenshots** that really contain the whole page: the actor scrolls through first so lazy images appear.
- **Clean pages**: consent dialogs are accepted (OneTrust, Cookiebot, Didomi, Sourcepoint, Usercentrics, Quantcast and
  buttons in 20+ languages), leftover banners, newsletter bars, chat widgets and modal popups are hidden, ad networks blocked.
- **Real Chrome, not a stripped headless shell**: loads sites that block simple bots (tested on X, The New York Times,
  Zalando, Etsy, Amazon, LinkedIn, Instagram, CNN, BBC, YouTube, Booking).
- **7 devices** (desktop, full HD, laptop, retina MacBook, iPad, iPhone, Android) or any custom size and pixel ratio.
- **PNG, JPEG, WebP or PDF**, quality setting, transparent background, dark mode, single-element capture.
- **Fast batches**: several pages in parallel, automatic retries, crash-safe, a stuck page never blocks the run.
- **Drop-in for `apify/screenshot-url`**: the same input fields (`urls`, `format`, `waitUntil`, `delay`, `viewportWidth`,
  `scrollToBottom`, `selectorsToHide`, `proxy`) work unchanged.

### Input

The only required thing is a list of URLs. Everything else has good defaults.

```json
{
  "urls": [{ "url": "https://apify.com" }, { "url": "https://www.bbc.com" }],
  "format": "png",
  "fullPage": true,
  "device": "iphone"
}
```

| Field | What it does |
|---|---|
| `urls` | Pages to capture (list, or upload a text file). |
| `format` | `png`, `jpeg`, `webp` or `pdf`. |
| `fullPage` | Whole scrollable page instead of the visible window. |
| `device` | `desktop` (1280x800), `desktop_hd`, `laptop`, `macbook_retina`, `tablet`, `iphone`, `android`. |
| `viewportWidth` / `viewportHeight` / `deviceScaleFactor` | Custom size and pixel ratio. |
| `hideCookieBanners`, `hidePopups`, `blockAds` | Clean-up, all on by default. |
| `hideSelectors` | Your own CSS selectors to hide. |
| `waitUntil`, `waitForSelector`, `delay` | When to take the shot. |
| `selector` | Capture one element only. |
| `colorScheme`, `locale`, `timezoneId`, `userAgent`, `cookies` | Dark mode, language, time zone, logged-in sessions. |
| `proxyConfiguration` | Optional proxy (Apify datacenter proxy or your own proxy URLs), e.g. to see a site from a given country. |

### Output

One dataset row per URL; the files are in the run's key-value store.

```json
{
  "url": "https://www.bbc.com",
  "screenshotUrl": "https://api.apify.com/v2/key-value-stores/.../records/shot-www-bbc-com-05e9df12.png",
  "title": "BBC Home - Breaking News, World News, US News, Sports, Business, Innovation, Climate, Culture, Travel, Video & Audio",
  "statusCode": 200,
  "finalUrl": "https://www.bbc.com/",
  "format": "png",
  "device": "desktop",
  "fullPage": false,
  "viewport": "1280x800@1.0x",
  "sizeBytes": 369719,
  "loadMs": 2050,
  "attempts": 1,
  "error": null,
  "capturedAt": "2026-11-05T18:50:12Z"
}
```

Failed URLs have `screenshotUrl: null` (or the error page's screenshot) and `error` set; they are also collected in the
`FAILED_URLS` record of the key-value store.

### Pricing

Pay per successful screenshot, plus a tiny start fee per run. No charge for failed URLs or bot-block pages, and no separate
platform usage costs. Set "Maximum cost per run" and the actor stops cleanly when it is reached.

### Tips

- **Monitoring a page over time**: create a task with your URL and add a schedule; each run stores a new screenshot.
- **Big batches faster**: the default 1 GB renders one page at a time; give the run 4 GB to capture 4 pages in parallel
  (same price per screenshot).
- **Huge pages**: full-page shots are capped at about 16,000 px height so Chrome does not crash.
- **Slow pages**: a page that never finishes loading is still captured after `pageTimeoutSecs`; use `waitForSelector` to wait
  for the part you need.
- **Sites behind a login**: pass your session cookies in `cookies`.
- **A site still blocks the visit**: try `proxyConfiguration` with Apify proxy, or your own residential proxy URLs.

### URL to PDF

Set `format` to `pdf` to save each URL as a PDF document: the page width follows the chosen device, background graphics are
kept, and with `fullPage` the whole page goes into the PDF. Cookie banners and popups are removed first, so the PDF shows the
page itself.

### Switching from apify/screenshot-url

Paste your existing input: `urls`, `format`, `waitUntil`, `delay`, `viewportWidth`, `scrollToBottom`, `selectorsToHide` and
`proxy` work unchanged. Differences you get on top: full-page shots that include lazy-loaded images, cleaned cookie banners
and popups, mobile/tablet devices, WebP and PDF output, and no charge for failed URLs or bot-block pages.

### FAQ

**Is there a screenshot API?** Yes: call the actor from any language over the Apify API (example below), from the Apify
Python/JavaScript clients, or connect it to Make, Zapier, n8n or a webhook. Each run returns a JSON row per URL with a direct
image link.

**How many URLs can I capture at once?** Any number. Big lists run in one go with retries; give the run more memory to
capture several pages in parallel.

**Can it screenshot pages behind a login?** Yes, pass your session cookies in `cookies`.

**What do I pay for a page that fails?** Nothing. Only screenshots that worked are charged.

### Use it from code

```bash
curl -X POST "https://api.apify.com/v2/acts/mvkdata~website-screenshot/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" -d '{"urls":[{"url":"https://apify.com"}],"fullPage":true}'
```

Questions or a site that does not work? Open an issue on the Issues tab, it gets fixed fast.

# Actor input Schema

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

Pages to capture. One screenshot per URL. You can paste a list or upload a text file.

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

Image format of the screenshot, or PDF.

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

Capture the whole scrollable page instead of only the visible window.

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

Screen size and browser type to emulate. Width/height below override it.

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

Custom window width. Leave empty to use the device's width.

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

Custom window height. Leave empty to use the device's height.

## `deviceScaleFactor` (type: `integer`):

1 = normal, 2 = retina (twice the pixels), 3 = high-end phone.

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

Compression quality from 1 to 100.

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

Accepts consent dialogs and hides any banner that is left.

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

Blocks common ad networks: cleaner and faster screenshots.

## `hidePopups` (type: `boolean`):

Hides newsletter/fundraiser bars, chat widgets and modal windows that cover the page. The site header stays.

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

Elements to hide before capturing, e.g. .chat-widget or #newsletter-popup.

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

Scrolls through the page first so lazy-loaded images appear. On automatically for full-page screenshots.

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

When the page counts as loaded. If it never gets there, the screenshot is still taken at the timeout.

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

CSS selector that must be visible before the screenshot is taken.

## `delay` (type: `integer`):

Wait this long after loading (animations, charts).

## `maxLoadWaitSecs` (type: `integer`):

Longest wait for the 'Wait until' state. Pages with endless background requests are captured after this.

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

CSS selector of a single element to capture instead of the page.

## `colorScheme` (type: `string`):

Force light or dark mode on sites that support it.

## `transparentBackground` (type: `boolean`):

Removes the default white background on pages that do not set one.

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

e.g. en-US, de-DE, fr-FR.

## `timezoneId` (type: `string`):

e.g. Europe/Berlin, America/New_York.

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

Custom user agent string. Leave empty for a normal Chrome / Safari one matching the device.

## `cookies` (type: `array`):

Cookies to set before loading, e.g. a login session: \[{"name": "session", "value": "...", "domain": ".example.com"}].

## `pageTimeoutSecs` (type: `integer`):

Maximum time to load one page.

## `maxRetries` (type: `integer`):

How often a URL that fails to load is tried again.

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

Pages captured at the same time. Leave empty to pick from the run's memory.

## `maxItems` (type: `integer`):

Capture only the first N URLs (0 = all).

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

Optional: route pages through a proxy, e.g. to capture a site as seen from a given country.

## Actor input object example

```json
{
  "urls": [
    {
      "url": "https://apify.com"
    }
  ],
  "format": "png",
  "fullPage": false,
  "device": "desktop",
  "quality": 80,
  "hideCookieBanners": true,
  "blockAds": true,
  "hidePopups": true,
  "waitUntil": "load",
  "delay": 0,
  "maxLoadWaitSecs": 15,
  "colorScheme": "no-preference",
  "transparentBackground": false,
  "pageTimeoutSecs": 60,
  "maxRetries": 2,
  "maxItems": 0,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

## `files` (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": [
        {
            "url": "https://apify.com"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("mvkdata/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": [{ "url": "https://apify.com" }] }

# Run the Actor and wait for it to finish
run = client.actor("mvkdata/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": [
    {
      "url": "https://apify.com"
    }
  ]
}' |
apify call mvkdata/website-screenshot --silent --output-dataset

```

## MCP server setup

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