# Website Screenshot & PDF Generator (`thriving_adder/website-screenshot-pdf`) Actor

Batch full-page screenshots (PNG/JPEG) and PDFs of public web pages, with mobile/desktop presets and cookie-banner hiding. Pay per screenshot.

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

## Pricing

from $2.00 / 1,000 screenshot captureds

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 & PDF Generator

Capture **full-page screenshots (PNG/JPEG) and PDFs** of any public web page, one URL or thousands. Choose desktop, laptop, tablet or mobile. Cookie-consent popups are hidden automatically. You pay only per successful capture.

### What does it do?

- Takes a screenshot and/or a PDF of each URL you provide.
- Full-page or viewport-only captures, with device presets or a custom size.
- Hides common cookie banners with CSS. It **never clicks "Accept"**. You can also hide any element with your own CSS selectors.
- Optionally scrolls the page first so lazy-loaded images appear.
- Very tall pages are clipped at a safe height (10,000 px by default, adjustable) and flagged; if a capture still times out, the Actor falls back once to the top 4,000 px (flagged) instead of failing. Timeouts are not retried, so slow pages fail fast.
- Returns a table with each page's final URL, HTTP status, title and a link to each file.

### What data does it collect?

Only what you ask for: an image or PDF of each page you list, plus that page's URL, HTTP status code and `<title>`. It does not extract contact details or personal data, and it does not log in anywhere. Login-protected pages, `localhost` and private-network addresses are rejected, and the browser is blocked from loading anything from private networks. By default it **respects robots.txt**: URLs a site disallows for automated agents are skipped and not charged.

**You are responsible for the URLs you submit.** Use only pages you are allowed to capture, and respect each website's terms. If a page shows personal data, the capture will contain it, so handle such files under the privacy laws that apply to you (GDPR, PDPA, etc.).

### How much does it cost?

| Event | Price |
|---|---|
| Screenshot (PNG or JPEG), per page | $0.002 |
| PDF, per page | $0.0025 |

Apify also adds its standard tiny start fee (about $0.00005 per run per GB of memory). For example, 1,000 full-page PNGs cost about $2.00. Pages that fail after retries, rejected URLs and robots.txt skips are **not charged**; each shows up in the **Errors (not charged)** view with the reason. Set "Maximum cost per run" in the run options: the Actor never starts a capture it cannot bill within your limit, and stops cleanly when the limit is reached.

### Input example

```json
{
  "urls": [{ "url": "https://example.com" }, { "url": "https://www.wikipedia.org" }],
  "outputFormats": ["png", "pdf"],
  "viewport": "mobile",
  "fullPage": true,
  "hideCookieBanners": true
}
```

### Output example

```json
{
  "startUrl": "https://example.com",
  "url": "https://example.com/",
  "statusCode": 200,
  "title": "Example Domain",
  "viewport": "390x844",
  "heightTruncated": false,
  "fullPage": true,
  "takenAt": "2026-10-26T07:48:19.165Z",
  "pngUrl": "https://api.apify.com/v2/key-value-stores/<id>/records/png_b559c7edd3fb6737",
  "pngBytes": 56984,
  "pdfUrl": "https://api.apify.com/v2/key-value-stores/<id>/records/pdf_b559c7edd3fb6737",
  "pdfBytes": 112866
}
```

The files are stored in the run's key-value store. Download them from the links, or through the API, integrations (Zapier, Make, Google Drive) or webhooks.

### Use cases

- Visual archives and before/after records of your own websites.
- Batch PDFs of documentation, articles or reports for offline reading.
- Mobile vs desktop QA checks for landing pages.
- Visual input for AI agents: call it through Apify's MCP server or API.

### Tips

- For single-page apps, set `waitUntil` to `networkidle` or add `delayMs`.
- Use `hideSelectors` to hide chat widgets or sticky headers.
- Datacenter proxy is optional. Most public pages need no proxy.
- Mobile and tablet presets render at 2x pixel density (a 390 px wide mobile page gives a 780 px wide image).

### FAQ

**Is it legal?** Taking a screenshot of a public page is generally fine, but the copyright in the page's content stays with its owner, and some sites restrict automated access in their terms. Check before you capture at scale, and consult a lawyer if unsure.

**Something broke?** Open an issue in the Issues tab with the URL and your input. We answer within 2 business days.

# Actor input Schema

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

Public web pages to capture (max 10,000 per run). Login-protected, localhost and private-network URLs are rejected and not charged.

## `outputFormats` (type: `array`):

Each format is charged as one result.

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

Capture the whole scrollable page instead of only the viewport.

## `maxPageHeightPx` (type: `integer`):

Very tall pages are clipped at this height (flagged as heightTruncated) to avoid timeouts and out-of-memory errors. If a full-page capture still times out, the Actor falls back once to the top 4,000 px (flagged with 'fallback').

## `viewport` (type: `string`):

Viewport preset.

## `viewportWidth` (type: `integer`):

Overrides preset width.

## `viewportHeight` (type: `integer`):

Overrides preset height.

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

Navigation event to wait for.

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

Wait after load before capture.

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

Scroll through the page first so lazy-loaded images render.

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

Hides common consent popups with CSS. Never clicks Accept.

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

Extra elements to hide (chat widgets, ads...).

## `jpegQuality` (type: `integer`):

Only for JPEG.

## `pdfFormat` (type: `string`):

Only for PDF.

## `pdfPrintBackground` (type: `boolean`):

Only for PDF.

## `respectRobotsTxt` (type: `boolean`):

Skip (and do not charge for) URLs that the site's robots.txt disallows for automated agents. Turn off only for sites you own or have permission to capture.

## `navigationTimeoutSecs` (type: `integer`):

Per page.

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

Parallel pages.

## `maxRequestRetries` (type: `integer`):

Retries per failed page for non-timeout errors (failed pages are not charged). Timeouts are not retried.

## `proxyConfiguration` (type: `object`):

Optional. Datacenter proxy is usually enough.

## Actor input object example

```json
{
  "urls": [
    {
      "url": "https://apify.com"
    }
  ],
  "outputFormats": [
    "png"
  ],
  "fullPage": true,
  "maxPageHeightPx": 10000,
  "viewport": "desktop",
  "waitUntil": "load",
  "delayMs": 0,
  "scrollToBottom": false,
  "hideCookieBanners": true,
  "hideSelectors": [],
  "jpegQuality": 80,
  "pdfFormat": "A4",
  "pdfPrintBackground": true,
  "respectRobotsTxt": true,
  "navigationTimeoutSecs": 45,
  "maxConcurrency": 5,
  "maxRequestRetries": 1,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

One row per URL with status, title and links to the PNG/JPEG/PDF files.

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

The screenshot and PDF files themselves (keys png\_*, jpeg\_*, pdf\_\*).

# 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://apify.com"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("thriving_adder/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://apify.com" }] }

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

```

## MCP server setup

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