# Website Screenshot API, Full Page & URL/HTML to PDF (`rigel/website-screenshot-pdf`) Actor

Website screenshot API and URL/HTML to PDF converter. Full-page PNG, JPEG, WebP and A4/Letter PDF from one page load. Batch from a URL list, sitemap or dataset; iPhone/Android views; cookie banners hidden; visual regression diff. $2 per 1,000 files, failed URLs free.

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

## Pricing

from $2.00 / 1,000 files

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, Full Page & URL/HTML to PDF

Take a **website screenshot** (viewport, **full page**, one element, or a mobile view) and convert **URLs or raw HTML to PDF**, in bulk, from one Apify Actor. Each page is loaded once in headless Chromium, then every format you ask for (PNG, JPEG, WebP, PDF) comes from that same load. You pay **$0.002 per stored file**. Failed, blocked and skipped URLs are free.

- **Full-page screenshots** up to 16,384 px tall, with lazy images scrolled into view.
- **Mobile and tablet views**: iPhone 15, Pixel 8, iPad, plus desktop, laptop, MacBook Retina and a 1200×630 Open Graph card.
- **URL to PDF and HTML to PDF**: A4, Letter, Legal or A3, margins, landscape, backgrounds, page numbers, custom header and footer.
- **Batch input**: a list of URLs, a `sitemap.xml` (indexes and `.xml.gz` followed), or the URLs of an existing dataset. Up to 5,000 URLs per run.
- **Visual regression diff**: compare each screenshot with the previous run and get `percentChanged` plus a diff image.
- **Clean captures**: common cookie banners hidden with CSS, ads and trackers blocked, dark mode, custom CSS, hide or blur selectors.
- **API-first**: REST, Python, JavaScript, sync endpoint that returns the file bytes, MCP for AI agents, n8n and Make.

