# Website Screenshot API – Bulk Full-Page Screenshots & PDF (`gazidev/website-screenshot`) Actor

Capture full-page or viewport screenshots (PNG, JPEG, WebP) and PDFs of any list of URLs with headless Chrome. Desktop, laptop, tablet and iPhone viewports, element capture by CSS selector, cookie-banner hiding, ad blocking, dark mode, custom CSS/JS. Pay only per successful capture.

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

## Pricing

from $3.00 / 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 – Bulk Full-Page Screenshots & PDF

Take **full-page website screenshots** and **PDFs** of any list of URLs with a real headless Chrome browser. Choose a desktop, laptop, MacBook retina, tablet, iPhone, Android or OG-image viewport. Save as **PNG, JPEG or WebP**, capture a single element by CSS selector, hide cookie banners, block ads and trackers, and switch to dark mode. Paste URLs and click Start: every image gets a public link, and you pay only for screenshots that succeed.

### What it does

- **Bulk screenshots:** one URL or thousands. One shared Chromium captures several pages in parallel, with retries.
- **Full page or viewport:** scrolls through the page first so lazy-loaded images appear. Endless pages are cut at a height you choose (default 16,000 px) instead of timing out.
- **Device presets:** `desktop` 1920×1080, `laptop` 1366×768, `macbook` 1440×900 @2x, `tablet` (iPad-like) 820×1180 @2x, `mobile` (iPhone-like) 390×844 @2x with touch and a mobile user agent, `android` 412×915, `og-image` 1200×630, or `custom` width/height. The device scale factor can be overridden from 1 to 4.
- **Formats:** PNG (lossless), JPEG or WebP with a quality setting, and **PDF** (A4, Letter, Legal, A3, Tabloid, portrait or landscape, print or screen CSS). You can also get a screenshot and a PDF of the same page in one run.
- **Element screenshots:** `selector: "#pricing"` captures only that element, even if it is taller than the screen.
- **Clean captures:** cookie and consent banners (OneTrust, Cookiebot, Didomi, Quantcast, Usercentrics, TrustArc, Sourcepoint and more) are **hidden with CSS. Nothing is clicked or accepted.** About 75 ad and tracking domains are blocked, and animations are reduced.
- **Dark mode** (`prefers-color-scheme: dark`), **custom CSS** and **custom JavaScript** before capture, a custom user agent, and an option to ignore HTTPS errors.
- **No silent timeouts:** if `load`/`networkidle` never fires (endless trackers or streaming), the page is still captured as rendered and the row gets a `warning`. Real failures become free `error` rows.
- **Output:** each image or PDF is stored in the run's key-value store with a public URL. The dataset row has the URL, final URL after redirects, HTTP status, title, image URL, width/height, bytes, timing and any error.

### Use cases

