# Website Screenshot API: Full Page, PDF & Mobile (`parth-tools/website-screenshot-api`) Actor

Capture any URL as PNG, JPEG, WebP or PDF: viewport, full page or one element. Desktop, laptop, tablet, iPhone & Android presets, dark mode, cookie banner & ad hiding. Pay only per successful screenshot.

- **URL**: https://apify.com/parth-tools/website-screenshot-api.md
- **Developed by:** [Parth](https://apify.com/parth-tools) (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

from $1.50 / 1,000 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, PDF & Mobile

**Turn any list of URLs into clean website screenshots or PDFs, ready to share or feed into your pipelines.** Choose PNG, JPEG, WebP or PDF, and capture the visible viewport, the full scrollable page, or a single element by CSS selector. Presets cover desktop, laptop, tablet, iPhone and Android, and you can also set a custom size, retina density or dark mode. Cookie banners are hidden automatically, and ads and trackers can be blocked too.

Every capture is saved as a file with a direct download link, and gets one dataset row with the final URL, HTTP status, page title, pixel size and file size. **You pay a flat price per successful screenshot.** Failed, timed-out or blocked pages produce a free error row.

### What can it do?

- 📸 **4 formats**: PNG (lossless), JPEG and WebP (with a quality setting), and PDF (A4, Letter, Legal, A3 or Tabloid; portrait or landscape)
- 🖥️ **3 capture modes**: *viewport* (above the fold), *full page* (the whole scrollable page, with lazy images loaded first) and *element* (just `#pricing`, `header`, `.product-card` and so on)
- 📱 **Device presets**: Desktop 1920×1080, Laptop 1440×900, Tablet (iPad), iPhone 15 and Android (Pixel 7), each with the right user agent, touch and mobile emulation. Custom width and height and retina 2×/3× are also available.
- 🌙 **Dark mode** via `prefers-color-scheme: dark`
- 🍪 **No cookie banners**: 35+ consent tools (OneTrust, Cookiebot, Usercentrics, Quantcast, Didomi, TrustArc, Sourcepoint, CookieYes, Osano and more) are hidden and page scrolling is unlocked. You can add your own selectors to hide chat widgets, pop-ups or sticky headers.
- 🚫 **Ad and tracker blocking** (on by default, can be turned off): about 100 ad and analytics networks are blocked, so ad-heavy pages load up to 5× faster and look cleaner
- ⏱️ **Wait control**: wait for `load`, `networkidle` (good for SPAs and dashboards) or `domcontentloaded`, plus an extra delay for animations and charts
- ⚡ **Fast and cheap**: one shared Chromium browser captures several pages in parallel. Slow third-party scripts can't stall a capture, and no proxy is used by default.
- 🧾 **Fair billing**: you are charged only when a file is saved. Errors, HTTP 4xx/5xx responses and bot-protection pages are free.

### Input example

```json
{
    "urls": [
        "https://apify.com",
        "https://en.wikipedia.org/wiki/Web_scraping",
        "https://news.ycombinator.com"
    ],
    "format": "png",
    "mode": "fullPage",
    "device": "desktop",
    "darkMode": false,
    "hideCookieBanners": true,
    "hideSelectors": ["#intercom-container"],
    "blockAdsAndTrackers": true,
    "waitUntil": "load",
    "delayMs": 500,
    "timeoutSecs": 30
}
```

| Field | What it does |
|---|---|
| `urls` | Pages to capture, one per line (`https://` is added if missing) |
| `format` | `png`, `jpeg`, `webp`, `pdf` |
| `mode` | `viewport`, `fullPage`, `element` |
| `selector` | CSS selector for `element` mode |
| `device` | `desktop`, `laptop`, `tablet`, `iphone`, `android`, `custom` |
| `viewportWidth` / `viewportHeight` | Override the preset size (`0` = preset) |
| `deviceScaleFactor` | `1`–`3` for retina output (`0` = preset) |
| `darkMode` | Emulate dark color scheme |
| `hideCookieBanners` | Hide consent pop-ups (default **on**) |
| `hideSelectors` | Extra CSS selectors to hide |
| `blockAdsAndTrackers` | Block ad and analytics requests (default **on**; turn off to capture ads) |
| `waitUntil` | `load`, `networkidle`, `domcontentloaded` |
| `delayMs` | Extra wait before capture |
| `quality` | JPEG/WebP quality 1–100 |
| `maxFullPageHeight` | Cut infinite feeds at N CSS px (default 15,000) |
| `pdfPageFormat` / `pdfLandscape` / `pdfMedia` | PDF paper, orientation, screen or print CSS |
| `timeoutSecs` | Page load timeout |
| `maxConcurrency` | Pages captured in parallel (`0` = auto, 1 per GB of memory) |
| `proxyConfiguration` | Optional Apify Proxy or your own proxies (off by default) |

### Output example

Each capture is stored in the run's **key-value store**, for example as `0001-apify.com.png`. You also get one dataset row per URL:

```json
{
    "inputUrl": "https://apify.com",
    "url": "https://apify.com/",
    "finalUrl": "https://apify.com/",
    "statusCode": 200,
    "title": "Apify: Full-stack web scraping and data extraction platform",
    "format": "png",
    "mode": "fullPage",
    "device": "desktop",
    "width": 1920,
    "height": 9876,
    "viewportWidth": 1920,
    "viewportHeight": 1080,
    "deviceScaleFactor": 1,
    "darkMode": false,
    "pdfPages": null,
    "truncated": false,
    "fileSizeBytes": 2154312,
    "contentType": "image/png",
    "key": "0001-apify.com.png",
    "fileUrl": "https://api.apify.com/v2/key-value-stores/aBcD1234/records/0001-apify.com.png",
    "loadTimeMs": 3120,
    "notes": null,
    "success": true,
    "error": null,
    "errorType": null,
    "capturedAt": "2026-10-21T08:00:00.000Z"
}
```

A failed URL gives a row with `"success": false`, an `error` message and an `errorType` (`invalid_url`, `dns`, `timeout`, `navigation_failed`, `http_error`, `blocked`, `selector_not_found`, `capture_failed`). **These rows are never charged.**

The dataset has three views: **Screenshots** (with image previews), **File links** and **Errors**. You can export to JSON, CSV or Excel, or use `fileUrl` to download each file directly.

### Pricing

Pricing is **pay per event**, a flat price per successful capture:

| Event | Price | Per 1,000 |
|---|---|---|
| Viewport or element screenshot (PNG/JPEG/WebP, any device) | **$0.0015** | $1.50 |
| Full-page screenshot or PDF | **$0.003** | $3.00 |
| Actor start (Apify's default start fee, once per run per GB of memory) | $0.00005 | $0.05 per 1,000 runs |

Failed, blocked and HTTP-error pages cost nothing. Set **Max cost per run** and the Actor stops cleanly once that budget is reached.

#### How this compares to Apify's Website Screenshot Generator (`apify/screenshot-url`)

| | **This Actor** | apify/screenshot-url |
|---|---|---|
| Billing | Flat price per successful capture | Platform compute (2 GB default memory) **plus** Apify Proxy traffic |
| Cost predictability | Known before you run | Depends on page weight, memory and run time |
| Proxy | Off by default (optional) | Apify Proxy on by default |
| Formats | PNG, JPEG, WebP, PDF | PNG, PDF |
| Capture modes | Viewport, full page, single element | Viewport or scroll to bottom |
| Device presets, retina, dark mode | ✅ Desktop, laptop, tablet, iPhone, Android | Viewport width only |
| Cookie banner hiding | ✅ Built-in list + your selectors | Your own selectors only |
| Ad and tracker blocking | ✅ On by default (can be turned off) | ❌ |
| Failed pages | Free error row | Compute is still billed |

`apify/screenshot-url` is a great open-source **example Actor**. This Actor is a production screenshot API with predictable per-capture pricing.

### Use cases

- **SEO and agency reports**: capture client homepages, landing pages and SERP-ranked pages on desktop and mobile for monthly reports and audits
- **Competitor monitoring**: schedule daily full-page captures of competitors' pricing, home and feature pages to keep a visual history of every change
- **QA and visual regression**: screenshot staging and production on every device preset after a deploy, then diff them in your CI
- **Archiving and compliance**: keep timestamped PNG/PDF evidence of web pages, ads, terms and disclosures
- **AI agents and LLM vision**: give agents (via the Apify MCP server or API) a screenshot tool to "look" at pages, or feed captures into GPT-4o, Claude or Gemini vision for analysis
- **No-code automation**: connect to **Zapier, Make or n8n**. Send new URLs from a Google Sheet, Airtable or CRM, then post the resulting `fileUrl` to Slack, Notion, Google Drive or email
- **Social and link previews**: generate thumbnails and OG-style previews for directories, newsletters and link pages

### How to use it via API

```bash
curl -X POST "https://api.apify.com/v2/acts/<ACTOR_ID>/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"urls":["https://example.com"],"format":"png","mode":"fullPage"}'
```

The response contains the dataset rows. Each row's `fileUrl` points to the image or PDF. JavaScript and Python clients, schedules and webhooks all work the same way.

### FAQ

**Does it bypass Cloudflare, CAPTCHAs or logins?**
No. It captures public pages as a normal browser sees them. Pages that show a bot-protection challenge, or return HTTP 4xx/5xx, produce a free `blocked` or `http_error` row instead of a screenshot of the challenge page.

**Do I need a proxy?**
Usually not, and none is used by default. To see a country-specific version of a page, enable Apify Proxy (billed to your account as normal proxy usage) or add your own proxy URLs.

**Why is a cookie banner or pop-up still visible?**
Some sites use custom consent dialogs. Add their CSS selector to **Extra elements to hide** and they will be removed. Banners are hidden with CSS and never accepted for you.

**Which memory should I use?**
Keep the default **2048 MB**. 1024 MB works for simple viewport screenshots, but heavy news and SPA pages, and tall full-page captures, can crash the browser at 1 GB. Crashes give a free `out_of_memory` error row. The per-screenshot price is the same at any memory. Only the small Actor start fee scales with memory.

**Very long pages?**
Full-page captures are cut at `maxFullPageHeight` (15,000 CSS px by default) to avoid giant files from infinite feeds. Set it to `0` for no limit. To keep captures reliable, one image is also limited to about 36 megapixels. That is roughly 18,000 px tall at 1920 px wide, or about 10,000 CSS px on an iPhone at 3×. WebP is always limited to 16,383 px per side by the format. The `truncated` field and `notes` show when a cut happened.

**Are the file links public?**
`fileUrl` is the Apify key-value store record URL and works without an API token. If you restrict general resource access in your Apify account settings, the link carries a signature so it still opens. Files follow your plan's data retention.

**How many URLs per run?**
As many as you like. Pages are captured in parallel in one shared browser, one per GB of memory by default (2 at the default 2048 MB). For big batches, raise memory to 4–8 GB and parallelism goes up automatically.

### Legal note

Only capture pages you are allowed to access, and respect the website's terms, copyright and trademarks when you store or republish screenshots. Screenshots can contain personal data. If they do, you are responsible for handling it lawfully (for example under GDPR or CCPA). This Actor does not log in, solve CAPTCHAs or bypass access controls, and it refuses private and internal network addresses. This is not legal advice.

### Support

Found a page that renders incorrectly, or want another device, format or option? Open an issue on the Actor's **Issues** tab with the URL and your input.

# Actor input Schema

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

One web page per line. <code>https://</code> is added when missing (e.g. <code>example.com</code>). Each URL becomes one file in the run's key-value store and one row in the dataset. URLs that fail, time out or are blocked produce a free error row.

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

<b>PNG</b> – lossless, best for UI and text. <b>JPEG</b> – smaller files for photos (see <i>Quality</i>). <b>WebP</b> – smallest files, modern browsers (max 16,383 px per side). <b>PDF</b> – printable document of the whole page (always billed as a full-page capture).

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

<b>Viewport</b> – what is visible on screen (e.g. 1920×1080 above the fold). <b>Full page</b> – the whole scrollable page, top to bottom (lazy-loaded images are triggered by scrolling first). <b>Element</b> – only the first element matching the <i>CSS selector</i> below. Ignored for PDF.

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

Used only in <i>Element</i> mode: the first visible element matching this selector is captured, e.g. <code>header</code>, <code>#pricing</code>, <code>.product-card</code>, <code>main article</code>. If nothing matches within 10 s, you get a free error row.

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

Screen size, pixel density, user agent and touch/mobile emulation.<ul><li><b>Desktop</b> 1920×1080</li><li><b>Laptop</b> 1440×900</li><li><b>Tablet</b> iPad 810×1080 @2x</li><li><b>iPhone</b> iPhone 15, 393×659 @3x</li><li><b>Android</b> Pixel 7, 412×839 @2.6x</li><li><b>Custom</b> 1280×800 unless you set width/height below</li></ul>

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

Overrides the device's viewport width. <code>0</code> = use the device preset. Max 7680.

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

Overrides the device's viewport height (the visible area; full-page captures still grow to the page's height). <code>0</code> = use the device preset. Max 4320.

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

Device pixel ratio: <code>2</code> gives a sharp retina image twice the width/height in pixels. <code>0</code> = device preset (desktop/laptop 1, tablet 2, iPhone 3, Android 2.625). Max 3.

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

Emulate <code>prefers-color-scheme: dark</code>. Sites that support a dark theme render it; others look unchanged.

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

Hide consent pop-ups from 35+ common consent tools (OneTrust, Cookiebot, Usercentrics, Quantcast, Didomi, TrustArc, Sourcepoint, Iubenda, CookieYes, Osano, HubSpot…) and generic cookie bars, and unlock page scrolling. Banners are hidden with CSS, never accepted or declined.

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

Your own CSS selectors to hide before capturing, one per line, e.g. a chat widget <code>#intercom-container</code>, a newsletter modal <code>.newsletter-popup</code>, or a sticky header <code>header.sticky</code>.

## `blockAdsAndTrackers` (type: `boolean`):

Block requests to ~100 ad, analytics and tracking networks (Google Ads/Analytics/Tag Manager, Meta pixel, Taboola, Outbrain, Criteo, Hotjar…) and hide common ad slots. On by default: ad-heavy pages load up to 5× faster and look cleaner. Turn off if you need to capture the ads themselves (ad verification, compliance archives) or if a site breaks without its scripts.

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

When the page counts as loaded. <b>load</b>: the window load event, waited for up to 15 s after the HTML arrives (good default). <b>networkidle</b>: also wait until there have been no network requests for 0.5 s (best for single-page apps and dashboards; capped at 15 s and never fails the capture). <b>domcontentloaded</b>: the HTML is parsed (fastest).

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

Wait this many milliseconds after the page loaded, e.g. for animations, carousels or charts. Max 60,000.

## `scrollToLoadLazyContent` (type: `boolean`):

In full-page mode, scroll through the page first so lazy-loaded images and sections render, then scroll back to the top.

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

Maximum time for the page's HTML to arrive. After that, the Actor waits up to 15 s more for the <code>load</code> event (slow ad or analytics scripts can't hold the capture up) and then captures the page as rendered. If the HTML never arrives, you get a free error row.

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

