# URL Screenshot 📸 Full-Page & Viewport — Only $1/1K 💰 (`viralanalyzer/screenshot-url`) Actor

Capture full-page or viewport screenshots of any list of URLs. Each image is stored in the Key-Value Store and returned as a public download URL in the dataset. Configurable viewport, PNG/JPEG format, lazy-load scroll and per-URL error isolation included.

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

## Pricing

from $1.00 / 1,000 screenshot captureds

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/platform/actors/running/actors-in-store#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

## URL Screenshot 📸 Full-Page & Viewport — Only $1/1K 💰

[![Apify Store](https://img.shields.io/badge/Apify-Store-blue)](https://apify.com/viralanalyzer/screenshot-url)
![Price](https://img.shields.io/badge/price-%241%2F1K%20screenshots-4CAF50)

Capture **full-page or viewport screenshots** of any list of URLs. Each image is
stored in the run's **Key-Value Store** and returned in the dataset as a public
download URL.

Capture **screenshots full-page ou de viewport** de qualquer lista de URLs. Cada
imagem é guardada no **Key-Value Store** da run e retornada no dataset como uma
URL pública de download.

***

### How it works / Como funciona

**EN**

1. You provide a list of `urls` (plus optional viewport, format, scroll options).
2. The actor opens each URL in a real Chromium browser (Playwright).
3. It waits for load, optionally waits for a CSS selector, best-effort network
   idle (images), and scrolls to the bottom to trigger lazy loading.
4. It captures the screenshot (full-page or viewport; PNG or JPEG) and saves the
   bytes to the run's default **Key-Value Store** with key `screenshot-<i>.<ext>`.
5. One dataset item per URL is pushed with the public download URL
   (`https://api.apify.com/v2/key-value-stores/<storeId>/records/<key>`), title,
   status code, viewport and timestamp.

**PT**

1. Você informa uma lista de `urls` (mais opções de viewport, formato e scroll).
2. O actor abre cada URL em um navegador Chromium real (Playwright).
3. Ele espera o carregamento, opcionalmente um seletor CSS, network idle
   best-effort (imagens) e rola até o fim para ativar lazy loading.
4. Captura o screenshot (full-page ou viewport; PNG ou JPEG) e salva os bytes no
   **Key-Value Store** default da run com a chave `screenshot-<i>.<ext>`.
5. Um item por URL é gravado no dataset com a URL pública de download
   (`https://api.apify.com/v2/key-value-stores/<storeId>/records/<key>`), title,
   status code, viewport e timestamp.

### Features / Funcionalidades

- **Full-page ou viewport** — capture a página inteira ou apenas a área visível.
- **Viewport customizável** — qualquer resolução (default 1280x800).
- **PNG ou JPEG** — JPEG com qualidade ajustável (1-100).
- **Lazy-load scroll** — scroll incremental ativa imagens/conteúdo preguiçoso.
- **Erros isolados por URL** — uma URL que falha não derruba a run; vira item de
  erro (`screenshot_url: null`) e **não é cobrada**.
- **Sem anti-bot frustrado** — se todas as URLs falharem, um item diagnóstico
  (`setup_status: "DIAGNOSTIC_GUIDE"`) é emitido com causas e remediações.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `urls` | `string[]` **required** | `["https://example.com"]` | URLs to capture. Each produces one screenshot. |
| `fullPage` | `boolean` | `true` | Capture the entire page height (`true`) or only the visible viewport (`false`). |
| `viewport` | `object` | `{width:1280, height:800}` | Browser viewport size in pixels. |
| `format` | `enum` | `"png"` | `png` or `jpeg`. |
| `quality` | `integer` | `80` | JPEG quality 1-100 (only for `jpeg`). |
| `pageLoadTimeout` | `integer` | `30` | Seconds to wait for each page to load before failing that URL. |
| `waitForSelector` | `string` | `""` | CSS selector to wait for before capture (e.g. `body`, `#app`). Empty = skip. |
| `scrollToBottom` | `boolean` | `true` | Scroll incrementally before capture to trigger lazy loading. |
| `waitForImages` | `boolean` | `true` | Best-effort wait for network idle so images render before capture. |
| `proxyConfig` | `proxy` | `{useApifyProxy: true}` | Apify proxy; enable `RESIDENTIAL` if sites block datacenter IPs. |

#### Example input JSON / Exemplo de input

```json
{
  "urls": ["https://example.com", "https://github.com", "https://news.ycombinator.com"],
  "fullPage": true,
  "viewport": { "width": 1280, "height": 800 },
  "format": "png",
  "pageLoadTimeout": 30,
  "scrollToBottom": true,
  "waitForImages": true,
  "proxyConfig": { "useApifyProxy": true }
}
```

### Output fields / Campos de saída

| Field | Type | Description |
|---|---|---|
| `url` | `string` | Source URL that was captured. |
| `screenshot_url` | `string \| null` | Public download URL of the image (`null` on error). |
| `key` | `string \| null` | Key-Value Store key of the image. |
| `title` | `string \| null` | Page title at capture time. |
| `status_code` | `number \| null` | HTTP status code of the page. |
| `viewport` | `string \| null` | Viewport used, e.g. `1280x800`. |
| `fullPage` | `boolean` | Whether full-page capture was used. |
| `timestamp` | `string \| null` | ISO timestamp of the capture. |
| `error` | `string \| null` | Error message when the capture failed. |
| `setup_status` | `string \| null` | `DIAGNOSTIC_GUIDE` when every URL failed. |
| `_dataQuality` | `string` | `screenshot` | `error` | `diagnostic`. |

Example item / Exemplo de item:

```json
{
  "url": "https://example.com",
  "screenshot_url": "https://api.apify.com/v2/key-value-stores/xxx/records/screenshot-0.png",
  "key": "screenshot-0.png",
  "title": "Example Domain",
  "status_code": 200,
  "viewport": "1280x800",
  "fullPage": true,
  "timestamp": "2026-08-13T03:00:00.000Z",
  "_dataQuality": "screenshot"
}
```

### Pricing / Preços & Free tier

- **Charge:** `$0.001` per valid screenshot (event `screenshot-captured`, i.e.
  **$1 per 1,000 screenshots**). Errors and the diagnostic guide item are
  **never charged**.
- **Free tier (non-owner, non-paying):** limited to **3 URLs** per run. Upgrade
  your Apify plan to unlock the full input.
- **PT:** `$0.001` por screenshot válido (evento `screenshot-captured`, ou seja
  **$1 por 1.000 screenshots**). Erros e o item de diagnóstico **nunca são
  cobrados**. Free tier (não-owner, não-pagante): limitado a **3 URLs** por run.

### FAQ

- **Onde ficam as imagens?** No Key-Value Store default da run. O dataset guarda
  apenas a URL pública de download de cada imagem.
- **A imagem some depois?** A KV store da run persiste enquanto a run existir na
  sua conta; baixe as imagens para armazenamento de longo prazo se precisar.
- **Uma URL quebrada derruba a run?** Não. Cada URL é isolada: falha vira item
  com `screenshot_url: null`, `_dataQuality: "error"` e sem cobrança.
- **E se TODAS falharem?** A run emite um item diagnóstico (`setup_status:
  "DIAGNOSTIC_GUIDE"`) com causas e remediações e termina `SUCCEEDED`, sem charge.
- **Qual proxy usar?** Datacenter default é mais barato. Se o site bloquear,
  use `RESIDENTIAL`.
- **PT:** As imagens ficam no KV Store default da run. URL quebrada não derruba
  a run. Se todas falharem, item diagnóstico + SUCCEEDED sem cobrança.

### Limitations / Limitações (honestas)

- Sites com **anti-bot agressivo** (Cloudflare, captcha, fingerprinting) podem
  bloquear a captura mesmo com proxy. Nesses casos, tente `RESIDENTIAL`, aumente
  `pageLoadTimeout` ou use uma API oficial do site.
- **Full-page de páginas infinitas** (scroll infinito) é truncado no limite do
  scroll — a captura cobre o conteúdo carregado até o fim do scroll.
- `networkidle` é best-effort: sites com polling contínuo (analytics, websockets)
  podem capturar antes de todas as imagens renderizarem; aumente
  `pageLoadTimeout`/`waitForSelector` para forçar mais espera.
- Sites que exigem login/autenticação não são suportados nesta versão.
- **PT:** Sites com anti-bot agressivo podem bloquear mesmo com proxy; full-page
  de páginas infinitas é truncado; login não é suportado.

### Changelog

- **v1.0 (2026-08-13):** primeira versão — PlaywrightCrawler, KV Store + dataset,
  FREE\_TIER cap, UAG-SG guard, charge `screenshot-captured` $1/1K com owner-skip.

# Actor input Schema

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

List of URLs to capture. Each URL produces one screenshot item.

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

Capture the entire page height (true) or only the visible viewport (false).

## `viewport` (type: `object`):

Browser viewport size (width x height in pixels).

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

PNG (lossless, larger) or JPEG (smaller, quality applies).

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

JPEG quality 1-100. Only used when format is 'jpeg'.

## `pageLoadTimeout` (type: `integer`):

Maximum time to wait for each page to load before failing that URL.

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

CSS selector to wait for before capturing (e.g. 'body' or '#app'). Leave empty to skip.

## `scrollToBottom` (type: `boolean`):

Scroll the page incrementally before capturing to trigger lazy loading of images/content.

## `waitForImages` (type: `boolean`):

Best-effort wait for network idle after load so images are rendered before capture.

## `proxyConfig` (type: `object`):

Proxy settings. Default uses lower-cost Apify datacenter proxy; enable RESIDENTIAL only if sites block the capture.

## Actor input object example

```json
{
  "urls": [
    "https://example.com",
    "https://github.com",
    "https://news.ycombinator.com"
  ],
  "fullPage": true,
  "viewport": {
    "width": 1280,
    "height": 800
  },
  "format": "png",
  "quality": 80,
  "pageLoadTimeout": 30,
  "waitForSelector": "",
  "scrollToBottom": true,
  "waitForImages": true,
  "proxyConfig": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

Dataset containing one item per URL with the screenshot download URL. Each item follows the dataset schema.

# 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"
    ],
    "fullPage": true,
    "viewport": {
        "width": 1280,
        "height": 800
    },
    "format": "png",
    "quality": 80,
    "pageLoadTimeout": 30,
    "waitForSelector": "",
    "scrollToBottom": true,
    "waitForImages": true,
    "proxyConfig": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("viralanalyzer/screenshot-url").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"],
    "fullPage": True,
    "viewport": {
        "width": 1280,
        "height": 800,
    },
    "format": "png",
    "quality": 80,
    "pageLoadTimeout": 30,
    "waitForSelector": "",
    "scrollToBottom": True,
    "waitForImages": True,
    "proxyConfig": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("viralanalyzer/screenshot-url").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"
  ],
  "fullPage": true,
  "viewport": {
    "width": 1280,
    "height": 800
  },
  "format": "png",
  "quality": 80,
  "pageLoadTimeout": 30,
  "waitForSelector": "",
  "scrollToBottom": true,
  "waitForImages": true,
  "proxyConfig": {
    "useApifyProxy": true
  }
}' |
apify call viralanalyzer/screenshot-url --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,viralanalyzer/screenshot-url"
        }
    }
}

```

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/yDRht4aiSBUxwK8KV/builds/M4LiU1NfYbwidC2mj/openapi.json
