# Website Screenshot API — URL & HTML to PNG, JPEG, WebP, PDF (`moonweil/url-screenshot-api`) Actor

Turn any URL or raw HTML into a screenshot, PDF, or Open Graph card. Full-page & device capture, dark mode, ad/tracker/cookie-banner blocking, visual diffing, base64-to-image conversion, and DOM + console-error extraction — all through one fast API.

- **URL**: https://apify.com/moonweil/url-screenshot-api.md
- **Developed by:** [Aleksandr Jelohhin](https://apify.com/moonweil) (community)
- **Categories:** Developer tools, Automation
- **Features:** Limited permissions
- **Stats:** 350 total users, 159 monthly users, 98.3% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 results

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 📸

Turn any **URL or raw HTML** into a pixel-perfect **screenshot, PDF, or Open Graph card**.
Full-page & device capture, dark mode, ad/tracker/cookie-banner blocking, PII redaction,
visual diffing, base64-to-image conversion, and DOM + console-error extraction — all in a
single run.

### Four tools in one Actor

Pick a **Mode** and get exactly one result per run — every mode is billed the same
(one result = one charge):

| Mode | What you get | Key inputs |
|---|---|---|
| **`screenshot`** (default) | PNG / JPEG / WebP / Chrome-rendered PDF of any URL **or raw HTML** | `url` or `html`, `format`, `fullPage`, `device` |
| **`og`** | Branded 1200×630 Open Graph / social-share card — no URL needed | `ogTitle`, `ogSubtitle`, `ogTheme`, `ogLogoUrl` |
| **`diff`** | Highlighted pixel-diff image of two URLs + `percentChanged` score | `url`, `compareUrl`, `diffThreshold` |
| **`decode`** | A base64 image string converted back to a downloadable file | `base64Image` |

Screenshot mode features:

- **Full page or viewport** — capture the whole scrollable page or just the fold
- **Device emulation** — iPhone 14, iPhone SE, Pixel 7, iPad Pro, desktop, or a custom viewport
- **Dark mode**, **timezone**, and **locale** emulation
- **Blocking** — strip ads, trackers, and cookie-consent banners before capture
- **Redaction** — hide or blur any CSS selector (e.g. account numbers, emails)
- **Wait strategies** — wait for a selector, network idle, or fonts + images to finish
- **DOM extraction** — return page text, links, and metadata alongside the image
- **Console capture** — collect JavaScript errors and warnings for QA / page-health checks

### Input

#### Screenshot (default mode)

Provide at least a `url` (or raw `html`). All other fields are optional:

```json
{
  "url": "https://example.com",
  "format": "png",
  "fullPage": true,
  "device": "iphone_14",
  "blockCookieBanners": true,
  "extract": ["metadata", "links"]
}
```

#### Open Graph card

```json
{
  "mode": "og",
  "ogTitle": "Ship Faster with Our API",
  "ogSubtitle": "One call. Any page. Pixel-perfect.",
  "ogTheme": "gradient"
}
```

The input above produces this card:

![Example OG card generated by this Actor](https://api.apify.com/v2/key-value-stores/Inbw2cIDCiKgO9HjC/records/og-sample.png?signature=SDVa3bjso4MfNNgGIaUm)

#### Visual diff

```json
{
  "mode": "diff",
  "url": "https://example.com",
  "compareUrl": "https://example.com/v2",
  "diffThreshold": 10
}
```

Changed pixels are highlighted, unchanged areas are greyed out
(example.com vs iana.org — 7.09% changed):

![Example visual diff generated by this Actor](https://api.apify.com/v2/key-value-stores/Inbw2cIDCiKgO9HjC/records/diff-sample.png?signature=12GQXlnnBdeQILKTgzn1W)

#### Decode base64

```json
{
  "mode": "decode",
  "base64Image": "iVBORw0KGgoAAAANSUhEUg..."
}
```

See the **Input** tab for the full, documented list of fields with defaults and bounds.

### Output

- **Key-value store** — the produced image is stored under `screenshot.<ext>`, `og-card.<ext>`,
  `diff.png`, or `decoded.<ext>` depending on the mode.
- **Dataset** — one record per run:

```json
{
  "mode": "screenshot",
  "url": "https://example.com",
  "format": "png",
  "width": 1920,
  "height": 1080,
  "captureTimeMs": 2184,
  "screenshotUrl": "https://api.apify.com/v2/key-value-stores/.../records/screenshot.png",
  "extraction": { "metadata": { "title": "Example Domain", "lang": "en" } },
  "consoleErrors": []
}
```

Diff runs additionally include `percentChanged`, `changedPixels`, and `totalPixels`.

`screenshotUrl` is a direct public link to the stored image — embed it, download it, or pass it downstream.

### Memory & performance

The default **1 GB** handles typical captures (most runs finish in 5–15 s). For very long,
media-heavy pages captured with **Full page + Scroll to load** (e.g. news home pages), run with
**2 GB** memory — at 1 GB the browser can run short of memory and the capture may time out.
If a capture fails, the run's status message explains why and no result is charged.

### Common uses

- Website thumbnails and preview images
- URL-to-PDF archiving and reporting
- Visual QA and page-health monitoring (console errors)
- Visual regression checks between two deployments or page versions
- Open Graph / social-share card generation
- Scraping page metadata and links together with a visual snapshot

***

<sub>**How it runs:** each run starts its own isolated headless Chrome inside the Actor container —
no external backend, and your pages and HTML never leave the Apify platform.</sub>

# Actor input Schema

## `mode` (type: `string`):

What to produce. screenshot: capture a URL or raw HTML. og: generate a 1200×630 Open Graph / social card (uses the OG fields below). diff: visually compare 'URL' against 'Compare URL' and return a highlighted diff image. decode: convert a base64 image string back to a raw image file.

## `url` (type: `string`):

The page to capture. Must be http(s). Mutually exclusive with 'html'.

## `html` (type: `string`):

Render this raw HTML instead of fetching a URL. Mutually exclusive with 'url'.

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

Image/document format to return.

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

100-3840 px. Ignored when 'device' is set.

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

100-2160 px. Ignored when 'device' is set.

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

Capture the entire scrollable page instead of just the viewport.

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

Overrides width/height/user-agent with a device emulation preset.

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

0-100. Applies to jpeg/webp only.

## `delay` (type: `integer`):

0-60. Extra wait after the page load event.

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

Wait until this element is visible before capturing.

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

load: fire on the browser load event. networkidle: load, then settle for 2s. complete: wait for fonts and images to finish too.

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

Emulate prefers-color-scheme: dark.

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

Block known ad-serving domains via CDP request blocking before capture.

## `blockTrackers` (type: `boolean`):

Block known tracker/analytics domains via CDP request blocking before capture.

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

Removes common cookie-consent overlays before capture.

## `hide` (type: `string`):

Comma-separated CSS selectors to hide (display:none) before capture.

## `blur` (type: `string`):

Comma-separated CSS selectors to blur before capture (useful for redacting PII).

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

Injected as a <style> tag before capture. Max 8192 chars.

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

Overrides the browser's User-Agent header/navigator.userAgent.

## `timezone` (type: `string`):

IANA timezone, e.g. America/New_York.

## `locale` (type: `string`):

BCP-47 locale, e.g. fr-FR.

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

Auto-scrolls the page before capture to trigger lazy-loaded images/sections.

## `extract` (type: `array`):

Also return DOM data alongside the screenshot.

## `captureConsole` (type: `boolean`):

Also return JS console errors/warnings encountered while loading the page.

## `ogTitle` (type: `string`):

Card headline (required in og mode, max 120 chars).

## `ogSubtitle` (type: `string`):

Optional subheading under the title (max 200 chars).

## `ogLogoUrl` (type: `string`):

Optional public HTTP(S) URL of a logo shown above the title.

## `ogTheme` (type: `string`):

Card color theme.

## `ogAccentColor` (type: `string`):

Hex accent color for the title gradient, e.g. #6c63ff.

## `compareUrl` (type: `string`):

Second page to compare against 'URL' (required in diff mode).

## `diffThreshold` (type: `integer`):

Per-pixel color-distance threshold as a percentage (0-100). Pixels differing more than this count as changed. Default 10.

## `diffHighlightColor` (type: `string`):

Hex color used to mark changed pixels, e.g. #ff0000.

## `diffStabilize` (type: `boolean`):

Deterministic rendering for reliable diffs: blocks ads/trackers/cookie banners, freezes animations, waits for network idle. Recommended.

## `base64Image` (type: `string`):

Base64-encoded image — plain base64 or a data:image/...;base64,... URL. Format is sniffed from the bytes when not set explicitly via 'Output format'.

## Actor input object example

```json
{
  "mode": "screenshot",
  "url": "https://example.com",
  "format": "png",
  "width": 1920,
  "height": 1080,
  "fullPage": false,
  "device": "",
  "quality": 85,
  "delay": 2,
  "waitUntil": "load",
  "darkMode": false,
  "blockAds": false,
  "blockTrackers": false,
  "blockCookieBanners": false,
  "scrollToLoad": false,
  "captureConsole": false,
  "ogTheme": "dark",
  "diffThreshold": 10,
  "diffStabilize": true
}
```

# Actor output Schema

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

Captured images (PNG/JPEG/WebP/PDF) stored in the key-value store.

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

One record per capture with the screenshot URL and render metadata.

# 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 = {
    "url": "https://example.com"
};

// Run the Actor and wait for it to finish
const run = await client.actor("moonweil/url-screenshot-api").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 = { "url": "https://example.com" }

# Run the Actor and wait for it to finish
run = client.actor("moonweil/url-screenshot-api").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 '{
  "url": "https://example.com"
}' |
apify call moonweil/url-screenshot-api --silent --output-dataset

```

## MCP server setup

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

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/4X8u4O2IIS8NiIxrM/builds/RQN4Rg23MVNBXefhW/openapi.json
