# Website Screenshot API: Full Page, Mobile, No Cookie Banners (`sokolovich/reliable-website-screenshot`) Actor

Bulk full-page and mobile screenshots of any public URL. Lazy images loaded, sticky headers fixed, cookie banners and pop-ups hidden. Failed pages are never charged; each run has a small start fee.

- **URL**: https://apify.com/sokolovich/reliable-website-screenshot.md
- **Developed by:** [Daniil Kravchenko](https://apify.com/sokolovich) (community)
- **Categories:** Developer tools, Automation, 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 full-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.

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

Capture clean screenshots of public web pages in bulk: the whole page or just the first screen, on desktop,
tablet or mobile — with lazy-loaded images actually loaded, sticky headers not repeated, and cookie banners and
sign-in pop-ups out of the way.

**Failed screenshots are never charged.** Pages that return an error, refuse automated access, show a bot
check, time out or render empty are reported in the dataset with `charged: false`. Each run also has a small
start fee (see [Pricing](#pricing)), which applies even if every page fails.

### Who it is for

- **SEO and marketing agencies** — weekly full-page snapshots of client and competitor landing pages.
- **No-code automations** (Make, n8n, Zapier) — "take a screenshot of this URL" as one reliable step.
- **AI agents and QA** — a visual of what a page really looks like, on desktop and mobile.

Example: an agency monitors 40 competitor pricing pages every Monday. It runs this Actor on a schedule with the
40 URLs in `fullPage` mode and gets 40 PNGs plus a table of which pages failed — failed pages are not billed.

### What it fixes compared with a plain screenshot

| Problem | What this Actor does |
|---|---|
| Images below the fold are blank | scrolls the page to trigger lazy loading, then returns to the top |
| Sticky header repeated / covering content in full-page shots | turns fixed and sticky elements into normal page flow before capture |
| Cookie banner covers the page | hides known consent managers and consent overlays — **nothing is accepted on your behalf** |
| Sign-in / newsletter pop-ups | hides modal dialogs, dark backdrops and floating sign-in widgets (`hidePopups`) |
| Can't choose the height | `viewport`, `fullPage` (up to 20,000 px) or `fixedHeight` (top N px) |
| Emoji show as boxes | colour-emoji and CJK fonts are installed in the image |
| Stuck runs | hard timeout per URL (`urlTimeoutSecs`), failed pages are not charged |

### Pricing

Pay per event. Prices are set in Apify Console; this table explains them.

| Event | Price | When |
|---|---|---|
| Full-page screenshot | $0.004 | per page captured successfully in `fullPage` or `fixedHeight` mode |
| First-screen screenshot | $0.002 | per page captured successfully in `viewport` mode |
| Actor start | $0.001 per GB of memory | once per run, charged by Apify at start: **$0.004 with the default 4 GB**, $0.002 with 2 GB |

Examples with the default 4 GB: 1 first-screen shot = $0.006; 40 full-page shots = $0.164; a run where every page
fails = $0.004. Viewport-only runs work with 2 GB of memory (set it in the run options) and pay a $0.002 start fee.
No separate platform-usage charge is added on top of these events.

### Input

```json
{
  "urls": ["https://www.bbc.com/news", "https://stripe.com", "https://en.wikipedia.org/wiki/Emoji"],
  "mode": "fullPage",
  "device": "desktop",
  "format": "png",
  "hideCookieBanners": true,
  "hidePopups": true,
  "blockAds": true
}
```

| Field | Default | Notes |
|---|---|---|
| `urls` | — | 1–500 public http(s) URLs; duplicates are captured once; `[{"url": ...}]` objects also accepted |
| `mode` | `fullPage` | `viewport`, `fullPage` (cut at 20,000 px), `fixedHeight` |
| `height` | 1080 | CSS pixels, used with `fixedHeight` |
| `device` | `desktop` | `desktop` 1280 px, `tablet` 820 px (2× density), `mobile` 390 px (3× density) |
| `format` | `png` | `png`, `jpeg`, `webp`; JPEG/WebP files are 3–10× smaller |
| `quality` | 85 | JPEG/WebP only |
| `waitMs` | 0 | extra wait after load (animations) |
| `hideCookieBanners`, `hidePopups`, `blockAds` | true | see table above |
| `hideSelectors` | \[] | your own CSS selectors to hide (chat widgets, promo bars) |
| `urlTimeoutSecs` | 90 | per URL (5–300); slower pages are reported as failed and not charged |

Image width/height in the output are in **device pixels** (a 390 px wide mobile viewport at 3× density gives a
1170 px wide image).

### Output

One dataset item per URL; images are stored in the run's key-value store and linked by `screenshotUrl`.

```json
{
  "url": "https://www.bbc.com/news",
  "finalUrl": "https://www.bbc.com/news",
  "httpStatus": 200,
  "status": "ok",
  "screenshotUrl": "https://api.apify.com/v2/key-value-stores/<store>/records/screenshot-0001-….png",
  "width": 1280, "height": 6541, "bytes": 3589541,
  "title": "BBC News - Breaking news, video and the latest top stories …",
  "error": null, "mode": "fullPage", "device": "desktop", "format": "png",
  "durationMs": 4135, "capturedAt": "2026-10-06T10:02:11+00:00", "charged": true
}
```

`status` is `ok`, `blocked` (the site refused automated access, HTTP 401/403/429/451 or a bot check — never
bypassed) or `error` (DNS/TLS/timeout/HTTP error/empty page/invalid URL). Only `ok` items are charged.

### Limits and honest notes

- Public pages only: no logins, no cookies/sessions, no proxies, no CAPTCHA solving. Sites that block automated
  browsers return `blocked`.
- Cookie banners are hidden visually; the page is captured as a first-time visitor who has not consented, so some
  sites show reduced content.
- Very long pages are cut at 20,000 px; video is not loaded (poster frames only) when `blockAds` is on.
- Very long documents are cut at 20,000 px *before* rendering, so even 100,000-px pages are captured in seconds.
- Emoji added in the newest Unicode release (16.0) may still show as boxes until the system fonts catch up.
- Default memory is 4 GB (heavy pages need more than 2 GB); for viewport-only runs 2 GB is enough.
- You are responsible for having the right to capture and use screenshots of the pages you submit.

### Run locally

```bash
pip install -r requirements.txt && playwright install chromium
mkdir -p storage/key_value_stores/default && cp example_input.json storage/key_value_stores/default/INPUT.json
python -m src
```

# Actor input Schema

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

Public http(s) pages to capture (max 500 per run). Duplicates are captured once.

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

viewport = first screen only; fullPage = whole page (cut at 20,000 px); fixedHeight = top N pixels.

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

Used only with mode = fixedHeight.

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

Browser window to emulate. Tablet and mobile use touch, a mobile user agent and 2-3x pixel density.

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

PNG is lossless; JPEG and WebP files are 3-10x smaller.

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

Image quality for JPEG and WebP (ignored for PNG).

## `waitMs` (type: `integer`):

Waits after the page is loaded, e.g. for animations.

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

Hides consent pop-ups from the image. Nothing is accepted on your behalf.

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

Hides sign-in/newsletter modals and dark overlays that cover the page.

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

Faster and cheaper captures; ad slots may appear empty.

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

e.g. chat widgets or promo bars.

## `urlTimeoutSecs` (type: `integer`):

A page that is not captured within this time is reported as failed and not charged.

## Actor input object example

```json
{
  "urls": [
    "https://apify.com",
    "https://en.wikipedia.org/wiki/Web_scraping"
  ],
  "mode": "fullPage",
  "height": 1080,
  "device": "desktop",
  "format": "png",
  "quality": 85,
  "waitMs": 0,
  "hideCookieBanners": true,
  "hidePopups": true,
  "blockAds": true,
  "hideSelectors": [],
  "urlTimeoutSecs": 90
}
```

# Actor output Schema

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

Dataset items: url, status (ok/blocked/error), screenshotUrl, width, height, bytes, title, error, charged.

## `images` (type: `string`):

Key-value store listing of the captured images (screenshot-\*.png/jpg/webp).

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

// Run the Actor and wait for it to finish
const run = await client.actor("sokolovich/reliable-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",
    ] }

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

```

## MCP server setup

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