# Website Screenshot API: Full Page, PDF, Mobile, No Banners (`ucchiii/website-screenshot`) Actor

Website Screenshot API: capture full-page or element screenshots (PNG, JPEG, WebP) and PDFs of any public URL. Desktop, tablet, mobile and OG-image sizes, dark mode, cookie-banner hiding, ad blocking. $0.004 per screenshot, $0.006 per PDF; failures are free.

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

## Pricing

Pay per event

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 API — full page, PDF, mobile, no cookie banners

**For SEO teams, QA engineers, marketers and developers who need reliable screenshots of web pages.** Send a list of URLs
and get a **PNG, JPEG, WebP or PDF** of each one, stored in your key-value store with a public link in the dataset.
**$0.004 per screenshot, $0.006 per PDF — and you only pay when the file was stored successfully.** Leave the input empty
for a free demo.

### Use cases

- **Visual monitoring** of landing pages, pricing pages and competitors (run on a schedule, compare images)
- **Open Graph / social preview images** (device `og`, 1200x630)
- **Archiving** pages as evidence or records, as PDF or full-page PNG
- **Responsive QA**: the same URLs at desktop, tablet and mobile (390x844, 3x, mobile user agent) sizes
- **Docs, reports and thumbnails**: capture one element (`#pricing`, `main article`) instead of the whole page

### Features

- Formats: PNG, JPEG, WebP (with quality) and PDF
- Devices: desktop 1440x900 (default), laptop 1366x768, tablet 768x1024, mobile 390x844, og 1200x630, or custom width/height/scale factor
- Full page (height capped at 20,000 px), optional scroll to trigger lazy-loaded images
- Element screenshot with a CSS selector
- Dark mode, wait strategy (`load`, `domcontentloaded`, `networkidle`) and extra delay (up to 10 s)
- **Hide cookie banners**: CSS hides common consent pop-ups (OneTrust, Cookiebot, Didomi, Quantcast, TrustArc, Usercentrics, CookieYes, Osano and generic cookie banners). Nothing is clicked or accepted.
- **Block ads and trackers**: requests to a small built-in list of common ad/tracking domains are blocked (not a complete filter)

### Price

| Event | Price |
|---|---|
| `screenshot` (PNG, JPEG, WebP) | $0.004 |
| `pdf` | $0.006 |

**Not charged on failures:** timeouts, navigation errors, HTTP 4xx/5xx pages, selector not found, blocked or unsupported
URLs, invalid URLs and files that could not be stored. A row is charged only after its file is stored. If you set a
maximum cost per run, the run stops when the limit is reached. The empty-input demo is free.

### Input

```json
{
  "urls": ["https://example.com", "https://www.python.org"],
  "format": "png", "device": "desktop", "fullPage": true, "scrollToLazyLoad": true,
  "hideCookieBanners": true, "blockAds": false, "waitUntil": "load", "delayMs": 0
}
```

Up to 100 URLs per run (extra URLs are ignored with a warning). Other fields: `quality` (JPEG/WebP, default 80), `width`, `height`,
`deviceScaleFactor` (device `custom` only), `darkMode`, `selector`. There is no login, cookie, header or raw-HTML input.

### Output

One dataset row per URL:

```json
{
  "url": "https://example.com", "finalUrl": "https://example.com/", "status": 200, "format": "png",
  "width": 1440, "height": 900, "bytes": 18234,
  "imageUrl": "https://api.apify.com/v2/key-value-stores/<storeId>/records/screenshot-001-1a2b3c4d5e.png",
  "key": "screenshot-001-1a2b3c4d5e.png", "capturedAt": "2026-10-19T09:00:00+00:00", "error": null
}
```

The file itself is stored in the run's default key-value store with the correct content type. `width`/`height` are the
image size in pixels (`null` for PDF). `imageUrl` is a signed link that opens without an API token; anyone who has the link can open that image, so share it only where you want to. Failed rows have `imageUrl: null` and `error` set to one of: `invalid_url`,
`unsupported_domain`, `blocked_private_address`, `timeout`, `navigation_failed`, `http_<status>`, `selector_not_found`,
`invalid_selector`, `capture_failed`, `storage_failed`. Demo rows carry `_demo: true`.

