# Website Screenshot & PDF API (`noclat/website-screenshot-pdf`) Actor

Render any public page in a real browser and get a screenshot or an A4 PDF back. Full page or viewport, desktop to mobile presets, retina, dark mode, ads blocked and consent overlays hidden so the image shows the page, not a cookie wall.

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

## Pricing

from $8.00 / 1,000 captures

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 API

Render any public page in a **real browser** and get back a **screenshot**, an **A4 PDF**, or both. Give it a list of URLs; it returns a direct link to every file plus the page title, final URL and HTTP status.

Typical uses: link previews and Open Graph images, visual regression and uptime checks, archiving a page as a PDF, thumbnails for a directory or a marketplace, design and competitor research, and AI agents that need to *see* a page rather than read its markup.

### What makes a screenshot usable

Most screenshot tools hand you a picture of a cookie wall. This one is built around the things that actually ruin captures:

- **Consent and cookie overlays are hidden**, two ways. A list covers the usual managers (OneTrust, Cookiebot, Usercentrics, Didomi, Osano, Quantcast, Sourcepoint, HubSpot), and a detector catches the bespoke ones every publisher writes: an element is hidden only when it is pinned to the viewport, large, stacked above the page, and either reads like a consent notice or embeds a known consent frame. That wording test is what keeps a hero banner or a sticky header on screen. They are hidden with CSS, never clicked, so nothing is consented to on anyone's behalf.
- **Lazy-loaded images are rendered.** A full-page capture scrolls through the whole document first, then returns to the top, so the image is not half placeholders.
- **Ads and trackers are blocked**, which removes the flashing boxes and makes pages load faster.
- **Late overlays are caught**, because the hiding rules are applied again after scrolling.
- **Dark mode** is a real system-level emulation, not a CSS filter, so the page renders the theme its author wrote.

### Input

```json
{
    "urls": ["https://stripe.com", "https://vercel.com"],
    "screenshot": true,
    "pdf": false,
    "fullPage": true,
    "device": "desktop",
    "deviceScaleFactor": 2,
    "darkMode": false,
    "hideCookieBanners": true
}
```

| Option | What it does |
| --- | --- |
| `urls` | Pages to render, one capture each |
| `screenshot`, `pdf` | Either or both; at least one must be on |
| `imageFormat`, `quality` | PNG for interfaces, JPEG for photo-heavy pages |
| `fullPage` | Whole document, or just the viewport |
| `device` | Desktop 1920x1080, Laptop 1440x900, Tablet 820x1180, Mobile 390x844, or Custom |
| `width`, `height`, `deviceScaleFactor` | Your own viewport; density 2 gives a retina image |
| `darkMode` | Render as a visitor whose system is set to dark |
| `hideCookieBanners`, `hideSelectors` | Hide consent overlays and anything else you name |
| `blockAds` | Block the usual ad and analytics hosts |
| `waitUntil`, `waitForSelector`, `delaySecs` | Control when the page is considered ready |
| `timeoutSecs` | Give up on a page after this long |

### Output example

```json
{
    "url": "https://stripe.com",
    "finalUrl": "https://stripe.com/",
    "status": 200,
    "title": "Stripe | Financial Infrastructure to Grow Your Revenue",
    "device": "desktop",
    "viewportWidth": 1920,
    "viewportHeight": 1080,
    "fullPage": true,
    "darkMode": false,
    "screenshotUrl": "https://api.apify.com/v2/key-value-stores/.../records/0001-stripe-com.png?signature=...",
    "pdfUrl": null,
    "imageFormat": "png",
    "loadTimeMs": 4120,
    "error": null,
    "capturedAt": "2026-09-21T20:40:00.000Z"
}
```

`screenshotUrl` and `pdfUrl` are **signed links**: they open in a browser, an `<img>` tag, a report or an agent's next step without an Apify token. A URL that could not be rendered still appears in the output, with the reason in `error`, and is not charged as a capture.

### Pricing

