# Website Screenshot API - Full Page PNG, JPEG & PDF (Bulk URLs) (`integriapps/website-screenshot`) Actor

Capture full-page or viewport screenshots of many URLs as PNG, JPEG or PDF, on desktop, tablet or mobile. Hides cookie banners, waits for selectors, returns public file links, HTTP status, title and size. Respects robots.txt. Flat price per screenshot. By IntegriApps.

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

## Pricing

from $6.00 / 1,000 screenshot captureds

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 PNG, JPEG & PDF (Bulk URLs)

Take **screenshots of websites in bulk**: give a list of URLs and get a **full-page or viewport capture** of each one as **PNG, JPEG or PDF**, on **desktop, tablet or mobile**. Every capture comes with a **shareable file link**, the **HTTP status**, the **page title**, the **image size in pixels** and the **file size**. Common **cookie banners are hidden** automatically. Flat price per screenshot, and you only pay for screenshots that were actually captured.

Part of [IntegriApps MicroApps](https://integriapps.com/microapps/). Support Sunday to Friday.

### What it does

- **Bulk URL to screenshot:** one PNG, JPEG or PDF per URL, captured with a real Chromium browser (JavaScript is rendered).
- **Full page or viewport:** capture the whole scrollable page (up to a height you choose, 10,000 px by default) or only the visible screen.
- **Desktop, tablet or mobile:** desktop 1366×768, tablet 820×1180 (2x) or mobile 390×844 (2x, touch, mobile user agent). You can also set any viewport size.
- **Wait options:** wait for `load`, `domcontentloaded` or `networkidle`, for a CSS selector to be visible, and/or an extra delay.
- **Lazy images:** scrolls the page first so lazy-loaded images show up in full-page captures.
- **Cleaner captures:** hides common cookie/consent banners (OneTrust, Cookiebot, Usercentrics, Didomi, Quantcast and others) with CSS, plus any selectors you add (chat widgets, pop-ups) and your own custom CSS. It never clicks "accept".
- **PDF export:** A4, Letter, Legal or A3, with backgrounds.
- **Polite and safe by design:** respects **robots.txt**, uses no proxies and **does not bypass logins, paywalls, CAPTCHAs or anti-bot protections**.

### Use cases

- **Visual QA and monitoring:** capture your pages on desktop and mobile after each deploy.
- **SEO and marketing reports:** thumbnails and full-page captures of landing pages and competitors' public pages.
- **Archiving and compliance:** keep a dated PNG/PDF copy of what a public page showed.
- **AI agents and automations:** give an agent, Make, Zapier or n8n flow a tool that turns a URL into an image link.

### Not supported

To respect their terms, this Actor **does not open** LinkedIn, Instagram, Facebook/Messenger/Threads, TikTok, X/Twitter, Google (Search, Maps and other Google domains) or Amazon (any country). Those URLs, and links that redirect to them, are returned as `blocked_domain` and are **not charged**. Local or private network addresses (localhost, 10.x, 192.168.x…) are refused.

### Input

| Field | Description | Default |
|---|---|---|
| `urls` | Pages to capture | — (empty = free demo with example.com) |
| `format` | `png`, `jpeg` or `pdf` | `png` |
| `device` | `desktop`, `tablet` or `mobile` | `desktop` |
| `fullPage` | Whole page (PNG/JPEG) instead of only the viewport | true |
| `viewportWidth` / `viewportHeight` | Override the device viewport (px) | device size |
| `maxFullPageHeight` | Cut very long pages at this height (CSS px, 500–20,000) | 10,000 |
| `jpegQuality` | JPEG quality 1–100 | 80 |
| `pdfFormat` | `A4`, `Letter`, `Legal`, `A3` | `A4` |
| `waitUntil` | `load`, `domcontentloaded` or `networkidle` | `load` |
| `waitForSelector` | CSS selector that must be visible before capturing | — |
| `delayMs` | Extra wait before capturing (0–30,000 ms) | 0 |
| `scrollToLoadLazyContent` | Scroll first to load lazy images | true |
| `hideCookieBanners` | Hide common cookie banners with CSS | true |
| `hideSelectors` / `customCss` | Extra selectors to hide / CSS to inject | — |
| `navigationTimeoutSecs` | Page load timeout (5–120 s) | 30 |
| `maxRetries` | Retries for timeouts, network errors, 429 and 5xx | 2 |
| `maxConcurrency` | Pages captured in parallel (1–10) | 3 |

Example — mobile, full-page JPEG, waiting for the main content:

```json
{
  "urls": [{ "url": "https://www.python.org/" }, { "url": "https://www.gov.uk/" }],
  "format": "jpeg",
  "device": "mobile",
  "fullPage": true,
  "waitForSelector": "main",
  "hideSelectors": ".chat-widget"
}
```

### Output

Files are saved in the run's **key-value store**. The **dataset** has one item per URL (real output, shortened):

```json
{
  "url": "https://www.python.org/",
  "finalUrl": "https://www.python.org/",
  "status": "ok",
  "httpStatus": 200,
  "title": "Welcome to Python.org",
  "format": "png",
  "device": "desktop",
  "screenshotUrl": "https://api.apify.com/v2/key-value-stores/dFuFp6fRJHdeOcvid/records/python-org-1ab11d99.png?signature=…",
  "key": "python-org-1ab11d99.png",
  "contentType": "image/png",
  "width": 1366,
  "height": 2584,
  "pdfPages": null,
  "fileSizeBytes": 464500,
  "fullPage": true,
  "truncatedAtHeight": null,
  "viewport": { "width": 1366, "height": 768 },
  "capturedAt": "2026-11-01T17:51:13.942Z"
}
```

- `width` / `height` are the real image pixels (mobile and tablet use a 2x pixel ratio, so a 390 px wide phone gives a 780 px wide image).
- `truncatedAtHeight` is set when the page was longer than `maxFullPageHeight` and was cut.
- `status` is one of `ok`, `blocked_domain`, `blocked_by_robots_txt`, `http_error` (4xx/5xx), `invalid_url` or `error` (timeout, network error). **Only `ok` is charged.**
- `screenshotUrl` is a signed link that opens the file directly (no token needed), so you can share it or use it in other tools. It stays available for as long as your Apify plan keeps run data (data retention).
- The key-value store also has `RUN_SUMMARY` with counts per status.

### Pricing

**Pay per event: USD 0.006 per screenshot captured** (USD 6 per 1,000), the same for PNG, JPEG and PDF, desktop or mobile. Blocked domains, URLs disallowed by robots.txt, invalid URLs, HTTP errors and failed pages are **free**. You can cap spending with the run's maximum charge setting; the Actor stops cleanly when the limit is reached. Platform usage (browser time) is included in the price; Apify also applies its standard tiny Actor start fee (USD 0.00005 per GB of memory, i.e. USD 0.0001 per run at the default 2 GB).

### Use it from your code

Synchronous call that returns the dataset items (with the screenshot links) in the response:

```bash
curl -X POST "https://api.apify.com/v2/acts/integriapps~website-screenshot/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"urls":[{"url":"https://example.com/"}],"format":"png","fullPage":false}'
```

It also works from the Apify API clients (JavaScript/Python), Make, Zapier, n8n and the Apify MCP server for AI agents.

### FAQ

**Does it render JavaScript?** Yes. Pages are opened in Chromium and captured after they load. For heavy single-page apps use `waitUntil: "networkidle"` or `waitForSelector`.

**Why does a cookie banner still show?** Only common consent tools are hidden, and only with CSS. Add the banner's selector to `hideSelectors`. The Actor never accepts or rejects cookies for you.

**Can it capture pages behind a login, a paywall or a CAPTCHA?** No. It does not log in, solve CAPTCHAs or bypass anti-bot protection, and it uses no proxies. Pages that block automated browsers usually return `http_error` (for example 403) and are not charged.

**Why was a URL skipped?** Check `status` and `error`. `blocked_by_robots_txt` means the site's robots.txt does not allow it (or robots.txt could not be read, in which case we stay on the safe side). `blocked_domain` means the site is in the not-supported list above.

**The full-page image is cut. Why?** Pages longer than `maxFullPageHeight` (10,000 CSS px by default, up to 20,000) are cut to keep files usable; `truncatedAtHeight` tells you when this happened.

**How long are files kept?** They live in the run's default key-value store, which follows your Apify plan's data retention. Download them or copy them to your own storage if you need them longer.

**Is it legal to use?** You are responsible for having the right to capture and use the pages (your own sites, public pages whose terms allow it). The Actor respects robots.txt but does not read each site's terms of service for you.

### Changelog

See [CHANGELOG.md](./CHANGELOG.md).

Part of [IntegriApps MicroApps](https://integriapps.com/microapps/) — small tools by IntegriApps, a SaaS for SMBs. Support Sunday to Friday.

# Changelog

This Actor's version history is a separate document: https://apify.com/integriapps/website-screenshot/changelog.md

# Actor input Schema

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

Web pages to capture (one screenshot per URL). If empty, https://example.com/ is captured for free as a demo. LinkedIn, Instagram, Facebook, TikTok, X/Twitter, Google (Search/Maps) and Amazon are not supported.

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

PNG (lossless), JPEG (smaller files) or PDF (printable document).

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

Desktop (1366×768), tablet (820×1180, 2x) or mobile (390×844, 2x, touch, mobile user agent).

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

Capture the whole scrollable page instead of only the visible viewport (PNG/JPEG).

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

Optional. Overrides the device width (240–3840).

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

Optional. Overrides the device height (240–4320).

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

Very long pages are cut at this height (CSS pixels) to keep files usable. 500–20,000.

## `jpegQuality` (type: `integer`):

Only for JPEG (1–100).

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

Only for PDF.

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

When the page is considered loaded: 'load' (default), 'domcontentloaded' (faster) or 'networkidle' (waits up to 15 s for network to be quiet; best for heavy JavaScript pages).

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

Optional. Wait until this element is visible before capturing, e.g. #main-chart

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

Optional extra wait before capturing (0–30,000 ms), e.g. for animations.

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

For full-page and PDF captures, scroll down the page first so lazy-loaded images appear.

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

Hide common cookie/consent banners with CSS (OneTrust, Cookiebot, Usercentrics, Didomi, Quantcast and others). Nothing is clicked or accepted; unknown banners may still show.

## `hideSelectors` (type: `string`):

Optional comma-separated CSS selectors to hide, e.g. .chat-widget, #newsletter-popup

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

Optional CSS injected before capturing.

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

Maximum time to load each page (5–120 s).

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

Retries for timeouts, network errors, HTTP 429 and 5xx (0–5).

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

Pages captured in parallel (1–10). Higher values need more memory.

## Actor input object example

```json
{
  "urls": [
    {
      "url": "https://apify.com/"
    },
    {
      "url": "https://crawlee.dev/"
    }
  ],
  "format": "png",
  "device": "desktop",
  "fullPage": true,
  "maxFullPageHeight": 10000,
  "jpegQuality": 80,
  "pdfFormat": "A4",
  "waitUntil": "load",
  "delayMs": 0,
  "scrollToLoadLazyContent": true,
  "hideCookieBanners": true,
  "navigationTimeoutSecs": 30,
  "maxRetries": 2,
  "maxConcurrency": 3
}
```

# Actor output Schema

## `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": [
        {
            "url": "https://apify.com/"
        },
        {
            "url": "https://crawlee.dev/"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("integriapps/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": [
        { "url": "https://apify.com/" },
        { "url": "https://crawlee.dev/" },
    ] }

# Run the Actor and wait for it to finish
run = client.actor("integriapps/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": [
    {
      "url": "https://apify.com/"
    },
    {
      "url": "https://crawlee.dev/"
    }
  ]
}' |
apify call integriapps/website-screenshot --silent --output-dataset

```

## MCP server setup

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