# Website Screenshot & PDF — Full Page, Mobile, Video (`devdeep/website-screenshot-pdf`) Actor

Screenshot any website or HTML as PNG, JPEG, WebP, PDF or scrolling MP4/GIF. Full page, element or region, 200+ devices, cookie banners hidden or accepted, sticky headers fixed. Public links, page text for AI agents. Pay only for successful captures.

- **URL**: https://apify.com/devdeep/website-screenshot-pdf.md
- **Developed by:** [Devdeep Borisagar](https://apify.com/devdeep) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 screenshot or pdfs

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 — Full Page, Mobile, Video

Capture any web page — or your own HTML — as **PNG, JPEG, WebP, PDF, or a scrolling MP4/GIF video**, and get back a **public link**. Capture the **full page**, the **first screen**, a **custom height**, **one element** or an **exact region**, on **200+ devices**. Cookie banners are hidden or clicked away, sticky headers don't repeat, lazy images load, and emoji and Asian scripts render.

**You only pay for captures that succeed.** Pages that fail, time out or return an error (401, 404, 500…) are reported, never charged. If your run hits its maximum cost, remaining pages are skipped and listed, not charged.

### Everything in one Actor

| Area | What you get |
| --- | --- |
| Input | List of URLs, a single `url`, or raw `html` |
| What to capture | Full page, first screen, custom height, one element (CSS selector), exact region (x, y, width, height) |
| Formats | PNG, JPEG, WebP, PDF, MP4 scrolling video, GIF scrolling animation |
| Image options | Quality, transparent background, retina 2x/3x, free thumbnails, max height for endless pages |
| Devices | Desktop 1920/1440, laptop, MacBook, iPad, iPhone, Android, square, social card, custom size (mobile and touch), or any of 200+ exact device models |
| Clean-up | Cookie banners: hide, click accept or click reject · block ads and trackers · sticky headers: fix or hide · hide any selector · don't load images, video or fonts · custom CSS · custom JavaScript |
| Waiting | load / domcontentloaded / networkidle / commit · wait for a selector · wait for images · extra delay · lazy-load scrolling |
| PDF | A0–A6, Letter, Legal, Tabloid, Ledger or one single long page · landscape · scale · margins · backgrounds · page ranges · screen or print styles |
| Access | Cookies · extra headers · HTTP basic auth · user agent · language · time zone · GPS location · proxy |
| For AI agents | Page text and meta description returned with the capture (free) |
| Reliability | Retries, per-page timeout, parallel pages, charge only on success, spending limit respected |

### What you get back

For each URL, one row in the dataset:

| Field | Example |
| --- | --- |
| `url` | `https://apify.com/` (or `(HTML input)`) |
| `status` | `success`, `failed` or `skipped` |
| `screenshotUrl` | Public link to the image, PDF or video |
| `thumbnailUrl` | Public link to a small JPEG preview (if requested; video poster for MP4/GIF) |
| `format`, `captureMode`, `device` | `png`, `fullPage`, `desktop` |
| `width`, `height`, `bytes` | `1920`, `6480`, `1543210` |
| `pageHeight`, `truncated` | Full page height; `true` if a very long page was cut |
| `title`, `description`, `pageText` | Page title, meta description, visible text (if requested) |
| `cookieBanner` | `accept`, `reject` or `not-found` when you asked to click the banner |
| `httpStatus`, `finalUrl`, `attempts` | HTTP status, URL after redirects, tries needed |
| `error` | Why it failed (only when `status` is `failed`) |

### Examples

Full-page WebP with a thumbnail:

```json
{ "urls": ["https://apify.com"], "format": "webp", "thumbnailWidth": 400 }
```

Pricing section only, on an iPhone, accepting cookies:

```json
{ "url": "https://example.com", "captureMode": "element", "elementSelector": "#pricing", "device": "mobile", "cookieBanners": "accept" }
```

Printable PDF in Letter landscape:

```json
{ "urls": ["https://example.com/report"], "format": "pdf", "pdfPaper": "Letter", "pdfLandscape": true, "pdfMargin": "10mm" }
```

8-second scrolling MP4 of a landing page:

```json
{ "urls": ["https://example.com"], "format": "mp4", "videoSeconds": 8 }
```

Render your own HTML (an invoice, an email, a social card):

```json
{ "html": "<h1>Invoice #42</h1>", "device": "social_card", "captureMode": "viewport" }
```

### For AI agents

Call with `url` (or `urls`) and read `screenshotUrl` from each dataset item. Use `captureMode: "viewport"` for a quick look, `"element"` with a CSS selector for one part of a page, `format: "pdf"` for selectable text, and `includePageText: true` to get the page's text in the same call. Always check `status` before using a result.

### Pricing

- **Screenshot or PDF:** charged per successful capture.
- **MP4 or GIF video:** charged per successful video.
- Failed and skipped pages are free; thumbnails and page text are included.

Only capture pages you're allowed to access, and use cookies or passwords only for accounts you own.

# Actor input Schema

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

The web pages to capture. One file per URL. Duplicates are removed; invalid addresses are reported.

## `url` (type: `string`):

Optional: one page URL (handy for API and AI-agent calls). Added to 'Page URLs'.

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

Optional: HTML to render and capture instead of (or as well as) URLs, e.g. an invoice or email template.

## `captureMode` (type: `string`):

fullPage = the whole page. viewport = the first screen only. customHeight = from the top down to 'Height to capture'. element = one element (CSS selector). region = an exact rectangle (Region).

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

PNG (sharp), JPEG or WebP (smaller), PDF (printable, selectable text), MP4 or GIF (a video scrolling down the page).

## `elementSelector` (type: `string`):

CSS selector of the element to capture when 'What to capture' is 'element', e.g. #pricing.

## `clip` (type: `object`):

Rectangle to capture when 'What to capture' is 'region', in CSS pixels from the top-left of the page: {"x":0,"y":0,"width":800,"height":600}.

## `customHeight` (type: `integer`):

For 'customHeight': capture from the top of the page down to this many pixels.

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

Very long or endless pages are cut at this height (the result says truncated: true).

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

1–100, for JPEG and WebP.

## `omitBackground` (type: `boolean`):

Make the default white background transparent (PNG and WebP; the page must not paint its own background).

## `thumbnailWidth` (type: `integer`):

Also save a small JPEG thumbnail this many pixels wide (0 = none). Free.

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

Screen to emulate. Mobile, Android and tablet also set a mobile user agent and touch.

## `devicePreset` (type: `string`):

Optional: emulate one of 200+ exact devices (overrides 'Device'), e.g. iPhone 15 Pro Max, Galaxy S9+, iPad Pro 11 landscape.

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

Viewport width for 'Custom size'.

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

Viewport height for 'Custom size'.

## `isMobile` (type: `boolean`):

For 'Custom size': behave like a phone (mobile viewport rules).

## `hasTouch` (type: `boolean`):

For 'Custom size': report a touch screen.

## `scale` (type: `string`):

'Device default' uses the device's own density (iPhone = 3x). 2x gives sharp retina images.

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

Ask the site for its dark colour scheme.

## `cookieBanners` (type: `string`):

hide = hide consent banners (fastest). accept / reject = click the banner's accept or reject button (then hide what's left). off = leave them.

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