Pay per event: **$0.005 per run plus $0.008 per capture**, and the browser time is on us. A page that fails to render is not charged as a capture. Ten captures in one run cost about nine cents. Rendering a page in a real browser is not free compute, and this price covers it rather than passing you a separate usage bill at the end of the month.

### Using it from an AI agent or via API

An agent that has to judge a page, a layout or a design needs pixels, not HTML. Call this Actor with a URL, read `screenshotUrl` from the dataset, and pass the image straight into a vision model. It works through the [Apify API](https://docs.apify.com/api/v2), the [Apify MCP server](https://mcp.apify.com) or any Apify client.

### Legal and data policy

This Actor renders the URLs you give it, as an ordinary browser would, and stores the resulting files in your own run storage. It does not log in, does not bypass paywalls or bot protection, and collects no personal data. You are responsible for having the right to capture and reuse the pages you submit.

### More tools

Same approach, same output discipline:

- **[ATS Jobs Scraper](https://apify.com/noclat/ats-jobs-scraper)** — every open role from any company’s Greenhouse, Lever or Ashby job board.
- **[Sitemap & llms.txt URL Extractor](https://apify.com/noclat/sitemap-llms-txt-extractor)** — every URL a website publishes, from robots.txt, all sitemaps and llms.txt.

### FAQ

**The capture is a cookie wall anyway.** Add the overlay's selector to `hideSelectors`. Send the URL in the Issues tab too and the built-in list gets that site added.

**The page is blank or half loaded.** Set `waitUntil` to Network idle, or wait for a specific element with `waitForSelector`, or add a couple of seconds with `delaySecs`.

**Can I capture a page behind a login?** No. This Actor renders public pages only.

**How big can a full-page capture be?** Very tall pages produce very large PNGs. Switch `imageFormat` to JPEG, or turn `fullPage` off, if size matters more than fidelity.

# Actor input Schema

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

Pages to render. One capture is produced per URL.

## `screenshot` (type: `boolean`):

Produce an image of the page.

## `pdf` (type: `boolean`):

Produce an A4 PDF of the page, printed with backgrounds.

## `imageFormat` (type: `string`):

PNG is lossless and best for interfaces. JPEG is much smaller for photo-heavy pages.

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

1 to 100. Ignored for PNG.

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

Capture the whole document, scrolling through it first so lazy-loaded images appear. Turn off to capture only the viewport.

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

Viewport preset. Choose Custom to set your own width and height.

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

Overrides the preset width.

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

Overrides the preset height. With Full page on, this is only the starting window.

## `deviceScaleFactor` (type: `integer`):

2 gives a retina-quality image at twice the pixels.

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

Render the page as a visitor whose system is set to dark.

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

Hides the usual consent, cookie and newsletter overlays so the image shows the page. They are hidden, never clicked, so nothing is consented to.

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

CSS selectors to hide before capturing, for example a chat bubble or a sticky header.

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

Blocks the usual ad and analytics hosts, which makes pages load faster and look cleaner.

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

When to consider the page ready. Network idle is the safest for heavy apps and the slowest.

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

Wait for this CSS selector before capturing. The capture still happens if it never appears.

## `delaySecs` (type: `integer`):

Wait this long after the page is ready, for animations to settle.

## `maxRunMinutes` (type: `integer`):

A safety net for long lists of slow pages. The run stops cleanly and reports what it captured.

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

Give up on a page after this long. Capped at 90 seconds.

## Actor input object example

```json
{
  "urls": [
    "https://apify.com",
    "https://stripe.com"
  ],
  "screenshot": true,
  "pdf": false,
  "imageFormat": "png",
  "quality": 85,
  "fullPage": true,
  "device": "desktop",
  "darkMode": false,
  "hideCookieBanners": true,
  "blockAds": true,
  "waitUntil": "load",
  "maxRunMinutes": 15,
  "timeoutSecs": 45
}
```

# 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

```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://apify.com",
        "https://stripe.com"
    ]
};

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

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

```

## MCP server setup

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