# Website Screenshot API & URL to PDF Converter (`cyborg_cell/website-screenshot-pdf`) Actor

Website screenshot API and URL to PDF converter. Capture any web page as PNG, JPEG or PDF: full-page with lazy-load scrolling, mobile and retina modes, hidden cookie banners, wait for elements. Bulk URLs, public file links.

- **URL**: https://apify.com/cyborg_cell/website-screenshot-pdf.md
- **Developed by:** [Aditya Sapra](https://apify.com/cyborg_cell) (community)
- **Categories:** Developer tools, Automation
- **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 or pdfs

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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** turns any list of web addresses into clean screenshots or PDFs, each with a **public link to the file**. It is a screenshot API and URL to PDF converter in one, built for monitoring, reports, link previews, archiving and design review.

It uses a real Chrome browser, so pages look the way a visitor sees them: scripts run, fonts load, lazy images appear.

### What is it good for?

- **Monitoring and archiving**: capture pages on a schedule and compare them over time.
- **Reports and decks**: full-page screenshots and PDFs of any public page, in bulk.
- **Link previews and thumbnails**: desktop, mobile and retina captures.
- **QA and design review**: see how a page looks on a phone or in dark mode.

### Try it in 30 seconds

1. Press **Start**: the input is prefilled with real examples.
2. Open the **Output** tab and download JSON, CSV or Excel.
3. Replace the examples with your own and run again. You pay about **$2.00 per 1,000 pages**.

#### A taste of the output

| Page | Result | Format | Size |
|---|---|---|---|
| Wikipedia | captured | png | 123 KB |

The full record has more fields; see the example output further down.

### What does Website Screenshot API do?

- **PNG, JPEG or PDF** for every address, with a public link to the file in the results
- **Full-page screenshots** with automatic scrolling, so lazy-loaded images are not blank (pages are cut at 20,000 px)
- **Mobile and tablet** modes with real device profiles, **retina** (2x, 3x) and **dark mode**
- **Cookie banners hidden** (best effort) and your own CSS selectors to hide chat widgets or promo bars
- **Wait for an element** or a fixed delay before capturing, for charts and animations
- **Batch input**: hundreds of addresses in one run, several captured in parallel
- Page title, final address after redirects, HTTP status and file size in every result

### How do I take a screenshot of a website?

1. Paste addresses, one per line (`example.com` works as well as `https://example.com`).
2. Pick the format and options, then run it.
3. Open the **Captures** table for the links, or read the results through the API.

#### How do I convert a URL or webpage to PDF?

Set the format to **PDF**. Pick the paper size (A4 or Letter) and portrait or landscape; long pages paginate normally.

#### How do I take a full page screenshot of a website?

Turn on **Full page**. The Actor scrolls through the page first so lazy-loaded images and sections are rendered before the capture.

#### Example input

```json
{
  "urls": ["https://example.com", "https://www.wikipedia.org"],
  "format": "png",
  "fullPage": true,
  "device": "desktop",
  "deviceScaleFactor": 2,
  "hideCookieBanners": true
}
```

#### What does the output look like?

One record per address:

```json
{
  "url": "https://www.wikipedia.org",
  "finalUrl": "https://www.wikipedia.org/",
  "title": "Wikipedia",
  "httpStatus": 200,
  "format": "png",
  "device": "desktop",
  "fullPage": false,
  "fileUrl": "file:///Users/adityasapra/Library/Application%20Support/Claude/scratch-workspaces/e31d7d78-5186-4a87-a5ef-20d108034ba8/bf94f31b-4d5c-45a6-8bd2-bde9e516ef80/scratch-2026-10-04-194370/portfolio/build/website-screenshot-pdf/storage/key_value_stores/default/capture-76f543ed53b5.png",
  "fileKey": "capture-76f543ed53b5.png",
  "bytes": 126437,
  "pageHeight": 1104,
  "status": "ok",
  "error": null
}
```

`fileUrl` is a link to the finished file. Files are stored in the run's storage, so they stay available as long as your Apify storage retention allows.

### How much does it cost to take screenshots?

You pay per page captured: **$0.002 per screenshot or PDF, about $2.00 per 1,000 pages**, plus a tiny fixed fee per run. Apify bills the platform compute on top (the Actor starts with 2 GB of memory, which suits most pages; heavy pages use more compute). The run also stops if it reaches the maximum charge you set in the run options. The Pricing tab always shows the current rate.

#### Am I charged for failed pages?

No. You are charged **only for pages that were captured**. Addresses that fail (unreachable, blocked, timed out) or answer with an error page (404, 500) are reported with the reason and **not charged**. Turn on *Capture error pages* if you want those captured too.

### How do I call the screenshot API from code?

Yes. Like every Apify Actor it can be started from code, scheduled in the Apify Console, or connected to Make, Zapier, n8n, Google Sheets and webhooks through Apify integrations, for example to capture a page every day and compare the results.

**Python**

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")
run_input = {
    "urls": [
        "https://example.com"
    ],
    "format": "png",
    "fullPage": True
}
run = client.actor("cyborg_cell/website-screenshot-pdf").call(run_input=run_input)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

**JavaScript**

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_API_TOKEN>' });
const input = {
  "urls": [
    "https://example.com"
  ],
  "format": "png",
  "fullPage": true
};
const run = await client.actor('cyborg_cell/website-screenshot-pdf').call(input);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

**cURL**

```bash
curl -X POST "https://api.apify.com/v2/acts/cyborg_cell~website-screenshot-pdf/run-sync-get-dataset-items?token=<YOUR_API_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"urls": ["https://example.com"], "format": "png", "fullPage": true}'
```

### FAQ

#### Can it capture pages behind a login?

No. **Public pages only.** Pages behind a login are not supported, and addresses that point to private or internal networks (`localhost`, `192.168.x.x`, cloud metadata addresses, `.local` names) are refused.

#### What about sites that block automated browsers?

Some sites block automated browsers or show a bot check. Those pages may come back as a blocked-page screenshot or fail; this Actor does not try to bypass such protection.

#### Does it hide cookie banners?

It covers the most common consent tools. An unusual banner may remain: add its selector under *Also hide these elements*.

#### Is there a size limit for full-page screenshots?

Very long pages are cut at 20,000 px tall in full-page image mode. PDFs paginate normally.

#### Is it allowed to capture any website?

Capture only pages you are allowed to capture, and respect the terms of the sites you capture. The Actor opens each page once and keeps nothing besides the files it produces for you.

#### A page renders wrongly, or I need an option that is missing. What now?

Open an issue on the Actor page with the address and we will look at it.

### Other Actors by the same author

- [ATS Job Scraper (Greenhouse, Lever, Ashby, Workday and four more platforms)](https://apify.com/cyborg_cell/ats-job-listings-api) and [Remote Jobs Scraper (RemoteOK, Himalayas, Jobicy, Arbeitnow)](https://apify.com/cyborg_cell/remote-jobs-aggregator): structured job data from company career pages and remote job boards.
- Also by the same author: [Email Validator](https://apify.com/cyborg_cell/email-validator), [YouTube Transcript Scraper](https://apify.com/cyborg_cell/youtube-transcript-scraper).

# Actor input Schema

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

One per line. `example.com` works as well as `https://example.com`. Only public http(s) pages are captured.

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

Image or PDF.

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

Capture the whole scrollable page instead of just the first screen. Pages taller than 20,000 px are cut at that height.

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

Mobile and tablet use a real device profile (screen size, touch, user agent).

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

Desktop only.

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

Desktop only.

## `deviceScaleFactor` (type: `string`):

2x gives sharper images (and bigger files).

## `colorScheme` (type: `string`):

Asks the page for its light or dark theme.

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

Hides the most common cookie-consent pop-ups before capturing. Best effort: unusual banners may remain.

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

CSS selectors of anything else to hide, such as chat widgets or promo bars (for example `#chat-widget`, `.promo-bar`).

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

CSS selector the page must show before capturing (for example `#main-chart`).

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

When the page counts as ready.

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

Extra wait after the page is ready, for animations.

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

For full-page images and PDFs: scrolls down first so lazy-loaded images appear.

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

Only for JPEG output.

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

Only for PDF output.

## `pdfLandscape` (type: `boolean`):

Only for PDF output.

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

By default pages that answer with an error (404, 500, ...) are reported as failed and not charged. Turn on to capture them anyway.

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

Give up on a page after this long.

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

How many pages are captured in parallel.

## Actor input object example

```json
{
  "urls": [
    "https://example.com",
    "https://www.wikipedia.org"
  ],
  "format": "png",
  "fullPage": false,
  "device": "desktop",
  "viewportWidth": 1280,
  "viewportHeight": 800,
  "deviceScaleFactor": "1",
  "colorScheme": "light",
  "hideCookieBanners": true,
  "waitUntil": "load",
  "delayMs": 0,
  "scrollToLoad": true,
  "jpegQuality": 80,
  "pdfFormat": "A4",
  "pdfLandscape": false,
  "captureErrorPages": false,
  "timeoutSecs": 45,
  "maxConcurrency": 3
}
```

# Actor output Schema

## `captures` (type: `string`):

One record per page, with the link to its screenshot or PDF.

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

How many pages were captured or failed.

# 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://example.com",
        "https://www.wikipedia.org"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("cyborg_cell/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://example.com",
        "https://www.wikipedia.org",
    ] }

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

```

## MCP server setup

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