# Website Screenshot & PDF API – Full Page, Mobile & Batch (`openharvest/website-screenshot-api`) Actor

Website screenshot API: capture full-page or element screenshots (PNG, JPEG, WebP) and PDFs of any URL or raw HTML. Desktop, tablet and mobile presets, cookie-banner hiding, dark mode, lazy-load scrolling and batch URLs. Each row has a direct file URL.

- **URL**: https://apify.com/openharvest/website-screenshot-api.md
- **Developed by:** [Enes Bulanık](https://apify.com/openharvest) (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 $2.00 / 1,000 screenshot (viewport or element)s

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 API – Full Page, Mobile & Batch

Website screenshot API for any public URL or raw HTML: viewport, full-page or single-element screenshots (PNG, JPEG, WebP) and PDFs, with desktop/tablet/mobile presets, cookie banners hidden, dark mode and batch URLs. **Use this instead of a general web crawler when you (or your AI agent) need a picture or PDF of a page – every result row has a direct file URL you can open, embed or download.**

**Price: $2 per 1,000 screenshots, $4 per 1,000 full-page screenshots or PDFs.** Pages that fail are free.

### What does Website Screenshot & PDF API do?

It opens each page in a real Chromium browser, waits until it has loaded, cleans it up and saves a file to the run's key-value store:

- **Viewport screenshots** – what a visitor sees on the first screen
- **Full-page screenshots** – the whole scrollable page; lazy-loaded images are scrolled into view first
- **Element screenshots** – only the part that matches a CSS selector (`header`, `#pricing`, `.chart`)
- **PDF** – A4, Letter, Legal, A3, A5 or Tabloid, portrait or landscape, print or screen style
- **Cookie banners hidden** – OneTrust, Cookiebot, Usercentrics, Didomi, Quantcast, Sourcepoint, TrustArc, CookieYes, Complianz and other common consent tools, plus a heuristic for custom banners. Nothing is clicked or accepted.
- **Optional clean-up** – hide newsletter pop-ups, modals and chat widgets, or any element by CSS selector
- **Devices** – desktop 1440×900, desktop Full HD 1920×1080, laptop 1366×768, iPad, iPhone and Android presets, or any custom size; retina scale 1–3×
- **Dark mode** – for sites that support `prefers-color-scheme: dark`
- **Raw HTML input** – render your own HTML (invoices, reports, social cards) to an image or PDF
- **Ads and trackers blocked** by default – faster pages, smaller cost
- **Batch** – hundreds of URLs in one run, captured in parallel

Each dataset row contains the file URL, width and height (or PDF page count), file size, final URL after redirects, HTTP status and page title.

### Use cases

- **AI agents and LLM tools** – let an agent "look" at a page: pass the `fileUrl` to a vision model.
- **SEO and marketing reports** – full-page and mobile screenshots of your pages and competitors' pages.
- **Website monitoring and QA** – scheduled screenshots to spot broken layouts, visual changes or defacement.
- **Archiving and compliance** – keep a dated PDF or image of a page (terms, prices, ads, claims).
- **Link previews and thumbnails** – small JPEG/WebP previews for directories, newsletters and dashboards.
- **Lead and market research** – capture landing pages or pricing pages for a list of companies.
- **Documents from HTML** – turn generated HTML (invoices, certificates, reports) into PDF or PNG.

### How to take website screenshots

1. Click **Try for free** / **Start**.
2. Paste one or more URLs into **Page URLs** (`example.com` without https:// works too).
3. Choose the **Output format**, turn on **Full page** if you want the whole page, and pick a **Device**.
4. Click **Start**. Open the **Overview** tab of the results to preview the images, or download the files from the links.

### Input

| Field | Type | Description |
|---|---|---|
| `urls` | array of strings | Pages to capture. Default: `https://apify.com`. |
| `format` | `png` | `jpeg` | `webp` | `pdf` | Output file type. Default `png`. |
| `fullPage` | boolean | Capture the whole scrollable page. Default `false`. |
| `device` | `desktop` | `desktop-hd` | `laptop` | `tablet` | `mobile` | `android` | Screen size and browser type. Default `desktop`. |
| `hideCookieBanners` | boolean | Hide cookie-consent banners. Default `true`. |
| `selector` | string | Capture only the first visible element matching this CSS selector. |
| `html` | string | Raw HTML to render (in addition to or instead of URLs). |
| `darkMode` | boolean | Request the dark color scheme. Default `false`. |
| `quality` | integer | JPEG/WebP quality 1–100. Default `80`. |
| `viewportWidth` / `viewportHeight` | integer | Custom browser size in CSS pixels (0 = device preset). |
| `scaleFactor` | number | Pixel ratio 0.5–3 (2 = retina). Default `1`. |
| `maxHeight` | integer | Full-page captures are cut at this height. Default `10000` (max 30,000; WebP 16,000). |
| `hideOverlays` | boolean | Also hide pop-ups, modals and chat widgets. Default `false`. |
| `hideSelectors` | array | Extra CSS selectors to hide. |
| `pdfFormat`, `pdfLandscape`, `pdfMedia` | | PDF paper size, orientation and `print`/`screen` style. |
| `waitUntil` | `load` | `networkidle` | `domcontentloaded` | When the page counts as loaded. Default `load`. |
| `delayMs` | integer | Extra wait before capturing (animations, charts). |
| `scrollToBottom` | boolean | Scroll to load lazy images before full-page/element/PDF capture. Default `true`. |
| `blockAds`, `blockMedia` | boolean | Skip ads/trackers and video/audio downloads. Default `true`. |
| `captureErrorPages` | boolean | Also capture (and pay for) HTTP 4xx/5xx pages. Default `false`. |
| `navigationTimeoutSecs` | integer | Page load timeout. Default `45`. Every page is tried up to 3 times. |
| `maxConcurrency` | integer | Pages captured in parallel (default: 1 per GB of memory). |
| `proxyConfiguration` | object | Apify datacenter proxy by default; choose RESIDENTIAL for sites that block datacenters. |

Example input:

```json
{
    "urls": ["https://apify.com", "https://en.wikipedia.org/wiki/Screenshot"],
    "format": "jpeg",
    "fullPage": true,
    "device": "mobile",
    "quality": 75
}
```

### Output

Each dataset item has a `type`: `screenshot`, `pdf` or `error`. Real sample output:

**Screenshot**

```json
{
    "type": "screenshot",
    "url": "https://apify.com/",
    "finalUrl": "https://apify.com/",
    "httpStatus": 200,
    "pageTitle": "Apify: Marketplace of ready-to-run tools for AI",
    "fileUrl": "https://api.apify.com/v2/key-value-stores/oznTxr4VYInROr8PZ/records/0001-apify-com-882791f5.jpg?signature=eka0p71TYznQ7ki6oIba",
    "key": "0001-apify-com-882791f5.jpg",
    "format": "jpeg",
    "contentType": "image/jpeg",
    "fileSizeBytes": 321294,
    "width": 390,
    "height": 10000,
    "pdfPages": null,
    "fullPage": true,
    "truncated": true,
    "selector": null,
    "device": "mobile",
    "viewportWidth": 390,
    "viewportHeight": 844,
    "darkMode": false,
    "hiddenElements": 0,
    "loadTimeMs": 24189,
    "capturedAt": "2026-10-08T19:07:25.600Z"
}
```

**PDF** (shortened)

```json
{
    "type": "pdf",
    "url": "https://en.wikipedia.org/wiki/Screenshot",
    "pageTitle": "Screenshot - Wikipedia",
    "fileUrl": "https://api.apify.com/v2/key-value-stores/.../records/0001-en-wikipedia-org-d345471b.pdf?signature=...",
    "contentType": "application/pdf",
    "fileSizeBytes": 209316,
    "pdfPages": 4
}
```

**Error (free)**

```json
{
    "type": "error",
    "url": "https://example.com/",
    "finalUrl": "https://example.com/",
    "httpStatus": 200,
    "errorCode": "SELECTOR_NOT_FOUND",
    "error": "No visible element matches the CSS selector \"#doesnotexist\" on this page. You were not charged."
}
```

Possible `errorCode` values: `INVALID_URL`, `DNS_NOT_FOUND`, `SSL_ERROR`, `TIMEOUT`, `PROXY_ERROR`, `NOT_A_PAGE` (the URL is a download, not a page), `NAVIGATION_FAILED`, `PRIVATE_ADDRESS` (local or private network addresses are refused), `HTTP_ERROR` (page answered 4xx/5xx), `SELECTOR_NOT_FOUND`, `FILE_TOO_LARGE`, `CAPTURE_FAILED`.

The `fileUrl` works without an Apify token (it is a signed link to that one file) and stays valid as long as the run's storage is kept (the retention period of your Apify plan). Files are also listed in the run's **Storage → Key-value store** tab. The dataset has two views: **Overview** (with image previews) and **Files**.

### Pricing

This Actor uses **pay-per-event** pricing – you pay only for files you get. Platform usage is included.

| Event | Price | When it is charged |
|---|---|---|
| `screenshot` | **$0.002** ($2 / 1,000) | Each viewport or element screenshot (PNG, JPEG or WebP) |
| `full-page-screenshot` | **$0.004** ($4 / 1,000) | Each full-page screenshot |
| `pdf` | **$0.004** ($4 / 1,000) | Each PDF |
| Errors | **Free** | Invalid URLs, unreachable pages, HTTP 4xx/5xx pages, missing selectors |

Examples:

| Job | Cost |
|---|---|
| 100 homepage thumbnails (viewport, JPEG) | **$0.20** |
| 1,000 full-page screenshots | **$4.00** |
| 500 pages saved as PDF | **$2.00** |

Tip: set **Max cost per run** in the run options – the Actor stops cleanly when your budget is reached.

### Use with AI agents (MCP)

This Actor works as a tool in the Apify MCP server, so Claude, ChatGPT, Cursor and other MCP clients can call it. Add it to your MCP client with the server URL `https://mcp.apify.com/?tools=openharvest/website-screenshot-api`. Example tool input an agent can send:

```json
{
    "urls": ["https://example.com/pricing"],
    "fullPage": true,
    "format": "jpeg",
    "quality": 70
}
```

The agent receives one row per page; `fileUrl` is a direct link to the image or PDF that can be passed to a vision model or shown to the user. Use JPEG or WebP for smaller files when a model has to read the image.

### FAQ

**Why is a page captured with a cookie banner or pop-up?**
Most consent tools are hidden automatically. For a custom banner, add its CSS selector to **Hide these elements**, or turn on **Hide pop-ups and chat widgets**.

**Some images are missing on my full-page screenshot.**
Keep **Scroll to load lazy images** on (it scrolls the page before a full-page capture) and add an **Extra delay** of 1,000–3,000 ms for slow sites, or use `waitUntil: networkidle`.

**A site returns HTTP 403 or shows a "verify you are human" page.**
Some sites block datacenter traffic. Select the **RESIDENTIAL** proxy group (and a country) in **Proxy configuration**. Blocked pages (4xx/5xx) are free unless you turn on **Capture error pages**.

**How tall can a full-page screenshot be?**
Up to 30,000 px (WebP 16,000 px). The default cut-off is 10,000 px; rows that were cut have `truncated: true`. Very tall captures need more memory – use 4 GB or more for long pages.

**Can I capture pages behind a login?**
No. The Actor only opens public pages and does not log in to websites. Local and private network addresses (localhost, 10.x, 192.168.x, cloud metadata) are refused.

**Can I run it on a schedule or from my code?**
Yes – use Apify Schedules, the Apify API, the JavaScript/Python clients, or integrations such as Make, Zapier, n8n and webhooks.

### Is it legal to take screenshots of websites?

The Actor captures what any visitor sees on a public web page, like a browser screenshot. It does not log in, bypass paywalls or collect personal data. Screenshots can still contain copyrighted material or personal data, so make sure your use (for example storing, publishing or analysing them) complies with applicable laws such as copyright law and GDPR, and with the website's terms. If you are unsure, consult a lawyer.

### Related actors

Other actors by the same developer:

- **Website SEO Audit Crawler – Broken Links, Schema & llms.txt** – check titles, meta tags, headings and links of the pages you capture
- **Website Tech Stack Detector – Bulk CMS, Analytics & Frameworks** – see which CMS, frameworks and tools a website uses
- **Sitemap URL Extractor – All URLs from sitemap.xml & robots.txt** – get every page URL of a site to capture them in bulk
- **PDF to Markdown – DOCX, PPTX, XLSX & HTML for LLM & RAG** – turn the PDFs and pages you capture into clean Markdown text for LLMs
- **Bulk WHOIS Lookup – RDAP, DNS Records, SSL & Redirects** – add domain and certificate data to your website research

### Support & feedback

Found a bug or a site that does not render correctly? Open an issue in the **Issues** tab with the URL and your input.

# Actor input Schema

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

Web pages to capture, one per line. <code>example.com</code> without https:// also works. Duplicates are skipped. Leave empty to capture only the HTML below.

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

<code>png</code> = lossless image, <code>jpeg</code> = small photo-style image, <code>webp</code> = smallest image, <code>pdf</code> = printable PDF document (charged as a 'pdf' event).

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

Capture the whole scrollable page instead of only the first screen (viewport). Lazy-loaded images are scrolled into view first. Very long pages are cut at 'Max height'. Charged as a 'full-page-screenshot' event.

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

Screen size and browser type. <code>desktop</code> 1440×900, <code>desktop-hd</code> 1920×1080, <code>laptop</code> 1366×768, <code>tablet</code> iPad 820×1180, <code>mobile</code> iPhone 390×844, <code>android</code> Pixel 412×915 (mobile presets use a mobile user agent and touch).

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

Hide cookie-consent banners and their dark backdrops (OneTrust, Cookiebot, Usercentrics, Didomi, Quantcast, TrustArc, CookieYes, Complianz and other common consent tools). Nothing is clicked or accepted - banners are only hidden from the image.

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

Optional. Capture only the first visible element matching this CSS selector, e.g. <code>#main</code>, <code>.pricing-table</code> or <code>header</code>. If no element matches, you get a free error row.

## `html` (type: `string`):

Optional. Render this HTML document instead of (or in addition to) the URLs - useful for invoices, reports, email templates or Open Graph cards. External CSS, images and fonts referenced with absolute URLs are loaded.

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

Ask the site for its dark color scheme (prefers-color-scheme: dark). Works on sites that support dark mode.

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

Compression quality from 1 to 100 for JPEG and WebP. Lower = smaller files. Ignored for PNG and PDF.

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

Optional custom browser width in CSS pixels. 0 = use the device preset.

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

Optional custom browser height in CSS pixels (also the image height when 'Full page' is off). 0 = use the device preset.

## `scaleFactor` (type: `number`):

Device pixel ratio. 1 = normal, 2 = sharp retina image with 2× width and height (4× file size). Allowed 0.5 to 3.

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

Full-page screenshots of endless pages are cut at this height (CSS pixels). Max 30,000 (WebP max 16,000 divided by the scale factor). The row then has <code>truncated: true</code>.

## `hideOverlays` (type: `boolean`):

Also hide newsletter pop-ups, modal dialogs, full-screen overlays and chat widgets (Intercom, HubSpot, Drift, Zendesk, Crisp, Tidio…). Off by default because it may hide fixed elements you want to keep.

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

Optional. Extra CSS selectors to hide before capturing, e.g. <code>.ad-banner</code>, <code>#sticky-header</code>.

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

Paper size for PDF output.

## `pdfLandscape` (type: `boolean`):

Use landscape orientation for PDF output.

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

<code>print</code> uses the site's print stylesheet (clean, like Ctrl+P). <code>screen</code> keeps the on-screen look (menus, colors).

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

When the page counts as loaded. <code>load</code> (recommended) waits for the load event plus a short network-quiet period, <code>networkidle</code> waits longer for busy single-page apps, <code>domcontentloaded</code> is fastest. Waiting never fails the capture - slow trackers are simply ignored.

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

Extra wait after loading, before the capture - for animations, charts or slow widgets. Max 30,000.

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

Scroll through the page before a full-page, element or PDF capture so lazy-loaded images and sections appear (up to about 6 s).

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

Do not load common ad, tracking and analytics scripts (Google Ads, Criteo, Taboola, Hotjar…). Pages load faster; ad slots stay empty. Turn off if you need to see the ads.

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

Do not download video/audio streams (faster and cheaper; video posters still show).

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

By default pages that answer with HTTP 4xx/5xx (not found, blocked) produce a free error row and are not captured. Turn on to capture and pay for them anyway.

## `navigationTimeoutSecs` (type: `integer`):

Maximum time to open one page. Each page is tried up to 3 times.

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

Optional. How many pages are captured at the same time. Empty = automatic (1 per GB of memory). Full-page captures of heavy pages need about 1 GB each.

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

Apify datacenter proxy is used by default. Choose the RESIDENTIAL group (and a country) for sites that block datacenter traffic or to see a country-specific version of a page.

## Actor input object example

```json
{
  "urls": [
    "https://apify.com",
    "https://en.wikipedia.org/wiki/Screenshot"
  ],
  "format": "png",
  "fullPage": true,
  "device": "desktop",
  "hideCookieBanners": true,
  "selector": "main",
  "html": "<html><body style=\"font-family:sans-serif;padding:40px\"><h1>Invoice #1001</h1><p>Total: $49.00</p></body></html>",
  "darkMode": false,
  "quality": 80,
  "viewportWidth": 1440,
  "viewportHeight": 900,
  "scaleFactor": 1,
  "maxHeight": 10000,
  "hideOverlays": false,
  "hideSelectors": [
    ".ad-banner",
    "#promo-bar"
  ],
  "pdfFormat": "A4",
  "pdfLandscape": false,
  "pdfMedia": "print",
  "waitUntil": "load",
  "delayMs": 1000,
  "scrollToBottom": true,
  "blockAds": true,
  "blockMedia": true,
  "captureErrorPages": false,
  "navigationTimeoutSecs": 45,
  "maxConcurrency": 2,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

One row per page with the direct file URL, size, HTTP status and title (JSON, CSV, Excel and more via the dataset export).

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

All captured images/PDFs and the run summary in the default 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://apify.com"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("openharvest/website-screenshot-api").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"],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("openharvest/website-screenshot-api").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"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call openharvest/website-screenshot-api --silent --output-dataset

```

## MCP server setup

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

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/csMj2vJiJNBhCgwBQ/builds/6gaTuJNk2xyGdLtqp/openapi.json