Social networks and private network addresses are refused before any navigation (see [Legal and safety](#legal-and-safety)).

### Use cases

| You want to… | Use these inputs |
| --- | --- |
| Archive how a page looked, as an image and a PDF | `formats: ["png", "pdf"]`, `fullPage: true` |
| Check a responsive layout on a phone | `device: "iphone_15"` or `"pixel_8"` |
| Turn a list of documentation or report pages into PDFs | `urls: [...]`, `formats: ["pdf"]`, `pdf.format: "A4"` |
| Generate PDF invoices, receipts or reports from your own HTML | `html: "<html>…"`, `formats: ["pdf"]` |
| Get alerted when a page changes visually (visual regression testing) | `compareWithPrevious: true` + an Apify schedule |
| Make thumbnails of every page of your site | `sitemapUrl`, `formats: ["jpeg"]`, `quality: 75` |
| Capture a single chart, pricing table or widget | `selector: ".pricing-table"` |
| Create link-preview / Open Graph images | `device: "og_card"` (1200×630) |

Ready-made examples: [Full-page PNG](https://apify.com/rigel/website-screenshot-pdf/examples/full-page-website-screenshot) · [iPhone view](https://apify.com/rigel/website-screenshot-pdf/examples/mobile-screenshot-iphone) · [Bulk URL to A4 PDF](https://apify.com/rigel/website-screenshot-pdf/examples/bulk-url-to-pdf-a4) · [HTML invoice to PDF](https://apify.com/rigel/website-screenshot-pdf/examples/html-to-pdf-invoice) · [Visual regression diff](https://apify.com/rigel/website-screenshot-pdf/examples/visual-regression-diff) · [Element screenshot](https://apify.com/rigel/website-screenshot-pdf/examples/element-screenshot-css-selector) · [Sitemap thumbnails](https://apify.com/rigel/website-screenshot-pdf/examples/sitemap-bulk-screenshots) · [Open Graph image](https://apify.com/rigel/website-screenshot-pdf/examples/open-graph-image-1200x630)

### Pricing

Pay per event. Compute is included: there is no separate charge for CPU or memory.

| Event | Price | When |
| --- | --- | --- |
| Actor start | $0.0005 per GB of run memory | Once per run. At the default 2 GB this is **$0.001**; at the 1 GB minimum, $0.0005. |
| File | **$0.002** | One PNG, JPEG, WebP or PDF stored. PNG + PDF of the same page = 2 files. |
| Visual diff | $0.001 | Only when a baseline already existed and a diff was computed. The first run, which creates the baseline, is not charged for a diff. |

**Not charged:** invalid URLs, blocked domains, private addresses, DNS or connection errors, HTTP 4xx/5xx (unless you turn on `captureErrorPages`), timeouts, missing selectors, non-HTML responses (PDF or ZIP downloads), duplicates, and URLs skipped after your spending limit is reached.

#### What a run costs (default 2 GB memory)

| Run | Files | Cost |
| --- | --- | --- |
| 1 URL, one PNG | 1 | $0.003 |
| 1 URL, PNG + PDF | 2 | $0.005 |
| One raw HTML invoice to PDF | 1 | $0.003 |
| 100 URLs, full-page PNG | 100 | $0.201 |
| 1,000 URLs to PDF | 1,000 | $2.001 |
| 1,000 URLs, PNG + PDF | 2,000 | $4.001 |
| 50 URLs checked daily with visual diff (after the first run) | 50 + 50 diffs | $0.151 per run, about $4.53 per month |

Set a **maximum cost per run** in Apify Console or with `maxTotalChargeUsd` in the API: when it is reached, the remaining URLs are returned as `skipped` and not charged.

### Input examples

All field names below are the real input fields of this Actor. Only one source is required: `urls`, `html`, `sitemapUrl` or `datasetId`.

**Full-page screenshot, desktop**

```json
{
  "urls": [{ "url": "https://en.wikipedia.org/wiki/Screenshot" }],
  "formats": ["png"],
  "fullPage": true,
  "device": "desktop"
}
```

**Mobile screenshot (iPhone 15, 393×852 at 3×)**

```json
{
  "urls": [{ "url": "https://www.wikipedia.org/" }],
  "formats": ["png"],
  "device": "iphone_15"
}
```

**Bulk URL to PDF, A4 with page numbers**

```json
{
  "urls": [
    { "url": "https://example.com/" },
    { "url": "https://en.wikipedia.org/wiki/PDF" },
    { "url": "https://docs.apify.com/platform/actors" }
  ],
  "formats": ["pdf"],
  "pdf": {
    "format": "A4",
    "landscape": false,
    "printBackground": true,
    "pageNumbers": true,
    "margin": { "top": "1cm", "right": "1cm", "bottom": "1.4cm", "left": "1cm" }
  }
}
```

**HTML to PDF (your own HTML, up to 2 MB)**

```json
{
  "html": "<!doctype html><html><body><h1>Invoice INV-001</h1><p>Total: $2.50</p></body></html>",
  "formats": ["pdf"],
  "pdf": { "format": "Letter", "pageNumbers": true }
}
```

**Visual regression: diff against the previous run**

```json
{
  "urls": [{ "url": "https://example.com/" }],
  "formats": ["png"],
  "compareWithPrevious": true,
  "baselineStoreName": "rigel-screenshot-baselines",
  "diffThreshold": 0.1
}
```

**Screenshots of a whole site from its sitemap**

```json
{
  "sitemapUrl": "https://docs.apify.com/sitemap.xml",
  "maxUrls": 50,
  "formats": ["jpeg"],
  "quality": 75,
  "device": "laptop"
}
```

**One element only, at 2× density**

```json
{
  "urls": [{ "url": "https://en.wikipedia.org/wiki/Portable_Network_Graphics" }],
  "formats": ["png"],
  "selector": ".infobox",
  "deviceScaleFactor": 2
}
```

Other useful fields: `width` / `height` / `deviceScaleFactor` to override a device, `clip` (`{x, y, width, height}`), `omitBackground` (transparent PNG/WebP), `waitUntil` (`load`, `domcontentloaded`, `networkidle`), `waitForSelector`, `delayMs`, `scrollToLoad`, `timeoutSecs` (per page, 5–90 s), `darkMode`, `hideCookieBanners`, `acceptCookies`, `blockAds`, `hideSelectors`, `blurSelectors`, `customCss`, `maxConcurrency` (1–8), `datasetId` + `urlField`.

### Output

Files go to the run's default key-value store. Key format: `<host>-<10-char hash of URL and options>.<ext>` (raw HTML: `html-<hash>.<ext>`). `OUTPUT` holds a copy of the first stored file and `RUN_SUMMARY.json` has counts, events and duration.

The dataset has one row per URL:

```json
{
  "url": "https://example.com/",
  "finalUrl": "https://example.com/",
  "status": "ok",
  "errorCode": null,
  "httpStatus": 200,
  "files": [
    {
      "format": "png",
      "key": "example.com-0b5df33ae2.png",
      "url": "https://api.apify.com/v2/key-value-stores/STORE_ID/records/example.com-0b5df33ae2.png?signature=…",
      "bytes": 78288,
      "width": 1920,
      "height": 1080,
      "truncated": false
    }
  ],
  "page": { "title": "Example Domain", "lang": "en", "loadMs": 119, "consoleErrors": 0 },
  "visualDiff": { "baselineFound": true, "percentChanged": 0, "changedPixels": 0, "diffKey": "diff-example.com-0b5df33ae2.png" },
  "charged": { "capture": 1, "visual-diff": 1 }
}
```

`files[].url` is a signed link that opens without your API token. PDFs have `pages` instead of `width`/`height`. `status` is `ok`, `failed`, `blocked` or `skipped`, with a stable `errorCode` (for example `NAVIGATION_TIMEOUT`, `HTTP_ERROR`, `SELECTOR_NOT_FOUND`, `BLOCKED_DOMAIN`). `visualDiff` is `null` unless `compareWithPrevious` is on. The dataset has two views: **Overview** and **Errors**.

### Use it from the API

Get your token in Apify Console › Settings › API & Integrations.

**cURL: get the file bytes in one call** (sync endpoint, returns the `OUTPUT` record)

```bash
curl -X POST "https://api.apify.com/v2/acts/rigel~website-screenshot-pdf/run-sync-get-output" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"urls":[{"url":"https://example.com"}],"formats":["pdf"],"pdf":{"format":"A4","pageNumbers":true}}' \
  --output page.pdf
```

**Python** (`pip install "apify-client>=3"`)

```python
import os
import requests
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("rigel/website-screenshot-pdf").call(run_input={
    "urls": [{"url": "https://example.com"}, {"url": "https://en.wikipedia.org/wiki/PDF"}],
    "formats": ["png", "pdf"],
    "fullPage": True,
})
for row in client.dataset(run.default_dataset_id).iterate_items():
    for f in row.get("files", []):
        with open(f["key"], "wb") as out:
            out.write(requests.get(f["url"], timeout=60).content)
        print(row["status"], f["key"], f["bytes"])
```

**JavaScript / Node.js** (`npm install apify-client`)

```js
import { ApifyClient } from 'apify-client';
import { writeFile } from 'node:fs/promises';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('rigel/website-screenshot-pdf').call({
    urls: [{ url: 'https://example.com' }],
    formats: ['png'],
    device: 'iphone_15',
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const row of items) {
    for (const f of row.files ?? []) {
        const res = await fetch(f.url);
        await writeFile(f.key, Buffer.from(await res.arrayBuffer()));
        console.log(row.status, f.key, f.bytes);
    }
}
```

### Use it from AI agents (MCP)

Add the Apify MCP server with only this Actor as a tool:

```json
{ "mcpServers": { "website-screenshot": { "url": "https://mcp.apify.com?tools=rigel/website-screenshot-pdf" } } }
```

or `claude mcp add --transport http website-screenshot "https://mcp.apify.com?tools=rigel/website-screenshot-pdf"`. Sign in with OAuth or send `Authorization: Bearer <APIFY_TOKEN>`. The agent passes the same input as above and reads `files[].url` from the result.

### n8n and Make

- **n8n**: Apify node › *Run an Actor* (`rigel/website-screenshot-pdf`, wait for finish) › Apify node › *Get dataset items* › *HTTP Request* on `files[0].url` to download the PNG or PDF. For visual regression, add an *IF* node on `visualDiff.percentChanged > 1` and send yourself an email or a Slack message.
- **Make**: Apify app › *Run an Actor* (synchronous) › *Get Dataset Items* › *HTTP › Get a file* on `files[].url`.
- **Schedules**: an Apify schedule on a saved task with `compareWithPrevious: true` gives you a daily visual check without n8n or Make.

Keep `cookies`, `headers` and `proxyUrl` out of logged steps: they are secret inputs.

### Related Actors

- [PDF to Markdown for RAG & LLMs](https://apify.com/rigel/doc-to-markdown): when a URL is a PDF, DOCX or other file (`NOT_A_WEB_PAGE`, not charged here), send it there to get Markdown or RAG chunks with page numbers.

### FAQ

**Do I pay for URLs that fail?** No. Only stored files and computed diffs are charged, plus the start event of the run.

**Can I take a full-page screenshot of a very long page?** Yes, up to 16,384 device pixels tall. Longer pages are cut and the file is flagged `truncated: true`. Lazy images are scrolled into view first for full-page captures.

**How do I convert HTML to PDF without hosting it?** Put the HTML string in `html` and set `formats: ["pdf"]`. CSS, web fonts and images referenced by public URLs are rendered. One HTML document per run.

**How does the visual diff work?** With `compareWithPrevious: true`, the PNG of each URL is compared pixel by pixel ([pixelmatch](https://github.com/mapbox/pixelmatch)) with the baseline stored by the previous run in the named key-value store `baselineStoreName` of your account, then the baseline is replaced. The diff image key is in `visualDiff.diffKey`. Changing the device or capture options creates a new baseline.

**Can it capture pages behind a login?** You can pass `cookies` and `headers` for your own site. They are sent only to the target origin, never to third parties or after a redirect to another origin, and never logged. You must have the right to access and capture the page.

**Can I use a proxy?** Yes, your own `http` or `socks5` proxy in `proxyUrl`. Apify Proxy is not used.

**How fast is it?** Pages run in parallel: 2 at the default 2 GB, 3 at 4 GB, or set `maxConcurrency` (1–8). A simple page takes about 1 second of browser time.

**How long are the files kept?** They live in the run's key-value store, which follows the data retention of your Apify plan. Download them or copy them to your own storage if you need them longer.

**Why was my URL refused?** Social and profile platforms (Facebook, Instagram, LinkedIn, TikTok, X, Reddit and others) are blocked, as well as private and loopback addresses. File downloads such as PDF links return `NOT_A_WEB_PAGE`, free of charge. To convert documents to text, use [rigel/doc-to-markdown](https://apify.com/rigel/doc-to-markdown).

**Zapier: my Zap times out.** Zapier's synchronous "Run Actor" action stops waiting after 30 seconds. For batches, run the Actor asynchronously and start the next step from Apify's "Finished Actor run" trigger, then read the results with the "Fetch dataset items" search.

### Limits

- 5,000 URLs per run (`maxUrls`), 2 MB of raw HTML, 8 KB of custom CSS.
- Per-page timeout 5–90 seconds (default 30).
- Full-page height capped at 16,384 device pixels.
- A browser crash is retried once, then returned as `BROWSER_CRASH`, free of charge.

### Legal and safety

You need the right to capture each page; the Actor does not decide that for you. It does not collect accounts, profiles or personal data, and it does not log page content, cookies or request headers. Social and profile platforms are blocked in code. Loopback, private (RFC 1918), link-local (including cloud metadata), CGNAT and IPv6 unique-local addresses are rejected for the page, its redirects and its subresources.

### Support

Open an issue on the **Issues** tab. Bug reports with the run ID get the fastest answer.

# Actor input Schema

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

Pages to capture. Only http and https. Credentials in the URL are rejected.

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

HTML document to render, up to 2 MB. Produces one result with keys html-<hash>.<ext>.

## `datasetId` (type: `string`):

Read URLs from an existing dataset.

## `urlField` (type: `string`):

Field that contains the URL in each dataset item.

## `sitemapUrl` (type: `string`):

sitemap.xml URL. Sitemap indexes and .xml.gz are followed, up to maxUrls.

## `maxUrls` (type: `integer`):

Upper bound on URLs plus the optional HTML document.

## `formats` (type: `array`):

One stored file per format. All formats come from a single page load.

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

Capture the full page, capped at 16384 device pixels. Sets truncated when the page is cut.

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

Viewport, device scale, user agent, and touch.

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

Override the profile width, in CSS pixels.

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

Override the profile height, in CSS pixels.

## `deviceScaleFactor` (type: `number`):

Override the profile pixel density.

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

Capture the first matching element instead of the viewport.

## `clip` (type: `object`):

Capture a rectangle in CSS pixels: {x, y, width, height}.

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

JPEG and WebP quality, from 1 to 100.

## `omitBackground` (type: `boolean`):

Transparent background for PNG and WebP.

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

Navigation lifecycle event to wait for.

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

Wait until this element is visible. Missing selectors are free and return SELECTOR_NOT_FOUND.

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

Pause after load, before the capture.

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

Scroll the page to trigger lazy images, then return to the top. Defaults to on for full-page captures.

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

Per-page budget for navigation and rendering.

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

Emulate prefers-color-scheme: dark.

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

Hide common consent managers with CSS. Does not click Accept.

## `acceptCookies` (type: `boolean`):

Click a recognised consent Accept button before hiding the banner.

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

Block requests to a curated list of ad and tracker domains.

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

CSS selectors to hide before the capture.

## `blurSelectors` (type: `array`):

CSS selectors to blur before the capture.

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

CSS injected before the capture. Maximum 8 KB.

## `pdf` (type: `object`):

Print options used when formats includes pdf. Defaults to A4, portrait, 1 cm margins, and print backgrounds.

## `compareWithPrevious` (type: `boolean`):

Diff the PNG against the baseline for the same URL and options. The first run only stores the baseline.

## `baselineStoreName` (type: `string`):

Named key-value store that keeps baseline PNGs.

## `diffThreshold` (type: `number`):

pixelmatch threshold from 0 (strict) to 1.

## `captureErrorPages` (type: `boolean`):

Store a capture of HTTP 4xx and 5xx responses. Those files are billed. Otherwise HTTP errors are free.

## `cookies` (type: `array`):

First-party cookies. Sent only to the target origin, never logged.

## `headers` (type: `object`):

Extra request headers. Sent only to the target origin, never after a redirect to another origin, and never to third-party subresources. Put cookies in the cookies field. Never logged.

## `proxyUrl` (type: `string`):

Your own http or socks5 proxy, used for cleartext HTTP and for HTTPS. The host must be a public address. Apify Proxy is rejected, including its published IP addresses.

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

Parallel pages. Leave empty to derive it from run memory.

## Actor input object example

```json
{
  "urls": [
    {
      "url": "https://example.com"
    }
  ],
  "urlField": "url",
  "sitemapUrl": "https://example.com/sitemap.xml",
  "maxUrls": 100,
  "formats": [
    "png",
    "pdf"
  ],
  "fullPage": false,
  "device": "desktop",
  "width": 1280,
  "height": 720,
  "deviceScaleFactor": 2,
  "selector": "article",
  "clip": {
    "x": 0,
    "y": 0,
    "width": 800,
    "height": 600
  },
  "quality": 80,
  "omitBackground": false,
  "waitUntil": "load",
  "delayMs": 500,
  "timeoutSecs": 30,
  "darkMode": false,
  "hideCookieBanners": true,
  "acceptCookies": false,
  "blockAds": true,
  "hideSelectors": [
    ".newsletter-modal"
  ],
  "blurSelectors": [
    ".account-email"
  ],
  "pdf": {
    "format": "A4",
    "landscape": false,
    "margin": {
      "top": "1cm",
      "right": "1cm",
      "bottom": "1cm",
      "left": "1cm"
    },
    "printBackground": true,
    "scale": 1,
    "pageNumbers": true
  },
  "compareWithPrevious": false,
  "baselineStoreName": "rigel-screenshot-baselines",
  "diffThreshold": 0.1,
  "captureErrorPages": false,
  "cookies": [
    {
      "name": "session",
      "value": "replace-me"
    }
  ],
  "headers": {
    "Authorization": "Bearer replace-me"
  },
  "proxyUrl": "http://proxy.example.com:8080"
}
```

# Actor output Schema

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

Default dataset. One row per URL or HTML document, with status, signed file URLs, page metadata, and charged events.

## `file` (type: `string`):

OUTPUT record in the key-value store: the first PNG, JPEG, WebP, or PDF stored in the run. Useful for run-sync-get-output.

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

Counts by status, charged events, and duration. No page content.

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

Key-value store keys for every capture and visual-diff PNG written during the run.

# 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": [
        {
            "url": "https://example.com"
        }
    ],
    "urlField": "url",
    "maxUrls": 100,
    "formats": [
        "png"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("rigel/website-screenshot-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

```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": [{ "url": "https://example.com" }],
    "urlField": "url",
    "maxUrls": 100,
    "formats": ["png"],
}

# Run the Actor and wait for it to finish
run = client.actor("rigel/website-screenshot-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

```bash
echo '{
  "urls": [
    {
      "url": "https://example.com"
    }
  ],
  "urlField": "url",
  "maxUrls": 100,
  "formats": [
    "png"
  ]
}' |
apify call rigel/website-screenshot-pdf --silent --output-dataset

```

## MCP server setup

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