# Website Screenshot & PDF Capture with App Store Sizes (`blackcatforge/screenshot-capture`) Actor

Capture website screenshots and PDFs in bulk: full page or element, PNG/JPEG/WebP/PDF, desktop/tablet/mobile emulation, dark mode, cookie banners hidden, and exact App Store Connect screenshot sizes (iPhone 6.9"/6.5"/6.3"/6.1"/5.5", iPad 13"/11", Mac). Pay only per delivered capture.

- **URL**: https://apify.com/blackcatforge/screenshot-capture.md
- **Developed by:** [Blackcat Forge](https://apify.com/blackcatforge) (community)
- **Categories:** Developer tools, Automation, For creators
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 capture delivereds

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 & PDF Capture (App Store sizes, full page, WebP)

*By **Blackcat Forge***

Capture **screenshots and PDFs of any public web page in bulk**: the visible viewport, the full page, or a single element. Output is PNG, JPEG, WebP or PDF, with desktop, tablet and phone emulation, dark mode, and cookie banners hidden. Includes **ready-made App Store Connect sizes**, so a web app, landing page or prototype becomes upload-ready iPhone and iPad screenshots in one run.

Useful for visual monitoring and archiving, link previews and thumbnails, client reports, SEO and competitor audits, QA across devices, and App Store and marketing assets.

### Features

- **Sizes and devices.** Pick several at once and every URL is captured in each one:
  - Desktop 1920×1080, 1440×900 and 1440×900 @2x
  - Laptop 1366×768
  - Tablet (iPad) and Mobile (iPhone, @3x), with real device user agents and touch emulation
  - Social preview / Open Graph 1200×630
  - Custom width, height, scale and mobile mode
- **App Store Connect presets** that match Apple's required pixel sizes exactly, saved **without an alpha channel** (App Store Connect rejects transparency):

  | Preset | Output |
  |---|---|
  | iPhone 6.9" | 1320×2868 |
  | iPhone 6.5" | 1284×2778 |
  | iPhone 6.3" | 1206×2622 |
  | iPhone 6.1" | 1170×2532 |
  | iPhone 5.5" | 1242×2208 |
  | iPad 13" | 2064×2752 |
  | iPad 11" | 1668×2420 |
  | Mac | 2880×1800 |

  Each row reports `appStoreSizeOk: true`. Turn on **Landscape** for 2868×1320 and so on.
- **Full page** with lazy-loaded images triggered by scrolling (very long pages are cut at a configurable height), or **element capture** with any CSS selector.
- **Clean shots.** Common cookie-consent pop-ups are hidden: OneTrust, Cookiebot, Usercentrics, Didomi, Quantcast, TrustArc, Osano, Complianz, Termly and more. Nothing is clicked or accepted. You can also hide any extra elements you list, such as chat widgets or promo bars.
- **Waits for the page to settle.** It waits for the load event, then for network activity to calm down, then for web fonts, then an optional extra delay. Animations are frozen so captures are stable.
- **PDF** in A4, Letter, Legal, A3 or Tabloid, with screen or print styles and backgrounds included.
- **Dark mode** emulation (`prefers-color-scheme`).

### Input

```json
{
  "urls": ["https://apify.com", "https://www.python.org"],
  "presets": ["desktop-1920", "mobile", "appstore-iphone-6.9"],
  "format": "png",
  "fullPage": false,
  "hideCookieBanners": true
}
```

### Output

Each capture is saved as a file in the run's key-value store. The dataset holds one row per capture with a direct link:

```json
{
  "url": "https://www.python.org",
  "status": "ok",
  "preset": "appstore-iphone-6.9",
  "format": "png",
  "width": 1320,
  "height": 2868,
  "appStoreSizeOk": true,
  "bytes": 221898,
  "title": "Welcome to Python.org",
  "httpStatus": 200,
  "fileUrl": "https://api.apify.com/v2/key-value-stores/…/records/www-python-org-appstore-iphone-6.9-d2aa2c4e33.png"
}
```

### Pricing (pay per event)

| Event | Price |
|---|---|
| Capture delivered: one viewport, element or App Store size screenshot (one URL × one size) | **$0.004** ($4 per 1,000) |
| Full-page capture delivered: a full-page screenshot or a PDF | **$0.008** ($8 per 1,000) |
| Failed capture (timeout, HTTP 4xx/5xx, blocked, refused, selector not found) | free |
| Actor start (Apify standard) | $0.00005 per GB of run memory ($0.0002 at the default 4 GB) |

Examples: 1,000 home pages at one size cost $4. One app landing page in all 8 App Store sizes costs $0.032. App Store presets always count as a normal capture, even with Full page switched on.

Set **Max cost per run** and the Actor stops cleanly at your limit. Captures it couldn't charge for are never handed out.

### Good to know

- **No bot-protection bypass.** This Actor uses a normal headless Chrome with no proxies, CAPTCHA solving or stealth tricks. Pages that block automated browsers will show their block page or fail, and failures are free.
- **Refused by design:** private and local network addresses, and sites whose terms forbid automated access: Facebook, Instagram, Threads, LinkedIn, TikTok, X/Twitter, Reddit, Pinterest, YouTube and a few others.
- Videos and audio aren't downloaded by default (poster images still show), which keeps captures fast. Turn off *Skip video and audio downloads* if you need them.
- Full-page captures are limited to 12,000 CSS px tall by default (adjustable up to 20,000).

### Local development

```bash
pip install -r requirements.txt playwright && playwright install chromium
python -m pytest tests
apify run
```

*Blackcat Forge builds small, dependable tools for developers and creators.*

# Actor input Schema

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

Pages to capture. 'example.com' is fine (https is assumed). Each URL is captured once per selected size.

## `urlsText` (type: `string`):

Optional: paste a long list of URLs, one per line.

## `presets` (type: `array`):

One capture (and one charge) per URL per size. App Store presets produce the exact pixel sizes App Store Connect accepts, without an alpha channel.

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

PNG (lossless), JPEG or WebP (small files), or PDF (whole page as a document).

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

Capture the whole scrollable page instead of just the visible viewport. Ignored for App Store presets (they must be exact sizes) and element captures.

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

Optional. For example #pricing or .hero. The first visible match is captured.

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

Hides common cookie-consent pop-ups (OneTrust, Cookiebot, Usercentrics, Didomi, Quantcast and more) so they don't cover the page. Nothing is clicked or accepted.

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

CSS selectors to hide before capturing, e.g. chat widgets or promo bars.

## `landscape` (type: `boolean`):

Rotate device presets to landscape (e.g. App Store 2868x1320). For PDFs, prints in landscape.

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

Emulate light or dark mode (prefers-color-scheme).

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

1-100. Ignored for PNG and PDF.

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

load (recommended): wait for the load event (up to 'Max wait for load event'), then settle. domcontentloaded: fastest. networkidle: strictest, waits for all network activity to stop (slow on busy sites).

## `loadWaitSecs` (type: `integer`):

Some pages never finish 'loading' (endless widgets). After this long the page is captured anyway and the row is flagged loadEventTimedOut.

## `settleSecs` (type: `integer`):

After the page loads, wait up to this long until images, fonts, styles and scripts stop loading for 0.5 s. Background polling and analytics are ignored.

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

Fixed extra wait right before the capture.

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

Give up on a page after this long. Timed-out pages are not charged.

## `maxFullPageHeight` (type: `integer`):

Very long pages are cut at this height.

## `javascript` (type: `boolean`):

Turn off to capture the page without running scripts.

## `blockMedia` (type: `boolean`):

Video/audio files aren't needed for a still image; skipping them makes captures faster. Poster images still show.

## `blockTrackers` (type: `boolean`):

Blocks invisible analytics/tracking beacons (Google Analytics, Hotjar, Segment, Clarity, pixels...). Faster, steadier captures; the page looks the same.

## `pdfPaperFormat` (type: `string`):

Only used when format is PDF.

## `pdfMedia` (type: `string`):

screen = looks like the website; print = uses the site's print stylesheet.

## `custom` (type: `object`):

Used when the 'custom' preset is selected: {"width": 1280, "height": 800, "deviceScaleFactor": 1, "isMobile": false}. 100-3840 px per side.

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

Pages captured at the same time (1-8). 3 suits the default 4 GB memory.

## Actor input object example

```json
{
  "urls": [
    "https://apify.com",
    "https://www.python.org"
  ],
  "presets": [
    "desktop-1920"
  ],
  "format": "png",
  "fullPage": false,
  "hideCookieBanners": true,
  "hideSelectors": [],
  "landscape": false,
  "colorScheme": "light",
  "quality": 85,
  "waitUntil": "load",
  "loadWaitSecs": 15,
  "settleSecs": 3,
  "delayMs": 0,
  "timeoutSecs": 30,
  "maxFullPageHeight": 12000,
  "javascript": true,
  "blockMedia": true,
  "blockTrackers": true,
  "pdfPaperFormat": "A4",
  "pdfMedia": "screen",
  "custom": {
    "width": 1280,
    "height": 800,
    "deviceScaleFactor": 1,
    "isMobile": false
  },
  "maxConcurrency": 3
}
```

# Actor output Schema

## `results` (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": [
        "https://apify.com",
        "https://www.python.org"
    ],
    "custom": {
        "width": 1280,
        "height": 800,
        "deviceScaleFactor": 1,
        "isMobile": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("blackcatforge/screenshot-capture").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.python.org",
    ],
    "custom": {
        "width": 1280,
        "height": 800,
        "deviceScaleFactor": 1,
        "isMobile": False,
    },
}

# Run the Actor and wait for it to finish
run = client.actor("blackcatforge/screenshot-capture").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.python.org"
  ],
  "custom": {
    "width": 1280,
    "height": 800,
    "deviceScaleFactor": 1,
    "isMobile": false
  }
}' |
apify call blackcatforge/screenshot-capture --silent --output-dataset

```

## MCP server setup

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

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/3hDb4LN7ocYGnUmbs/builds/X0IQ0SiKKWmnccZeG/openapi.json
