Website Screenshot API (Apify Actor)

Turn URLs into full-page PDFs or PNG/JPEG screenshots: $0.004 per PDF, $0.0008 per screenshot, failed pages free. Paste URLs or HTML, get downloadable files back. Cookie banners removed, lazy-load scrolling, no API key. Runs as an Apify Actor, callable from MCP clients via the Apify MCP server (https://mcp.apify.com/?actors=pennydata/shot-pdf).

Serveur MCP hébergé

npx add-mcp 'https://mcp.apify.com/?actors=pennydata/shot-pdf'

S’installe dans Claude Code, Codex, Cursor et plus

Documentation

Website Screenshot & URL to PDF Converter, from $0.0008/page (pennydata/shot-pdf) Actor

Website screenshot and URL to PDF in bulk: paste URLs or HTML, get full-page PNG, JPEG or PDF files. $0.0008 per screenshot, $0.004 per PDF, failed pages free. Click Start: the 2 prefilled URLs run as screenshots for under $0.002. No API key.

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. 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 section below.

Each client library has reference documentation the quickstart does not restate: JavaScript/TypeScript (npm install apify-client) and Python (pip install apify-client).

README

Website Screenshot & URL to PDF Converter: $0.0008 per page

Give it URLs or HTML and get a full-page screenshot (PNG/JPEG, $0.0008) or PDF ($0.004) per page, rendered in headless Chromium. Failed pages are never charged. Price per page: screenshot $0.0008, PDF $0.004, both $0.0048.

Click Start: the prefilled 2 URLs (example.com and a Wikipedia page) run as is as screenshots (mode: screenshot) and cost at most $0.0016. Want a PDF? Set Output to pdf ($0.004 per page). Each URL returns one row:

inputhttpStatustitlepdfBytes
https://example.com200Example Domain91,727
https://en.wikipedia.org/wiki/Web_scraping200Web scraping - Wikipedia2,556,322

(Real rows from our test runs, 2026-10-16 to 10-21; pdfUrl and screenshotUrl link to the saved files.)

Quick start (only urls is required)

{ "urls": [{ "url": "https://en.wikipedia.org/wiki/Web_scraping" }], "mode": "pdf" }

urls accepts plain strings or {"url": "..."} objects. Every other field has a default.

Why use it

  • PDF as well as images: mode is screenshot, pdf or both (paper size A4/Letter/Legal/A3, landscape, backgrounds).
  • HTML to PDF / image: render inline HTML strings (htmlDocuments), not just URLs.
  • Full page, viewport or crop: fullPage on (default) captures the whole page; off captures the viewportWidth x viewportHeight window; clipWidth / clipHeight crop from the top-left corner.
  • Element screenshot: screenshotSelector captures only the first element matching a CSS selector. No match gives an error row that is not charged.
  • Sticky headers: hideFixedElements (default off) turns fixed elements into absolute and sticky ones into static, so headers, cookie bars and chat widgets do not repeat down a full-page capture.
  • No charge on failure: each page is charged only after its file is saved; failed pages get an error row and no charge.
  • Bulk with rate limits: many URLs per run, default concurrency 3, max 60 page loads/minute, automatic retries.

Captura de pantalla web, Website Screenshot, Screenshot erstellen - Español, Deutsch, Português

Español: captura de pantalla de una página web a PNG o PDF (masivo)

Convierte una lista de URL públicas (o tu propio HTML) en capturas de pantalla de página completa (PNG/JPEG) o en PDF, con Chromium sin interfaz. Entrada de ejemplo: { "urls": [{ "url": "https://example.com" }], "mode": "pdf" }. Coste en el plan gratuito: $0,0008 por captura y $0,004 por PDF (1.000 PDF = $4,00); las páginas que fallan no se cobran.

Deutsch: Screenshot von Webseiten erstellen, URL in PDF umwandeln (Liste)

Macht aus einer Liste öffentlicher URLs (oder eigenem HTML) ganzseitige Screenshots (PNG/JPEG) oder PDFs, gerendert mit headless Chromium. Beispiel-Eingabe: { "urls": [{ "url": "https://example.com" }], "mode": "both" }. Kosten im kostenlosen Plan: $0,0008 pro Screenshot und $0,004 pro PDF (Modus both = $0,0048 pro Seite); fehlgeschlagene Seiten werden nicht berechnet.

Português: captura de tela de site e URL para PDF em massa

Transforma uma lista de URLs públicas (ou HTML próprio) em capturas de tela de página inteira (PNG/JPEG) ou PDF, com Chromium headless. Exemplo de entrada: { "urls": [{ "url": "https://example.com" }], "mode": "screenshot" }. Custo no plano gratuito: US$ 0,0008 por captura e US$ 0,004 por PDF (1.000 PDFs = US$ 4,00); páginas que falham não são cobradas.

Example output

One item from a run with mode: both on https://example.com. On the Apify platform screenshotUrl and pdfUrl are links to files in the run's key-value store.

{
  "input": "https://example.com",
  "finalUrl": "https://example.com/",
  "httpStatus": 200,
  "title": "Example Domain",
  "screenshotUrl": "https://api.apify.com/v2/key-value-stores/<storeId>/records/screenshot-1.png",
  "pdfUrl": "https://api.apify.com/v2/key-value-stores/<storeId>/records/pdf-1.pdf",
  "screenshotBytes": 84613,
  "pdfBytes": 91727,
  "capturedAt": "2026-10-21T03:22:04.280Z"
}

Failed items get a row with input, error and capturedAt, and are not charged.

Options

Screenshot / PDF / both, full-page, PNG or JPEG, viewport size, clipWidth / clipHeight crop, screenshotSelector element capture, hideFixedElements, scroll to top, wait-until (load, domcontentloaded, networkidle), extra delay, wait for a CSS selector, PDF paper size, landscape, print backgrounds, concurrency and retries. Navigation timeout is 45 s. Colour emoji and fonts render as glyphs (Noto Color Emoji is in the image).

Screenshot FAQ

Screenshot above the fold / only the top of a page? Set fullPage to false for exactly the browser window, or crop a full-page capture with clipHeight:

{ "urls": [{ "url": "https://example.com" }], "fullPage": false, "viewportWidth": 1280, "viewportHeight": 720 }
{ "urls": [{ "url": "https://en.wikipedia.org/wiki/Web_scraping" }], "fullPage": true, "clipHeight": 1500 }

Capture one element?

{ "urls": [{ "url": "https://example.com" }], "screenshotSelector": "p" }

Sticky header repeated down a full-page shot? Turn on hideFixedElements:

{ "urls": [{ "url": "https://en.wikipedia.org/wiki/Web_scraping" }], "fullPage": true, "hideFixedElements": true }

Loading screen captured instead of the loaded page? Wait for the network and for an element that only exists once the page is ready:

{ "urls": [{ "url": "https://example.com" }], "waitUntil": "networkidle", "waitForSelector": "#app .loaded", "delayMs": 3000 }

Am I charged for pages that fail? No. Pages that return HTTP 4xx/5xx, time out or cannot be saved get an error row and no charge. Each result is charged only after the file is saved.

Call it synchronously and get the rows back in one request:

curl -X POST "https://api.apify.com/v2/acts/pennydata~shot-pdf/run-sync-get-dataset-items?token=$APIFY_TOKEN" -H "Content-Type: application/json" -d '{"urls":[{"url":"https://example.com"}],"mode":"pdf"}'

Does it capture pages behind a login? No. It does not log in, inject cookies, solve captchas or rotate proxies. Public pages only.

Can I convert my own HTML to PDF? Yes, pass HTML strings in htmlDocuments and set mode to pdf.

Pricing (pay per event)

Charged only for successful captures, via Actor.charge:

EventPrice
screenshot$0.0008 ($0.80 per 1,000)
pdf$0.004 ($4 per 1,000)
mode both$0.0048 per page (one screenshot + one PDF)

Pages answering HTTP 4xx/5xx, timeouts and rejected URLs are not charged. Paid Apify plans get lower tiers. Platform events such as actor start follow Apify's standard pay-per-event rules.

Limits and honesty notes

  • No login, no cookie injection, no captcha solving, no proxy rotation to bypass blocks. Pages behind logins, bot walls or captchas may fail or capture the block page.
  • Only public http(s) URLs: localhost, private IP ranges and file: URLs are rejected.
  • You are responsible for having the right to capture the pages you submit.
  • Not a scraper: it returns images/PDFs, not structured page data.

Run locally

npm install
mkdir -p storage/key_value_stores/default
echo '{"urls":[{"url":"https://example.com"}],"mode":"both"}' > storage/key_value_stores/default/INPUT.json
npm start        # or: apify run
## results: storage/datasets/default, files: storage/key_value_stores/default

Use cases

  • Archive evidence of how a page looked on a given date (compliance, legal, support).
  • Generate PDFs from HTML you supply, such as reports or receipts.
  • Create above-the-fold preview images (clipHeight) for link directories or CMS thumbnails.
  • Take snapshots of a list of staging pages for visual review.
  • Archive competitor sale pages to PDF every day: save the input as an Apify Task and add a daily Schedule; each row has a capturedAt timestamp. Some retailers block automated browsers, so check each row for an error.

Built with AI assistance (Claude).

Actor input Schema

urls (type: array):

Public http(s) pages to capture. Each item is a URL string or an object like {"url": "https://example.com"}.

htmlDocuments (type: array):

Optional inline HTML strings to render (HTML to PDF/screenshot).

mode (type: string):

What to produce for each page.

format (type: string):

Image format for screenshots: png (lossless) or jpeg (smaller).

fullPage (type: boolean):

Capture the whole scrollable page instead of only the visible viewport.

viewportWidth (type: integer):

Browser viewport width in pixels.

viewportHeight (type: integer):

Browser viewport height in pixels.

clipWidth (type: integer):

Optional: crop the screenshot to the top-left N px wide. 0 = no crop.

clipHeight (type: integer):

Optional: capture only the top N px of the page (works with full-page on). 0 = no crop.

hideFixedElements (type: boolean):

Unsticks sticky navbars, cookie bars and chat widgets (fixed becomes absolute, sticky becomes static) so they do not repeat or cover content.

screenshotSelector (type: string):

Optional: capture only the first element matching this CSS selector (for example #chart or article). No match gives an unbilled error row. Screenshot mode only.

scrollToTop (type: boolean):

Scroll to the top of the page before capturing.

waitUntil (type: string):

Page lifecycle event to wait for before capturing: load, domcontentloaded or networkidle.

delayMs (type: integer):

Extra time to wait after the page is ready, in milliseconds, before capturing.

waitForSelector (type: string):

Optional selector to wait for (max 15s) before capture.

pdfFormat (type: string):

Paper size used for PDF output.

pdfLandscape (type: boolean):

Render PDFs in landscape orientation.

pdfPrintBackground (type: boolean):

Include CSS background colors and images in PDFs.

maxConcurrency (type: integer):

Maximum number of pages captured in parallel.

maxRetries (type: integer):

How many times to retry a page that fails before reporting an error.

Actor input object example

{
  "urls": [
    {
      "url": "https://example.com"
    },
    {
      "url": "https://en.wikipedia.org/wiki/Web_scraping"
    }
  ],
  "mode": "screenshot",
  "format": "png",
  "fullPage": true,
  "viewportWidth": 1280,
  "viewportHeight": 800,
  "clipWidth": 0,
  "clipHeight": 0,
  "hideFixedElements": false,
  "scrollToTop": true,
  "waitUntil": "load",
  "delayMs": 500,
  "pdfFormat": "A4",
  "pdfLandscape": false,
  "pdfPrintBackground": true,
  "maxConcurrency": 3,
  "maxRetries": 3
}

Actor output Schema

results (type: string):

No description

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

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": [
        {
            "url": "https://example.com"
        },
        {
            "url": "https://en.wikipedia.org/wiki/Web_scraping"
        }
    ],
    "mode": "screenshot"
};

// Run the Actor and wait for it to finish
const run = await client.actor("pennydata/shot-pdf").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

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": [
        { "url": "https://example.com" },
        { "url": "https://en.wikipedia.org/wiki/Web_scraping" },
    ],
    "mode": "screenshot",
}

# Run the Actor and wait for it to finish
run = client.actor("pennydata/shot-pdf").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

echo '{
  "urls": [
    {
      "url": "https://example.com"
    },
    {
      "url": "https://en.wikipedia.org/wiki/Web_scraping"
    }
  ],
  "mode": "screenshot"
}' |
apify call pennydata/shot-pdf --silent --output-dataset

MCP server setup

{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,pennydata/shot-pdf"
        }
    }
}

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/mKUrHZTYtNOuft0hb/builds/r3wP5F7bEtWm5BuPL/openapi.json