# Website Screenshot API: full-page, element, mobile & PDF (`steadyline/website-screenshot`) Actor

Capture screenshots of any list of URLs with real Chromium: viewport, full-page, element and PDF captures in PNG, JPEG, WebP or PDF, with cookie-banner hiding, ad blocking, dark mode and custom CSS/JS. Also usable as a live HTTP API via Standby mode. By Steadyline Data.

- **URL**: https://apify.com/steadyline/website-screenshot.md
- **Developed by:** [Steadyline Data](https://apify.com/steadyline) (community)
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 screenshots

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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, element, mobile & PDF

Capture pixel-accurate screenshots of any number of web pages with a real **Chromium** browser (Playwright). You can capture the viewport, the full scrolling page, a single element, or an A4 **PDF**, in PNG, JPEG or WebP. Every image is stored in the run's key-value store and returned with a shareable link. Built and maintained by **Steadyline Data**.

### Features

- **Viewport presets:** desktop 1920×1080, laptop 1366×768, tablet 820×1180 @2x, mobile 390×844 @3x (iPhone user agent and touch), or a custom size and pixel density.
- **Full page:** the Actor scrolls the page first so lazy-loaded images appear, then captures the whole page.
- **Element capture:** pass a CSS selector such as `header` or `#pricing` and only that element is captured.
- **Formats:** PNG, JPEG and WebP (with quality), or PDF with backgrounds.
- **Clean captures:** cookie and consent banners from about 60 common consent managers and generic banners (OneTrust, Cookiebot, Didomi, Quantcast, Usercentrics, CookieYes and more) are hidden, never accepted. Requests to about 60 ad, tracker and chat-widget hosts are blocked, and you can add your own selectors to hide.
- **Dark mode** (`prefers-color-scheme: dark`), **custom CSS**, and **custom JavaScript** that runs only inside the page's browser sandbox, for example to open a tab before capturing.
- `waitUntil` (networkidle, load or domcontentloaded), an extra delay, per-page timeouts, retries and concurrency.
- **Standby mode (live HTTP API):** call `GET https://steadyline--website-screenshot.apify.actor/?url=example.com&viewport=mobile&fullPage=true&format=jpeg` with your Apify token (`Authorization: Bearer <token>`) and the image comes back directly in the response. Query parameters use the same names as the input fields. Custom JS is only available in batch mode.

### Output

Each URL produces one dataset row: `url`, `finalUrl`, `status` (HTTP), `title`, `imageUrl` (signed link to the stored image), `kvKey`, `format`, `viewport`, `fullPage`, `width`, `height`, `bytes`, `takenAt` and `error`.

Real output from a cloud test run (mobile preset). The second row shows a site that blocked the request with HTTP 403. That page is still captured so you can inspect it, but it is reported as an error and **not charged**:

```json
[
  {
    "url": "https://www.wikipedia.org/",
    "finalUrl": "https://www.wikipedia.org/",
    "status": 200,
    "title": "Wikipedia",
    "imageUrl": "https://api.apify.com/v2/key-value-stores/dYFMufuifjQUD6KJK/records/www-wikipedia-org-mobile-239cbc0600.png?signature=\u2026",
    "kvKey": "www-wikipedia-org-mobile-239cbc0600.png",
    "format": "png",
    "viewport": "mobile",
    "fullPage": false,
    "width": 390,
    "height": 844,
    "bytes": 391574,
    "takenAt": "2026-10-29T22:48:02.131Z",
    "error": null
  },
  {
    "url": "https://www.nytimes.com/",
    "finalUrl": "https://www.nytimes.com/",
    "status": 403,
    "title": "nytimes.com",
    "imageUrl": "https://api.apify.com/v2/key-value-stores/dYFMufuifjQUD6KJK/records/www-nytimes-com-mobile-5f9de1a079.png?signature=\u2026",
    "kvKey": "www-nytimes-com-mobile-5f9de1a079.png",
    "format": "png",
    "viewport": "mobile",
    "fullPage": false,
    "width": 390,
    "height": 844,
    "bytes": 106777,
    "takenAt": "2026-10-29T22:48:01.686Z",
    "error": "HTTP 403: page returned an error or blocked the request (captured for reference, not charged)"
  }
]
```

### Pricing and cost example

Pay per event, with platform usage included:

- `screenshot`: **$0.002** per successful viewport or element screenshot.
- `screenshot-fullpage-or-pdf`: **$0.004** per successful full-page screenshot or PDF.

Failed captures are **never charged**: DNS errors, timeouts, missing selectors and pages that answer with HTTP 4xx or 5xx. For example, 1,000 product pages captured as viewport PNGs cost **$2.00**, and 500 full-page JPEG captures cost **$2.00**. You can cap spend with the run's maximum total charge.

### Tips and limits

- Use about 3 concurrent pages per 2 GB of memory. Full-page captures of very long pages (above roughly 16,000 px) can be heavy, and WebP is limited by the browser's canvas size.
- Some sites block cloud data-centre IPs, for example with HTTP 403. Those rows are flagged with `error` and not charged.
- `networkidle` falls back gracefully on sites that never stop polling.

### Acceptable use and legal

Only capture pages you are allowed to access. Respect each website's terms of service, robots rules and copyright, and do not use this Actor to bypass logins, paywalls or access controls, or to collect personal data unlawfully. Screenshots may contain third-party trademarks and copyrighted material, and you are responsible for how you use them. Steadyline Data is not affiliated with any of the websites you capture.

### Support

Questions or feature requests: open an issue on the Actor's Issues tab.

**Roadmap:** proxy support, so you can capture sites that block data-centre IPs.

# Actor input Schema

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

Pages to capture (http/https only). A missing scheme defaults to https://.

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

Device preset. Mobile and tablet use a touch, mobile user agent and higher pixel density.

## `customWidth` (type: `integer`):

Used when viewport = custom.

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

Used when viewport = custom.

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

Pixel density for custom viewport (1-3).

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

Mobile user agent and touch for custom viewport.

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

Capture the whole scrollable page instead of just the viewport (billed as full-page).

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

CSS selector; when set, only the first matching visible element is captured (e.g. header, #pricing).

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

Image format, or PDF (A4, backgrounds printed; billed as full-page/PDF).

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

Compression quality for JPEG and WebP.

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

When to consider the page loaded. networkidle falls back gracefully if a site never goes idle.

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

Wait after load before capturing (animations, late widgets).

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

Hides ~60 common consent-manager and cookie-banner selectors (OneTrust, Cookiebot, Didomi, Quantcast, Usercentrics, ...). Banners are hidden, never accepted.

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

Your own CSS selectors to hide (popups, chat bubbles).

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

Blocks requests to ~60 ad, analytics and chat-widget hosts. Faster, cleaner captures.

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

Emulates prefers-color-scheme: dark.

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

CSS injected before capture.

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

JavaScript evaluated in the page (browser sandbox only, no server access) before capture, e.g. to click a tab. Batch mode only.

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

Navigation and capture timeout.

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

Pages captured in parallel. ~3 per 2 GB memory.

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

Retries per URL on navigation errors.

## Actor input object example

```json
{
  "urls": [
    "https://apify.com",
    "https://www.wikipedia.org/"
  ],
  "viewport": "desktop",
  "fullPage": false,
  "format": "png",
  "quality": 80,
  "waitUntil": "networkidle",
  "delayMs": 0,
  "hideCookieBanners": true,
  "blockAds": true,
  "darkMode": false,
  "timeoutSecs": 45,
  "maxConcurrency": 3,
  "maxRetries": 1
}
```

# Actor output Schema

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

One row per URL with a link to the stored image.

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

Failed captures (not charged).

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

Key-value store with the captured image and PDF files.

# 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://www.wikipedia.org/"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("steadyline/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://www.wikipedia.org/",
    ] }

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

```

## MCP server setup

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