### Limits

- 100 URLs per run, 4 pages at a time overall, at most 2 at a time per host, 45 s per page
- Full-page height capped at 20,000 px; very long pages are cut at the cap
- Public pages only: no login, no cookies, no custom headers, no HTML input. Pages behind a consent wall that CSS cannot hide, or behind bot protection, may capture the wall (or fail)
- Facebook, Instagram, X/Twitter, TikTok, LinkedIn and Threads are refused (`unsupported_domain`)

### Safety

Only `http`/`https` URLs are accepted. Every host is resolved first and **localhost, private ranges, link-local
(169.254.169.254) and other internal addresses are never contacted** — for the URL itself, each redirect hop and every
request the page makes. Known limit: a DNS answer that changes between the check and the connection (DNS rebinding) is not
detected. You are responsible for having the right to capture the pages you submit (site terms, copyright). Files stay in
your own storage; nothing is kept by the developer.

### More tools from the same developer

- [Sitemap URL Extractor](https://apify.com/ucchiii/sitemap-urls) — list every URL of a website from its sitemaps
- [Google Sheets Export](https://apify.com/ucchiii/google-sheets-export) — export an Apify dataset to Google Sheets

# Actor input Schema

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

Public http(s) URLs to capture, up to 100 per run. Leave empty for a free demo (example.com, not charged). Social networks and login-wall sites (Facebook, Instagram, X/Twitter, TikTok, LinkedIn, Threads) and internal addresses are refused.

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

Output file type: 'png' (default), 'jpeg', 'webp' or 'pdf'. PDF is billed as the PDF event, the others as a screenshot.

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

Compression quality for JPEG and WebP, 1 to 100 (default 80). Ignored for PNG and PDF.

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

Viewport preset: 'desktop' 1440x900 (default), 'laptop' 1366x768, 'tablet' 768x1024, 'mobile' 390x844 with mobile user agent, 'og' 1200x630 (Open Graph image), or 'custom' to use the width, height and deviceScaleFactor below.

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

Viewport width, 200 to 3840. Used only when Device is Custom.

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

Viewport height, 200 to 4000. Used only when Device is Custom.

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

Pixel density, 1 to 4 (2 = retina). Used only when Device is Custom.

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

Ask the page for its dark color scheme (prefers-color-scheme: dark). Only sites that support it change.

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

Capture the whole scrollable page instead of only the first screen. Height is capped at 20,000 px.

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

Optional. Capture only the first element matching this CSS selector, for example #pricing or main article. If nothing matches, the row gets error selector_not_found (not charged).

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

When the page counts as loaded: 'load' (default), 'domcontentloaded' (fastest) or 'networkidle' (slowest, for late content). Each page has a 45 second limit.

## `delayMs` (type: `integer`):

Wait this long after loading before capturing, 0 to 10000 ms. Useful for animations.

## `scrollToLazyLoad` (type: `boolean`):

Scroll down the page before capturing so lazy-loaded images appear. Recommended together with Full page.

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

Block requests to a small built-in list of common ad and tracking domains. Not a complete filter.

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

Hide common consent pop-ups (OneTrust, Cookiebot, Didomi, Quantcast, TrustArc, Usercentrics, CookieYes, Osano and generic cookie banners) with CSS. Nothing is clicked or accepted.

## Actor input object example

```json
{
  "urls": [
    "https://example.com",
    "https://www.python.org"
  ],
  "format": "png",
  "quality": 80,
  "device": "desktop",
  "width": 1440,
  "height": 900,
  "deviceScaleFactor": 1,
  "darkMode": false,
  "fullPage": false,
  "waitUntil": "load",
  "delayMs": 0,
  "scrollToLazyLoad": false,
  "blockAds": false,
  "hideCookieBanners": false
}
```

# Actor output Schema

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

One item per URL: status, format, width, height, bytes, imageUrl (link to the file), capturedAt, error.

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

The screenshot and PDF files in the run's key-value store.

# 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://example.com",
        "https://www.python.org"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("ucchiii/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://example.com",
        "https://www.python.org",
    ] }

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

```

## MCP server setup

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