# Website Screenshot — Full-Page, Mobile & PDF, No Cookie Banners (`adorable_partial/website-screenshot`) Actor

Capture full-page, viewport, element or fixed-height screenshots and PDFs of any website in bulk. Desktop, tablet & mobile, cookie banners hidden, lazy images loaded, stealth Chrome for blocked sites. Flat price per screenshot; failures are free.

- **URL**: https://apify.com/adorable_partial/website-screenshot.md
- **Developed by:** [Leandro Zanatta](https://apify.com/adorable_partial) (community)
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.50 / 1,000 screenshot captureds

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 — Full-Page, Mobile & PDF, No Cookie Banners

Capture **clean screenshots of any website** in bulk: **full page** (with lazy images loaded), **visible area**, **fixed height**, **one element** by CSS selector, or **PDF**. Desktop, laptop, tablet and **real mobile layouts**. **Cookie banners and consent pop-ups are hidden**, ads and chat bubbles are blocked, and pages that block automated browsers are retried automatically in **stealth mode** with real Google Chrome. **Flat price per screenshot**, and **failed or blocked pages are free**.

![Before and after hiding a consent wall, a stealth-mode capture, a mobile screenshot, an element screenshot and a full-page capture](https://api.apify.com/v2/key-value-stores/jf9P3UxOnBuO3TCUn/records/demo.png?signature=1LlBn1LHQPgR2geTyik0o)

*Real output of this Actor.*

### Why this screenshot Actor

Built from what users of other screenshot tools complain about:

| Common complaint | What this Actor does |
|---|---|
| "Slow and expensive: minutes and cents per screenshot" | Several pages in parallel in one browser, **flat price per screenshot** (see Pricing) instead of paying for compute time |
| "It didn't work and still used my credits" | Pages answering **4xx/5xx**, bot checks and errors are **not billed** and get a clear reason |
| "Full page only captures above the fold" | Scrolls the whole page first so **lazy images and sections load**, then captures up to 60,000 px |
| "Can't set the height / capture only the top" | Modes **Visible area**, **Fixed height** (any pixel height) and **Element** (CSS selector) |
| "Sticky header repeated / page not loaded yet" | Native full-page capture (no stitching), waits for the network and fonts, optional extra delay |
| "Emojis show as boxes" | **Color emoji and CJK fonts** installed |
| Cookie walls covering the page | Consent dialogs of the common platforms (OneTrust, Cookiebot, Didomi, Quantcast, Sourcepoint, Usercentrics…) and generic cookie bars are **hidden**, never accepted on your behalf |
| Sites that block bots (403, "Just a moment…") | **Automatic stealth retry** with undetected-chromedriver and real Google Chrome |

### Who uses it

| Use | Typical setup |
|---|---|
| **Website monitoring & visual change tracking** | Schedule daily full-page screenshots and compare them |
| **SEO, marketing & agencies** | Capture client and competitor landing pages, ads landing pages and SERPs for reports |
| **QA & design review** | Desktop, tablet and mobile screenshots of every page of a site |
| **Compliance & legal evidence** | Timestamped captures of terms, prices, claims or ads, as PNG or PDF |
| **E-commerce & price intelligence** | Product pages and pricing tables as images for audits |
| **AI agents & LLM pipelines** | Give a vision model a clean picture of a page (no cookie wall in the way) |
| **Link previews & thumbnails** | Visible-area JPEG/WebP thumbnails for directories and dashboards |

### Capture modes

| Mode | Result |
|---|---|
| **Full page** (default) | The whole page down to *Max height* (16,000 px by default, up to 60,000), after scrolling to load lazy content |
| **Visible area** | Exactly what fits the screen (above the fold) |
| **Fixed height** | The top *N* pixels of the page (e.g. 1,500), even beyond the screen |
| **Element** | One element by CSS selector, e.g. `#pricing`, `.product-card`, `article` |
| **PDF** | Printable PDF (A4 or Letter) with backgrounds |

| Device | Screen |
|---|---|
| Desktop (default) | 1920×1080 |
| Laptop | 1366×768 |
| Tablet | 820×1180, 2× density, touch, mobile user agent |
| Mobile | 390×844 (iPhone size), 2× density, touch, mobile user agent |

Custom width, height and pixel density (1–3×) override the device.

### Input

| Field | Default | Description |
|---|---|---|
| **Page URLs** (`urls`) | — | Pages to capture; `https://` is added if missing |
| **What to capture** (`mode`) | `fullPage` | `fullPage`, `viewport`, `fixedHeight`, `element`, `pdf` |
| **Device** (`device`) | `desktop` | `desktop`, `laptop`, `tablet`, `mobile` |
| **Image format** (`format`) | `png` | `png`, `jpeg`, `webp` |
| **Hide cookie banners** (`hideCookieBanners`) | `true` | Hide consent dialogs and unlock scrolling |
| **Block ads and chat widgets** (`blockAds`) | `true` | Cleaner and faster pages |
| **Browser engine** (`engine`) | `auto` | `auto` (fast, stealth if blocked), `fast`, `stealth` |
| **Height for Fixed height** (`clipHeight`) | 1080 | Pixels from the top |
| **Max height for full page** (`maxHeight`) | 16000 | Cut very long / infinite pages |
| **CSS selector** (`selector`) | — | For element mode |
| **Also hide these elements** (`hideSelectors`) | — | Extra CSS selectors to hide (promo bars, app banners…) |
| **Extra wait** (`delaySeconds`) | 0 | For animations and slow widgets |
| **Scroll to load lazy content** (`scrollToLoad`) | `true` | For full-page and fixed-height captures |
| **Dark mode** (`darkMode`) | `false` | Request the page's dark theme |
| **Custom width / height / pixel density** | device | `viewportWidth`, `viewportHeight`, `scaleFactor` |
| **JPEG/WebP quality** (`quality`) | 85 | 30–100 |
| **PDF paper size** (`pdfFormat`) | `A4` | `A4` or `Letter` |
| **Browser language** (`locale`) | `en-US` | e.g. `pt-BR`, `de-DE` |
| **Page timeout** (`timeoutSeconds`) | 45 | Per page |
| **Capture error pages too** (`captureErrorPages`) | `false` | Also capture 4xx/5xx and bot-check pages (billed) |
| **Max parallel pages** (`maxConcurrency`) | 8 | Also limited by memory (1 page per GB) |
| **Proxy** (`proxyConfiguration`) | none | Apify Proxy, e.g. residential or a country, for strict sites or local versions |

```json
{
  "urls": ["https://www.example.com", "https://www.example.com/pricing"],
  "mode": "fullPage",
  "device": "mobile",
  "format": "webp",
  "hideSelectors": [".promo-bar"]
}
```

### Output

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

```json
{
  "url": "https://www.theguardian.com/international",
  "mode": "fullPage",
  "device": "desktop",
  "screenshotUrl": "https://api.apify.com/v2/key-value-stores/.../records/screenshot-0003-www-theguardian-com-international.jpg",
  "format": "jpg",
  "bytes": 1384299,
  "finalUrl": "https://www.theguardian.com/international",
  "statusCode": 200,
  "title": "Latest news, sport and opinion from the Guardian",
  "pageHeight": 21053,
  "width": 1920,
  "height": 8000,
  "consentBannersHidden": 0,
  "engine": "fast"
}
```

`engine` tells you whether the fast browser or stealth mode was used. Failed pages have an `error` field explaining why (blocked, 404, timeout…) and are **not billed**.

### Pricing

Flat **pay per screenshot**, plus a tiny per-run start fee. No compute-time surprises. See the **Pricing** tab for current prices and plan discounts.

- **Screenshot captured**: every successful image or PDF.
- **Stealth mode used**: small extra, only when a site blocked the fast browser and stealth Chrome got the page.
- **Failed, blocked or error pages: free.**

Set a *maximum cost per run* to cap spending; the Actor stops cleanly at the limit.

### Measured on the platform

On 20 well-known sites (news, tech, e-commerce, government) captured from the Apify cloud with default settings, **18 succeeded in one run**, including Reddit through the automatic stealth retry; the two misses (a page that reloads itself and a very heavy news page) were fixed and captured in the next version. In stealth mode the Actor got through sites that answer 403 to headless browsers in our tests (El País, Stack Overflow, Reddit, The New York Times). Some sites block data-center IP addresses entirely; for those, add Apify Proxy (residential).

### Use it from code or an AI agent

**Python**

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("adorable_partial/website-screenshot").call(run_input={
    "urls": ["https://www.example.com", "https://www.example.com/blog"],
    "mode": "fullPage", "format": "jpeg",
})
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(row["url"], row.get("screenshotUrl") or row.get("error"))
```

**JavaScript**

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('adorable_partial/website-screenshot').call({
    urls: ['https://www.example.com'],
    device: 'mobile',
    mode: 'viewport',
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0].screenshotUrl);
```

**HTTP (one request, waits for the result)**

```bash
curl -X POST "https://api.apify.com/v2/acts/adorable_partial~website-screenshot/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"urls": ["https://www.example.com"], "mode": "viewport", "format": "webp"}'
```

**No-code and agents:** schedule daily captures, send them to Slack, Drive or e-mail with **Make**, **Zapier** or **n8n**, or let an AI agent take screenshots through the **Apify MCP server**.

### FAQ

**Are cookies accepted to remove the banner?** No. Banners are hidden with CSS; nothing is clicked or accepted. The page is shown as it looks behind the dialog.

**Does stealth mode solve CAPTCHAs?** No. If a site still requires a CAPTCHA or human check, the page is reported as blocked and not billed.

**Can I log in to a site?** Not in this version. Public pages only.

**Why is a page cut?** Full-page captures stop at *Max height* (16,000 px by default). Raise it up to 60,000 px for very long pages.

**Can I capture a specific country's version of a site?** Use *Proxy* with an Apify Proxy country, and set *Browser language* (e.g. `pt-BR`).

**Is it legal?** Taking screenshots of public web pages is common practice. Respect each site's terms and copyright when you reuse the images.

### Related Actors

- [EXIF & GPS Cleaner](https://apify.com/adorable_partial/exif-gps-cleaner) — remove hidden metadata from photos
- [Image Quality Checker](https://apify.com/adorable_partial/image-quality-checker) — flag blurry, dark and duplicate images
- [Image & Video Anonymizer](https://apify.com/adorable_partial/image-anonymizer) — blur faces and license plates in screenshots before sharing
- [PII Masker](https://apify.com/adorable_partial/pii-masker) — mask personal data in texts and datasets

### Support

A page that doesn't look right? Open an issue in the **Issues** tab with the URL and the settings you used; it will be answered there.

### Need a different tool? Request it

Missing a feature, an input or output format, or a whole different tool for your workflow? **Open an issue in the Issues tab** and describe what you need:

- what goes in (files, URLs, data) and what should come out,
- roughly how much you process (per day or month),
- one example, if you can share it.

Requests with a real use case get built, either as a new option in this Actor or as a new Actor in [this collection](https://apify.com/adorable_partial), and you get notified in the issue when it's live. Every request is read.

# Actor input Schema

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

Pages to capture. 'https://' is added if missing. Hundreds per run are fine.

## `mode` (type: `string`):

Full page captures everything down to 'Max height'. Fixed height lets you choose exactly how many pixels from the top.

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

Screen size and type. Tablet and mobile get a mobile user agent and touch, so you see the real mobile layout.

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

Ignored for PDF.

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

Hides consent dialogs of the common platforms (OneTrust, Cookiebot, Didomi, Quantcast, Sourcepoint, Usercentrics...) and generic cookie bars, and unlocks scrolling. Nothing is accepted on your behalf.

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

Blocks the main ad networks and chat bubbles for cleaner, faster pages.

## `engine` (type: `string`):

Stealth mode uses undetected-chromedriver with real Google Chrome for sites that block automated browsers. CAPTCHAs are never solved: pages that still demand one are reported and not billed.

## `clipHeight` (type: `integer`):

How many CSS pixels from the top to capture in Fixed height mode.

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

Very long pages (infinite scroll) are cut at this height.

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

For example '#pricing', '.product-card' or 'article'. The first match is captured.

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

CSS selectors to hide before capturing (headers, chat bubbles, promo bars...).

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

Wait after the page is loaded, for animations or slow widgets.

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

Scroll through the page before a full-page capture so lazy images load.

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

Ask the page for its dark theme (prefers-color-scheme: dark).

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

Overrides the device width.

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

Overrides the device height.

## `scaleFactor` (type: `integer`):

1 = normal, 2 = retina. Default depends on the device.

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

30-100.

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

For PDF mode.

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

Language the browser reports, e.g. en-US, pt-BR, de-DE. Sites may show content in this language.

## `timeoutSeconds` (type: `integer`):

Maximum time to load one page.

## `captureErrorPages` (type: `boolean`):

By default pages answering 4xx/5xx or showing a bot check are reported as errors and not billed. Turn on to capture them anyway (billed).

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

Upper limit of pages processed in parallel (also limited by memory: 2 per GB).

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

Optional. Use Apify Proxy (e.g. residential or a specific country) for sites that block data-center IPs or show country-specific content.

## Actor input object example

```json
{
  "urls": [
    "https://apify.com",
    "https://en.wikipedia.org/wiki/Web_scraping",
    "https://www.theguardian.com/international"
  ],
  "mode": "fullPage",
  "device": "desktop",
  "format": "png",
  "hideCookieBanners": true,
  "blockAds": true,
  "engine": "auto",
  "clipHeight": 1080,
  "maxHeight": 16000,
  "delaySeconds": 0,
  "scrollToLoad": true,
  "darkMode": false,
  "quality": 85,
  "pdfFormat": "A4",
  "locale": "en-US",
  "timeoutSeconds": 45,
  "captureErrorPages": false,
  "maxConcurrency": 8
}
```

# Actor output Schema

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

One row per page with the screenshot link, page title, size and engine used.

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

All captured 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://en.wikipedia.org/wiki/Web_scraping",
        "https://www.theguardian.com/international"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("adorable_partial/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://en.wikipedia.org/wiki/Web_scraping",
        "https://www.theguardian.com/international",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("adorable_partial/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://en.wikipedia.org/wiki/Web_scraping",
    "https://www.theguardian.com/international"
  ]
}' |
apify call adorable_partial/website-screenshot --silent --output-dataset

```

## MCP server setup

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