Block requests to common ad and tracking domains.

## `stickyElements` (type: `string`):

fix = show them once at the top (no repeats in full-page shots). hide = remove them. off = leave as is.

## `selectorsToHide` (type: `array`):

CSS selectors to hide before capturing, e.g. .chat-widget.

## `blockResources` (type: `array`):

Skip loading these to go faster (images also disappear from the capture).

## `customCss` (type: `string`):

CSS injected before capturing.

## `customJs` (type: `string`):

JavaScript run in the page before capturing, e.g. to click a tab or close a pop-up.

## `loadLazyContent` (type: `boolean`):

Scroll through the page so lazy-loaded images appear, then return to the top.

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

When the page counts as loaded. networkidle is safest for heavy pages; commit is fastest.

## `waitForSelector` (type: `string`):

Optional CSS selector to wait for before capturing.

## `waitForImages` (type: `boolean`):

Wait until all images finish loading (up to 15 s).

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

Extra wait before capturing, for animations.

## `pdfPaper` (type: `string`):

Paper size, or 'Single long page' to keep the whole page on one page like a screenshot.

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

Landscape orientation.

## `pdfScale` (type: `string`):

Zoom of the page in the PDF, 0.1–2.

## `pdfMargin` (type: `string`):

Margin on every side, e.g. 0, 10mm, 0.5in, 20px.

