# Website Screenshot API: Full Page, Mobile, PDF (`jtpalms/website-screenshot`) Actor

Screenshot any list of URLs as full-page or viewport PNG, JPEG, WebP or PDF, on desktop, laptop, tablet or mobile. Cookie banners hidden, lazy images loaded, element screenshots, dark mode. Pay only per screenshot saved.

- **URL**: https://apify.com/jtpalms/website-screenshot.md
- **Developed by:** [JT Palms](https://apify.com/jtpalms) (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 $3.20 / 1,000 screenshot takens

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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, mobile, tablet and PDF

Paste a list of URLs and get back a screenshot of each page: the whole scrollable page or just the first screen, as PNG, JPEG, WebP or PDF, on a desktop, laptop, tablet or phone. Cookie banners are hidden, lazy-loaded images are loaded, and you can capture a single element such as a pricing table.

**USD 4 per 1,000 screenshots.** You pay only for screenshots that were taken and saved. Pages that fail, do not exist or block the browser are reported free.

### What people use it for

- **Website archives and change tracking.** Capture your own or competitors' homepages, pricing and landing pages on a schedule.
- **SEO and marketing reports.** Full-page shots of search results, landing pages and ads, on desktop and mobile.
- **Visual QA.** Check how a site renders on a phone, a tablet and a desktop, in light and dark mode, after every release.
- **Link previews and thumbnails.** Viewport-sized JPEG or WebP images for directories, dashboards and CMS entries.
- **Compliance and evidence.** PDF copies of web pages with selectable text and working links, with the time they were taken.

### Sample output

One row per URL. The image itself is saved in the run's key-value store and linked from `screenshotUrl`:

```json
{
  "url": "https://www.python.org/",
  "finalUrl": "https://www.python.org/",
  "title": "Welcome to Python.org",
  "statusCode": 200,
  "device": "desktop",
  "format": "png",
  "width": 1440,
  "height": 2555,
  "bytes": 501233,
  "screenshotUrl": "https://api.apify.com/v2/key-value-stores/STORE_ID/records/python.org-1e99bf8a65.png",
  "screenshotKey": "python.org-1e99bf8a65.png",
  "truncated": false,
  "cookieBannersHidden": 0,
  "loadSecs": 0.2,
  "takenAt": "2026-09-28T19:31:39.089Z",
  "warning": null,
  "error": null
}
```

`width` and `height` are the real pixel size of the saved image (for PDFs, the page size in points). The dataset's **Screenshots** view shows the images as thumbnails. Export as JSON, CSV or Excel, or pull the results through the Apify API.

### How to use it

1. Put your pages in **URLs**, one per line. Full URLs and bare domains (`example.com`) both work.
2. Pick a **Device** and a **File format**. Leave **Full page** on for the whole page, or turn it off for the first screen only.
3. Click **Start**, then open the dataset or the key-value store to download the files.

Connect the actor to Make, Zapier, n8n or your own code through the Apify API to take screenshots on a schedule or on demand.

### Options

| Option | What it does |
|---|---|
| Device | Desktop 1440 x 900, laptop 1280 x 800, tablet (iPad), mobile (iPhone 15), or a custom width and height. Tablet and mobile use touch and a mobile user agent, so sites show their mobile layout. |
| Full page | Whole scrollable page (default) or only the first screen. Very long pages are cut at **Maximum page height** (20,000 px by default) and marked `truncated`. |
| File format | PNG (lossless), JPEG or WebP (much smaller, with a quality setting), or PDF (A4, Letter, Legal or A3, scaled to the device width). |
| Element to capture | A CSS selector such as `#pricing` or `table.infobox`. Only that element is captured. |
| Hide cookie banners | On by default. Hides the banners of 30+ consent managers (OneTrust, Cookiebot, Didomi, Quantcast, TrustArc, Usercentrics, Sourcepoint and others) and clicks "reject" or "necessary only" where offered. It never accepts cookies for you. |
| Hide these elements | Your own CSS selectors to remove before capturing, for example chat widgets or promo bars. |
| Load lazy images | On by default. Scrolls through the page so lazy images and sections load, then back to the top. |
| Dark mode | Asks the site for its dark color scheme. |
| Wait until, extra delay, timeout | When the page counts as loaded, an optional delay for animations, and the maximum load time. |
| Pixel density | 1, 2 or 3 for sharp retina images. |
| Proxy | Optional. Load pages through a data center proxy or your own proxy URL, for example to see a site as visitors in another country see it. Residential proxies are not supported. |

### Pricing

| What | Price |
|---|---|
| Screenshot or PDF taken and saved | USD 0.004 (USD 4 per 1,000) |
| Page failed, not found, blocked the browser, or private address refused | Free |

Set a maximum cost per run in the run options and the actor stops cleanly when it reaches it. Screenshots taken before that are kept.

### Speed and memory

With the default 4 GB of memory the actor loads 3 pages in parallel. Full-page captures of heavy news sites take about 2.5 seconds per page on average, first-screen captures about 2 seconds. Each parallel page needs about 1.1 GB of memory at its peak; if you give the run less memory, the actor lowers the number of parallel pages by itself.

### Limits

- **No CAPTCHA solving or bot-protection bypass.** Pages that answer with HTTP 401, 403 or 429, or show a CAPTCHA or "checking your browser" page, are reported with a `warning` and are not charged. A proxy under **Advanced** helps with sites that block data centers, but does not get past CAPTCHAs.
- **Public websites only.** Private and internal addresses (localhost, 10.x, 172.16 to 31.x, 192.168.x, 169.254.x, 100.64/10, IPv6 local ranges, `*.local`, `*.internal`) are refused before the page is opened, and a public page cannot redirect or load images, frames or requests into them. Refused URLs are free.
- Logins and paywalls are not bypassed. The actor sees what a new visitor without cookies sees.
- WebP images are at most 16,383 pixels tall, so long WebP captures are cut there. Use PNG or JPEG for very long pages.
- Pages that keep changing (live tickers, video, infinite feeds) are captured as they are at the moment of the shot.

### Related actors

- [Link Preview Metadata: Open Graph, Twitter Card, Favicon](https://apify.com/JTPalms/link-preview-metadata): Get what a link unfurler shows for any URL: title, description, image, site name, every Open Graph and Twitter card tag, best favicon,...
- [Website Tech Stack Detector (Wappalyzer Alternative)](https://apify.com/JTPalms/tech-stack-detector): Find the technology behind any website in bulk: CMS, ecommerce platform, analytics, frameworks, CDN, hosting, payment, email and...

### FAQ

**Where are the image files?** In the run's default key-value store. Each dataset row has `screenshotUrl`, a direct link to the file, and `screenshotKey`, its key in the store.

**How long are the files kept?** As long as your Apify plan keeps the run's storage. Download them or copy them to your own storage if you need them longer.

**Why is a cookie banner still visible?** A few sites use their own banner code. Add its CSS selector to **Hide these elements** and it will be removed.

**Why is my screenshot cut off?** The page was taller than **Maximum page height**. Raise it (up to 60,000 px) or use first-screen captures.

**Is it legal?** It opens public web pages the way a browser does and saves an image of them. It does not log in or bypass protections. A screenshot shows whatever the page displays, which on some pages includes people's names or photos, so check the terms of the sites you capture and the privacy rules that apply to you before you republish their content.

### License

Apache-2.0. Built on Playwright (Apache-2.0) and proxy-chain (Apache-2.0).

# Actor input Schema

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

Web pages to capture, one per line. Full URLs or bare domains (example.com). Duplicates are removed automatically.

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

Screen size and device to emulate. Tablet and mobile use touch, a mobile user agent and the mobile layout of the site.

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

Capture the whole scrollable page. Turn off to capture only the first screen (what a visitor sees without scrolling).

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

PNG is lossless. JPEG and WebP are much smaller. PDF prints the page to A4 or Letter pages with selectable text and working links.

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

Optional. Capture only the first element matching this CSS selector, for example `#pricing`, `.product-card` or `table.infobox`. Leave empty for the whole page. Not used for PDF.

## `blockCookieBanners` (type: `boolean`):

Hide cookie and consent banners (OneTrust, Cookiebot, Didomi, Quantcast, TrustArc, Usercentrics, Sourcepoint and 25 more, plus a generic detector). Where a banner offers it, the actor clicks "reject" or "necessary only". It never accepts cookies for you.

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

Optional. Elements to remove before capturing, one CSS selector per line. Useful for chat widgets, promo bars or ads, for example `#intercom-container` or `.newsletter-popup`.

## `scrollToLoadLazy` (type: `boolean`):

Scroll through the page before capturing so lazy-loaded images and sections appear, then scroll back to the top.

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

Tell the site the visitor prefers a dark color scheme. Sites that support dark mode will render in it.

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

When the page counts as loaded. "Load" suits most sites. "Network idle" waits until no requests happen for half a second (slower, best for heavy single-page apps). If the chosen point is not reached in time, the actor still captures what has rendered and adds a warning.

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

Wait this long after the page has loaded and before capturing. Use it for pages with intro animations or charts that draw slowly.

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

Maximum time to wait for each page to load.

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

1 to 100. Higher is sharper and larger. Ignored for PNG and PDF.

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

1 gives images at CSS pixel size (a 1440 px wide desktop shot). 2 or 3 gives sharp retina images, 2 or 3 times as wide and tall.

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

Full-page captures of endless pages are cut at this height, measured in CSS pixels. The row then has truncated = true. WebP images are limited to 16,383 pixels per side, so long WebP captures are cut there.

## `pdfPaperSize` (type: `string`):

Page size for PDF output. The page is scaled so its layout matches the chosen device width.

## `width` (type: `integer`):

Viewport width when Device is "Custom".

## `height` (type: `integer`):

Viewport height when Device is "Custom". With Full page on, this is the height of the first screen; the image is as tall as the page.

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

How many pages to load at the same time. Each needs about 1.1 GB of memory for full-page captures, so 3 fits the default 4 GB. If the run has less memory, the actor lowers this number automatically.

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

Optional. Load pages through a proxy, for example to see a site as visitors in another country see it. It does not get past CAPTCHAs or bot protection. Data center proxies only; residential proxies are not supported.

## Actor input object example

```json
{
  "urls": [
    "https://apify.com",
    "https://en.wikipedia.org/wiki/Web_scraping"
  ],
  "device": "desktop",
  "fullPage": true,
  "format": "png",
  "blockCookieBanners": true,
  "scrollToLoadLazy": true,
  "darkMode": false,
  "waitUntil": "load",
  "delaySecs": 0,
  "timeoutSecs": 45,
  "quality": 80,
  "deviceScaleFactor": 1,
  "maxHeight": 20000,
  "pdfPaperSize": "A4",
  "width": 1440,
  "height": 900,
  "maxConcurrency": 3
}
```

# Actor output Schema

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

All output rows in the default dataset (JSON, CSV, Excel via the format parameter).

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

Counts and per-input status for this run.

# 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"
    ]
};

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

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

```

## MCP server setup

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