Compression quality for JPEG and WebP (1–100). Lower = smaller files. Ignored for PNG and PDF.

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

Cut extremely long pages (infinite feeds) at this height in CSS pixels. <code>0</code> = no limit. Each image is also capped at ~36 megapixels for reliability (≈18,000 px tall at 1920 px wide, ≈10,000 CSS px on iPhone 3×), and WebP at 16,383 px per side. The output's <code>truncated</code> field tells you when this happened.

## `pdfPageFormat` (type: `string`):

Paper size for PDF output.

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

Landscape orientation for PDF output.

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

<b>screen</b> – the PDF looks like the website on screen (default). <b>print</b> – use the site's print stylesheet (often hides navigation and ads).

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

How many pages are captured at the same time in one shared browser. <code>0</code> = automatic: one per GB of run memory (2 at the default 2048 MB). Higher values on low memory make heavy pages time out or crash; raise memory together with this setting. Max 8.

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

No proxy is used by default. Turn on Apify Proxy (billed to your account as proxy usage) or add your own proxy URLs to capture geo-specific versions of pages. A proxy does not bypass bot protection or CAPTCHAs.

## Actor input object example

```json
{
  "urls": [
    "https://apify.com",
    "https://en.wikipedia.org/wiki/Web_scraping",
    "https://news.ycombinator.com"
  ],
  "format": "png",
  "mode": "viewport",
  "device": "desktop",
  "viewportWidth": 0,
  "viewportHeight": 0,
  "deviceScaleFactor": 0,
  "darkMode": false,
  "hideCookieBanners": true,
  "blockAdsAndTrackers": true,
  "waitUntil": "load",
  "delayMs": 0,
  "scrollToLoadLazyContent": true,
  "timeoutSecs": 30,
  "quality": 80,
  "maxFullPageHeight": 15000,
  "pdfPageFormat": "A4",
  "pdfLandscape": false,
  "pdfMedia": "screen",
  "maxConcurrency": 0,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `screenshots` (type: `string`):

No description

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

No description

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

No description

## `summary` (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://en.wikipedia.org/wiki/Web_scraping",
        "https://news.ycombinator.com"
    ]
};

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

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

```

## MCP server setup

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