## `pdfPrintBackground` (type: `boolean`):

Include background colours and images.

## `pdfPageRanges` (type: `string`):

Optional page ranges, e.g. 1-3, 5.

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

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

## `videoSeconds` (type: `integer`):

For MP4/GIF: seconds to scroll from top to bottom.

## `videoWidth` (type: `integer`):

Maximum video width in pixels (GIFs are capped at 800).

## `includePageText` (type: `boolean`):

Also return the page's visible text and meta description, so an AI agent can read the page as well as see it. Free.

## `maxTextChars` (type: `integer`):

Cut the returned page text at this many characters.

## `cookies` (type: `array`):

Cookies to set before loading, e.g. \[{"name":"session","value":"abc","domain":".example.com"}]. Only for accounts you own.

## `headers` (type: `object`):

Headers sent with every request, e.g. {"Accept-Language":"de-DE"}.

## `httpUsername` (type: `string`):

For pages behind basic HTTP authentication.

## `httpPassword` (type: `string`):

Password for basic HTTP authentication.

## `userAgent` (type: `string`):

Optional custom browser user agent.

## `locale` (type: `string`):

Browser language, e.g. en-US, de-DE, ja-JP.

## `timezoneId` (type: `string`):

Optional time zone, e.g. Europe/Berlin, Asia/Kolkata.

## `geolocation` (type: `object`):

Optional GPS location, e.g. {"latitude":40.71,"longitude":-74.0}.

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

Use a proxy for sites that block data-centre traffic or to load country-specific versions.

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

Give up on a page after this many seconds (retried, then reported as failed and not charged).

## `maxRetries` (type: `integer`):

Times to retry a page that fails.

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

Pages captured at the same time.

## Actor input object example

```json
{
  "urls": [
    "https://apify.com"
  ],
  "captureMode": "fullPage",
  "format": "png",
  "clip": {},
  "customHeight": 2000,
  "maxHeight": 15000,
  "quality": 80,
  "omitBackground": false,
  "thumbnailWidth": 0,
  "device": "desktop",
  "viewportWidth": 1280,
  "viewportHeight": 800,
  "isMobile": false,
  "hasTouch": false,
  "scale": "device",
  "darkMode": false,
  "cookieBanners": "hide",
  "blockAds": true,
  "stickyElements": "fix",
  "blockResources": [],
  "loadLazyContent": true,
  "waitUntil": "load",
  "waitForImages": true,
  "delayMs": 500,
  "pdfPaper": "A4",
  "pdfLandscape": false,
  "pdfScale": "1",
  "pdfMargin": "0",
  "pdfPrintBackground": true,
  "pdfMedia": "screen",
  "videoSeconds": 8,
  "videoWidth": 1280,
  "includePageText": false,
  "maxTextChars": 5000,
  "cookies": [],
  "headers": {},
  "locale": "en-US",
  "geolocation": {},
  "proxyConfiguration": {
    "useApifyProxy": false
  },
  "timeoutSecs": 45,
  "maxRetries": 2,
  "maxConcurrency": 5
}
```

# Actor output Schema

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

One row per requested page: status, public link to the screenshot, PDF or video (screenshotUrl), size, page title and error if any.

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

The captured images, PDFs, videos and thumbnails, stored 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://apify.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("devdeep/website-screenshot-pdf").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"] }

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

```

## MCP server setup

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

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/gxEiHFHcmMe5tIYtH/builds/fRJF1fgd2UPCFP26T/openapi.json
