# Website Screenshot - Full Page PNG at Any Viewport (`s-r/website-screenshot`) Actor

Screenshot any list of URLs as PNG, at whatever viewport you choose, viewport-only or full page. Each image lands in the run's key-value store and every row carries a direct link to it.

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

## Pricing

Pay per event

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Website Screenshot

PNG screenshots of any list of URLs, at whatever viewport you choose, viewport
only or the whole scrollable page. Each image lands in the run's key-value
store and every dataset row carries a direct link to it.

Paste addresses with or without `https://`. A bare `example.com` works.

### Why the image is not in the table

A dataset is a table and a PNG is not. Putting the image into a column as
base64 makes the table unreadable, makes every CSV export enormous, and makes
the preview useless.

So the images go to the run's key-value store and each row carries `image_url`,
a plain link anyone with access to the run can open or download. `key` is the
same file's name in that store, which is prefixed with its position and the
host so the store stays legible when you are looking at fifty of them.

### Viewport

**Viewport width** is the single input that changes the most. A site lays
itself out differently at 1280 than at 390, so capturing both is how you see
the mobile layout. **Viewport height** sets the visible window and is ignored
when Full page is on.

### Full page has no natural end on some sites

**Full page** captures the whole scrollable document instead of the window.
That is what you want for a landing page or an article.

On an infinite-scroll site there is no bottom: the page keeps loading as it is
scrolled, so the capture is as tall as the renderer's patience rather than as
tall as the content. Leave it off for those, and use a tall viewport instead.

### A screenshot of a cookie banner is still a screenshot

This is the thing to know before you build on the output. A consent wall, a
404, an age gate and a login page all render perfectly well, and a capture of
one is reported as a success because an image really was produced.

`bytes` is the most useful signal here: a wall is usually far smaller than the
page behind it, and a set of captures that are all the same size is worth
looking at before trusting any of them.

### Errors

| Code | Meaning |
|---|---|
| `capture_failed` | The page did not render after every attempt |
| `bad_input` | No URL was given |

Raise **Attempts per URL** for slow or heavy pages. **Only images that exist
are billed**: a failed capture costs you nothing.

### Run sizes

**Parallel captures** defaults to 3. Rendering is the expensive part of this
job, so more parallelism finishes a long list sooner but each page still takes
as long as it takes.

### Related actors

For the text of a page rather than a picture of it, see the markdown and
crawling actors. For search results as images, see the SERP image actors.

# Actor input Schema

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

One address per line. The scheme is filled in when you leave it out, so example.com works.

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

Browser width in pixels. 1280 is a laptop, 390 is a phone, and a site will lay itself out differently for each.

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

Browser height in pixels. Ignored when Full page is on.

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

Capture the whole scrollable page instead of just the viewport. On an infinite-scroll site this has no natural end, so leave it off for those.

## `concurrency` (type: `integer`):

How many pages to render at once.

## `attempts` (type: `integer`):

How often to retry a page that did not render before giving up on it.

## Actor input object example

```json
{
  "urls": [
    "example.com",
    "https://news.ycombinator.com"
  ],
  "width": 1280,
  "height": 800,
  "fullPage": false,
  "concurrency": 3,
  "attempts": 3
}
```

# Actor output Schema

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

One row per URL, each with a link to its image.

## `images` (type: `string`):

The PNG files themselves.

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

How many were requested, captured and failed.

# 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("s-r/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"] }

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

```

## MCP server setup

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