- **Visual monitoring:** schedule daily screenshots of your pages or competitors' pricing pages and keep a visual history.
- **Archiving and compliance:** save PDF and PNG evidence of web pages, terms of service, ads or listings at a point in time.
- **OG images and thumbnails:** the `og-image` viewport (1200×630) or `selector` makes social preview cards and link thumbnails for directories.
- **QA and responsive testing:** capture the same URLs on desktop, tablet and mobile, in light and dark mode, after each deploy.
- **SEO and client reports:** full-page screenshots of landing pages for audits. Pairs with the [SEO Audit Crawler](https://apify.com/gazidev/seo-audit-crawler).
- **AI agents and LLM vision:** give a vision model a screenshot of the page. Pair it with [Website to Markdown](https://apify.com/gazidev/website-to-markdown) for the text.

### Input example

```json
{
  "urls": ["https://example.com", "https://en.wikipedia.org/wiki/Web_scraping", "apify.com"],
  "viewport": "mobile",
  "fullPage": true,
  "format": "webp",
  "quality": 80,
  "outputType": "both",
  "pdfFormat": "A4",
  "hideCookieBanners": true,
  "blockAds": true,
  "darkMode": false,
  "waitUntil": "load",
  "delaySecs": 0,
  "maxConcurrency": 3
}
```

Other useful options: `selector` (element only), `customCss`, `customJs` (async body, `await` allowed), `maxHeight`, `navigationTimeoutSecs`, `maxRetries`, `userAgent`, `ignoreHttpsErrors`, `proxyConfiguration` (datacenter or your own proxies), and `maxUrls`.

### Output example

```json
{
  "url": "https://en.wikipedia.org/wiki/Web_scraping",
  "finalUrl": "https://en.wikipedia.org/wiki/Web_scraping",
  "status": 200,
  "title": "Web scraping - Wikipedia",
  "screenshotUrl": "https://api.apify.com/v2/key-value-stores/<storeId>/records/00001-en-wikipedia-org-wiki-web-scraping.webp",
  "screenshotKey": "00001-en-wikipedia-org-wiki-web-scraping.webp",
  "format": "webp",
  "width": 780,
  "height": 7086,
  "bytes": 408288,
  "pdfUrl": "https://api.apify.com/v2/key-value-stores/<storeId>/records/00001-en-wikipedia-org-wiki-web-scraping.pdf",
  "pdfPages": 13,
  "pdfFormat": "A4",
  "viewport": "mobile",
  "deviceScaleFactor": 2.0,
  "fullPage": true,
  "truncated": false,
  "loadTimeMs": 1828,
  "captureTimeMs": 3506,
  "warning": null,
  "error": null
}
```

The Output tab shows a **Screenshots** table with image previews, plus **PDFs** and **Errors** views. `OUTPUT` in the key-value store holds a run summary (captured, failed, average time, whether the run stopped at the max charge). See [SAMPLE_OUTPUT.json](SAMPLE_OUTPUT.json) for full rows, including a truncated 20,000 px page and an invalid-URL error row.

### Pricing

Pay per event: **$0.003 per screenshot**, **$0.003 per PDF**, and $0.00005 per run start. That is **$3 per 1,000 screenshots**. Failed URLs, invalid input, timeouts and retries are **free**. The Actor respects your *Maximum cost per run*: it never starts a page it could not pay for, and it stops cleanly when the limit is reached.

| Actor | Price | Formats | Notes |
|---|---|---|---|
| **Website Screenshot API (this)** | **$0.003 / screenshot or PDF**, $0.00005 / start | PNG, JPEG, WebP, PDF | 7 device presets, element capture, cookie-banner hiding, ad blocking, dark mode, custom CSS/JS, partial capture instead of timeout, errors free |
| apify/screenshot-url | Free Actor, you pay platform usage | see Store page | Rated 3.9★, users report timeouts |
| moonweil/url-screenshot-api | $0.004 / item + $0.001 / start | see Store page | |

*Competitor details from the Apify Store, October 2026. Check their pages for current terms.*

### FAQ

**Does it accept cookies or click on consent popups?** No. Known consent containers and fixed boxes that mention cookies or consent are hidden with CSS only. No consent is given on your behalf. Turn `hideCookieBanners` off to capture the page exactly as a new visitor sees it.

**Why is a page cut at 16,000 px?** Endless feeds and very long pages would make huge images, and rendering them takes minutes. Images are limited to 16,383 device pixels in height (the WebP format limit, applied to all formats to keep memory bounded), so at 2x scale the cut is at about 8,190 CSS px. Lower `maxHeight` for smaller files. For the complete page as one document, use `outputType: pdf`. A cut capture has `truncated: true` and a `warning`.

**The page needs a click or a login first.** Use `customJs` (for example `document.querySelector('#tab-2').click(); await new Promise(r => setTimeout(r, 800));`). Logged-in pages are not supported.

**Some sites show "Access denied" or a captcha.** A few sites block all headless browsers or datacenter IPs. You still get the screenshot of what was served (with its `status`), which is useful for monitoring. A datacenter proxy can help in some cases. Residential proxies are not supported.

**Where are my files and how long are they kept?** In the run's default key-value store. Each row has a direct `screenshotUrl`/`pdfUrl`. Retention follows your Apify plan's storage settings. Download them or send them to S3, Google Drive or a webhook with Apify integrations.

**How fast is it?** Typical pages take about 1–3 s each, and 3 run in parallel at the default 2 GB memory. Raise `maxConcurrency` to 5–6 with 4 GB for big batches.

**Mobile screenshots look desktop-like.** `mobile`, `android` and `tablet` set the viewport, touch support and a mobile user agent, so responsive and mobile-detecting sites render their mobile layout. Rendering is done by Chromium, not real Safari.

### Use with AI agents / Apify MCP

- **Apify MCP server:** add the Actor to Claude Desktop, Cursor or VS Code via `https://mcp.apify.com?actors=gazidev/website-screenshot`. An agent can call it with `{"urls":["https://competitor.com/pricing"],"viewport":"desktop","fullPage":false}` and get back an image URL it can look at.
- **API (synchronous):** `POST https://api.apify.com/v2/acts/gazidev~website-screenshot/run-sync-get-dataset-items?token=...` with the input JSON returns the rows, including `screenshotUrl`, in one call.
- **Scheduled visual monitoring:** create a Task with your URLs, schedule it daily, and send the dataset to Slack, Google Drive or a webhook.

### More from the website toolkit

- [SEO Audit Crawler](https://apify.com/gazidev/seo-audit-crawler): broken links, meta tags, redirects and on-page SEO issues across a whole site.
- [Website to Markdown](https://apify.com/gazidev/website-to-markdown): any URL, sitemap or whole site to clean Markdown for LLMs and RAG.

# Actor input Schema

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

Pages to capture, one per line. `https://` is added if missing. Duplicates are skipped. Invalid URLs get a free error row.

## `outputType` (type: `string`):

`screenshot` = image only, `pdf` = PDF only, `both` = image and PDF of each page (charged as one screenshot + one PDF).

## `viewport` (type: `string`):

Browser window size. `desktop` 1920×1080, `laptop` 1366×768, `macbook` 1440×900 @2x (retina), `tablet` iPad-like 820×1180 @2x, `mobile` iPhone-like 390×844 @2x (touch + mobile user agent), `android` Pixel-like 412×915, `og-image` 1200×630 (social preview card). `custom` uses the width/height below.

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

Only for viewport `custom`. 200-3840.

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

Only for viewport `custom`. 200-4320.

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

Only for viewport `custom`: enable touch and mobile meta-viewport handling.

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

Pixel density override (1-4). Leave empty to use the preset's value (mobile, tablet, macbook = 2; android = 2.625; others = 1). Use 3 for true iPhone sharpness. Higher = sharper but bigger images.

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

Capture the whole scrollable page instead of only the visible viewport.

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

`png` (lossless), `jpeg` (small, uses quality) or `webp` (smallest, uses quality).

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

1-100. Ignored for PNG.

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

Optional, e.g. `#main`, `header`, `.pricing-table`. The first visible match is captured. If it does not appear within 15 s you get a free error row.

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

Hides common consent managers (OneTrust, Cookiebot, Didomi, Quantcast, Usercentrics, TrustArc, Sourcepoint, CookieYes, Complianz, ...) and fixed boxes that mention cookies/consent, using CSS only. Nothing is clicked or accepted.

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

Blocks requests to about 75 common ad, analytics and tracking domains (DoubleClick, Google Analytics/Tag Manager, Facebook pixel, Hotjar, Taboola, Criteo, ...). Pages load faster and screenshots are cleaner.

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

Emulate `prefers-color-scheme: dark`. Sites that support dark mode render dark.

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

When the page counts as loaded. `load` (default) also waits up to 3 s for the network to go quiet. `networkidle` is strict (no requests for 500 ms). If the wait times out but the page has content, it is still captured, with a `warning`.

## `delaySecs` (type: `integer`):

Wait this many seconds after loading, e.g. for animations, charts or slow widgets. 0-30.

## `scrollToLoad` (type: `boolean`):

For full-page screenshots, scroll through the page first (max 8 s) so lazy-loaded images and sections render.

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

Full-page captures are cut at this height (CSS pixels, max 16,000) so endless feeds do not produce giant images. Images are also limited to 16,383 device pixels in height (WebP format limit; keeps memory bounded), so at 2x scale the cut is at about 8,190 CSS px.

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

Used when Output includes PDF.

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

Landscape orientation for PDFs.

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

`print` uses the site's print stylesheet (clean, text-focused). `screen` makes the PDF look like the website on screen.

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

Injected before capture, e.g. `.chat-widget { display: none !important; }`.

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

Runs in the page before capture (async function body, `await` allowed), e.g. `document.querySelector('#tab-2').click(); await new Promise(r => setTimeout(r, 500));`. If it throws, you get a free error row.

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

Max time to load a page (5-180).

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

Extra attempts on timeouts and network errors (0-3). DNS errors are not retried.

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

Pages captured in parallel in one shared browser (1-10). 3 is right for 2 GB memory; use 5-6 with 4 GB.

## `maxUrls` (type: `integer`):

Capture at most this many URLs (0 = all).

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

Optional. Overrides the browser/device user agent.

## `ignoreHttpsErrors` (type: `boolean`):

Capture sites with expired or self-signed certificates.

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

Optional. Most sites work without a proxy. Datacenter Apify Proxy or your own proxy URLs are supported (residential is not).

## Actor input object example

```json
{
  "urls": [
    "https://example.com",
    "https://en.wikipedia.org/wiki/Web_scraping",
    "https://apify.com"
  ],
  "outputType": "screenshot",
  "viewport": "desktop",
  "viewportWidth": 1280,
  "viewportHeight": 800,
  "isMobile": false,
  "fullPage": true,
  "format": "png",
  "quality": 80,
  "hideCookieBanners": true,
  "blockAds": true,
  "darkMode": false,
  "waitUntil": "load",
  "delaySecs": 0,
  "scrollToLoad": true,
  "maxHeight": 16000,
  "pdfFormat": "A4",
  "pdfLandscape": false,
  "pdfMedia": "print",
  "navigationTimeoutSecs": 45,
  "maxRetries": 1,
  "maxConcurrency": 3,
  "maxUrls": 0,
  "ignoreHttpsErrors": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

No description

## `pdfs` (type: `string`):

No description

## `errors` (type: `string`):

No description

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

No description

## `summary` (type: `string`):

No description

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

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

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

```

## MCP server setup

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