# Website Screenshot & PDF API — Fast Captures (`george.the.developer/screenshot-pdf-api`) Actor

Capture pixel-perfect screenshots and PDFs from any URL in under 3 seconds. PNG/JPEG/WebP formats, custom viewports, full-page capture, batch up to 20 URLs.

- **URL**: https://apify.com/george.the.developer/screenshot-pdf-api.md
- **Developed by:** [George Kioko](https://apify.com/george.the.developer) (community)
- **Categories:** Marketing, Lead generation
- **Features:** Limited permissions, Single-tenant, Server interface
- **Stats:** 24 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 screenshot captures

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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](#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 — Pixel-Perfect Captures in Under 3 Seconds

> **The fastest screenshot API on the market.** Capture any webpage as PNG, JPEG, WebP, or PDF with sub-3-second delivery. Competitors take 6-21 seconds. We deliver in 1-2 seconds.

***

### Architecture Overview

```mermaid
flowchart TB
    subgraph Client["Your Application"]
        REQ["HTTP Request"]
    end

    subgraph API["Screenshot & PDF API"]
        ROUTER["Request Router"]
        VALIDATE["Input Validation"]
        CACHE["10-min LRU Cache"]
        BROWSER["Pre-Warmed Puppeteer<br/>Chromium Browser"]
        RENDER["Page Renderer"]
        FORMAT["Output Formatter"]
        CHARGE["PPE Billing"]
    end

    subgraph Output["Response"]
        BIN["Binary Image/PDF"]
        B64["Base64 JSON"]
    end

    REQ --> ROUTER
    ROUTER -->|"/screenshot"| VALIDATE
    ROUTER -->|"/pdf"| VALIDATE
    ROUTER -->|"/batch"| VALIDATE
    VALIDATE --> CACHE

    CACHE -->|"Hit"| FORMAT
    CACHE -->|"Miss"| BROWSER
    BROWSER --> RENDER --> FORMAT
    FORMAT --> CHARGE
    CHARGE --> BIN & B64

    style Client fill:#1a1a2e,color:#fff
    style API fill:#16213e,color:#fff
    style Output fill:#533483,color:#fff
```

***

### Performance Comparison

```mermaid
gantt
    title Screenshot Latency Comparison (lower is better)
    dateFormat X
    axisFormat %s seconds

    section This API
    Screenshot (2.1s)     :done, 0, 2100
    PDF (1.2s)            :done, 0, 1200

    section Competitor A
    Screenshot (8.4s)     :crit, 0, 8400

    section Competitor B
    Screenshot (14.2s)    :crit, 0, 14200

    section Competitor C
    Screenshot (21s)      :crit, 0, 21000
```

| Metric | **This API** | Competitor Avg |
|--------|-------------|---------------|
| Screenshot latency | **2.1 seconds** | 14.5 seconds |
| PDF latency | **1.2 seconds** | 8.3 seconds |
| Uptime | **100%** | 74-94% |
| Formats | **PNG, JPEG, WebP, PDF** | PNG only |
| Batch support | **20 URLs per call** | None |
| Full-page capture | **Yes** | Limited |

***

### Request Flow

```mermaid
sequenceDiagram
    participant App as Your App
    participant API as Screenshot API
    participant Cache as LRU Cache
    participant Chrome as Puppeteer Chrome

    App->>API: GET /screenshot?url=github.com&width=1280
    API->>Cache: Lookup (url + params hash)

    alt Cache Hit (within 10 min)
        Cache-->>API: Cached screenshot
        API-->>App: Image binary (instant)
    else Cache Miss
        API->>Chrome: Create new page
        Chrome->>Chrome: Set viewport (1280x720)
        Chrome->>Chrome: Navigate to URL
        Chrome->>Chrome: Wait for networkidle2
        Chrome-->>API: Screenshot buffer
        API->>Cache: Store screenshot
        API->>API: Actor.charge($0.005)
        API-->>App: Image binary (~2.1s)
    end
```

***

### API Endpoints

#### `GET /screenshot` — Capture webpage

```
GET /screenshot?url=https://github.com&width=1920&height=1080&format=png&fullPage=true
```

| Parameter | Type | Default | Range | Description |
|-----------|------|---------|-------|-------------|
| `url` | string | *required* | — | URL to capture |
| `width` | number | 1280 | 320-3840 | Viewport width in pixels |
| `height` | number | 720 | 200-2160 | Viewport height in pixels |
| `format` | string | png | png, jpeg, webp | Image format |
| `fullPage` | boolean | false | — | Capture full scrollable page |
| `quality` | number | 80 | 1-100 | Compression (jpeg/webp only) |
| `delay` | number | 0 | 0-10000 | Wait ms before capture |

#### `GET /pdf` — Generate PDF

```
GET /pdf?url=https://github.com&format=A4&landscape=false
```

| Parameter | Type | Default | Options | Description |
|-----------|------|---------|---------|-------------|
| `url` | string | *required* | — | URL to convert |
| `format` | string | A4 | A4, Letter, Legal | Paper size |
| `landscape` | boolean | false | — | Landscape orientation |
| `printBackground` | boolean | true | — | Include backgrounds |

#### `POST /batch` — Batch screenshots

```json
POST /batch
{
  "urls": [
    "https://google.com",
    "https://github.com",
    "https://apple.com"
  ],
  "width": 1280,
  "height": 720,
  "format": "jpeg"
}
```

***

### Output Formats

#### Binary (Default)

Returns raw bytes with headers:

```
Content-Type: image/png (or image/jpeg, image/webp, application/pdf)
Content-Length: 15856
X-Latency-Ms: 2172
X-From-Cache: false
```

#### Base64 JSON

Send header `Accept: application/json` to get:

```json
{
  "base64": "iVBORw0KGgoAAAANSUhEUgAABQ...",
  "mimeType": "image/png",
  "size": 15856,
  "latencyMs": 2172,
  "fromCache": false,
  "url": "https://github.com"
}
```

#### Batch Response

```json
{
  "count": 3,
  "succeeded": 3,
  "failed": 0,
  "latencyMs": 4521,
  "results": [
    { "url": "https://google.com", "base64": "...", "mimeType": "image/jpeg", "size": 12340 },
    { "url": "https://github.com", "base64": "...", "mimeType": "image/jpeg", "size": 45678 },
    { "url": "https://apple.com", "base64": "...", "mimeType": "image/jpeg", "size": 23456 }
  ]
}
```

***

### Use Case Workflows

#### Visual QA Testing Pipeline

```mermaid
flowchart LR
    DEPLOY["New Deployment"] --> URLS["Page URL List"]
    URLS --> BATCH["Screenshot API<br/>POST /batch"]
    BATCH --> COMPARE["Visual Diff<br/>Engine"]
    COMPARE --> PASS["All Match?"]
    PASS -->|Yes| OK["Deploy to Prod"]
    PASS -->|No| ALERT["Alert QA Team<br/>+ Diff Report"]

    style BATCH fill:#10b981,color:#fff
    style OK fill:#3b82f6,color:#fff
    style ALERT fill:#ef4444,color:#fff
```

#### Social Media Preview Generator

```mermaid
flowchart LR
    BLOG["New Blog Post<br/>Published"] --> SCREEN["Screenshot API<br/>GET /screenshot"]
    SCREEN --> THUMB["1200x630<br/>OG Image"]
    THUMB --> TWITTER["Twitter Card"]
    THUMB --> LINKEDIN["LinkedIn Preview"]
    THUMB --> FACEBOOK["Facebook Share"]

    style SCREEN fill:#10b981,color:#fff
```

#### Competitive Price Monitoring

```mermaid
flowchart LR
    SCHEDULE["Daily Cron Job"] --> URLS["Competitor<br/>Product Pages"]
    URLS --> SCREEN["Screenshot API<br/>POST /batch"]
    SCREEN --> ARCHIVE["Screenshot<br/>Archive"]
    ARCHIVE --> COMPARE["Price Change<br/>Detection"]
    COMPARE --> ALERT["Slack Alert:<br/>Price Changed!"]

    style SCREEN fill:#10b981,color:#fff
    style ALERT fill:#f59e0b,color:#fff
```

#### PDF Report Generation

```mermaid
flowchart LR
    DASH["Web Dashboard<br/>URL"] --> PDF["Screenshot API<br/>GET /pdf"]
    PDF --> EMAIL["Email PDF<br/>to Stakeholders"]
    PDF --> DRIVE["Save to<br/>Google Drive"]
    PDF --> ARCHIVE["Monthly<br/>Report Archive"]

    style PDF fill:#10b981,color:#fff
```

***

### Pricing

| Event | Price | Cost per 100 | Cost per 1,000 |
|-------|-------|-------------|----------------|
| **Screenshot** | $0.005 | $0.50 | $5.00 |
| **PDF** | $0.008 | $0.80 | $8.00 |

#### Cost Comparison

| Solution | Per Screenshot | Monthly (1K/day) |
|----------|---------------|-----------------|
| **This Actor** | **$0.005** | **$150** |
| ScreenshotAPI.net | $0.01 | $300 |
| Urlbox | $0.02 | $600 |
| Custom Puppeteer server | $50/mo + maintenance | $50+ |
| Browserless.io | $0.008 | $240 |

***

### Technical Details

```mermaid
flowchart TB
    subgraph "Actor Lifecycle"
        INIT["Actor.init()"] --> LAUNCH["Launch Puppeteer<br/>(pre-warmed)"]
        LAUNCH --> LISTEN["HTTP Server<br/>on STANDBY_PORT"]
        LISTEN --> READY["Ready for<br/>Requests"]
    end

    subgraph "Per Request"
        READY --> PAGE["Create New Page"]
        PAGE --> VIEWPORT["Set Viewport"]
        VIEWPORT --> NAV["Navigate to URL<br/>(networkidle2, 25s timeout)"]
        NAV --> DELAY["Optional Delay"]
        DELAY --> CAPTURE["Screenshot or PDF"]
        CAPTURE --> CLOSE["Close Page"]
        CLOSE --> READY
    end

    style LAUNCH fill:#10b981,color:#fff
    style CAPTURE fill:#3b82f6,color:#fff
```

- **Browser**: Chromium via Puppeteer, pre-launched at startup
- **Concurrency**: 3 parallel captures per batch
- **Cache**: In-memory LRU, 100 entries, 10-minute TTL
- **Timeout**: 25 seconds per page navigation
- **Base Image**: `apify/actor-node-puppeteer-chrome:22-24.11.1`

***

### Integrations

| Platform | Integration Method |
|----------|-------------------|
| **Zapier** | Webhook -> GET /screenshot |
| **Make (Integromat)** | HTTP module |
| **n8n** | HTTP Request node |
| **GitHub Actions** | curl in CI/CD pipeline |
| **Selenium/Playwright** | Screenshot service replacement |
| **Apify Orchestrator** | Direct Standby URL call |

***

### FAQ

**Q: What browser is used?**
A: Chromium via Puppeteer, pre-warmed at actor startup for instant response.

**Q: Can it capture login-protected pages?**
A: Current version captures public pages only. Authentication support coming soon.

**Q: Maximum resolution?**
A: 3840x2160 (4K Ultra HD). Default: 1280x720 (HD).

**Q: How does the cache work?**
A: Screenshots cached in-memory for 10 minutes. Same URL + same parameters = instant cached response at no additional cost.

**Q: Can it handle SPAs / JavaScript-heavy pages?**
A: Yes! Puppeteer renders JavaScript completely before capture. Uses `networkidle2` to wait for all resources.

**Q: What's the maximum batch size?**
A: 20 URLs per batch request. Processed with bounded concurrency (3 at a time).

***

### Related Actors

- [Web Content Extractor API](https://apify.com/george.the.developer/web-content-extractor-api) — Extract structured JSON from any URL
- [WebSight API](https://apify.com/george.the.developer/websight-api) — Website intelligence (SEO, tech stack, AI score)
- [Website Contact Scraper](https://apify.com/george.the.developer/website-contact-scraper) — Extract emails, phones, social links

***

*Built by [George Kioko](https://apify.com/george.the.developer) | 6,196+ data extraction jobs | 35+ production APIs | Sub-3s delivery guaranteed*

# Actor input Schema

## `url` (type: `string`):

URL to capture (used for testing; in Standby mode, pass url as a query parameter)

## Actor input object example

```json
{
  "url": "https://example.com"
}
```

# Actor output Schema

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

Rows of this run's dataset in the Overview table view, with url, output, mime type, size and captured at.

# 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 = {
    "url": "https://example.com"
};

// Run the Actor and wait for it to finish
const run = await client.actor("george.the.developer/screenshot-pdf-api").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 = { "url": "https://example.com" }

# Run the Actor and wait for it to finish
run = client.actor("george.the.developer/screenshot-pdf-api").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 '{
  "url": "https://example.com"
}' |
apify call george.the.developer/screenshot-pdf-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,george.the.developer/screenshot-pdf-api"
        }
    }
}
```

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/zxRr8PyiJB0vpgmAN/builds/mIhWg9uCkJfI0GA5p/openapi.json
