# Website Screenshot API – Bulk Full Page PNG, JPEG & PDF (`forevertools/website-screenshot`) Actor

Website screenshot API & URL to image converter for many URLs at once: full-page or viewport capture as PNG/JPEG, webpage to PDF, website thumbnails, desktop or mobile, cookie banners hidden. Each image gets a public URL; one dataset row per page with status, final URL, size and errors.

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

## Pricing

$3.00 / 1,000 screenshot takens

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

## Bulk Website Screenshot (PNG, JPEG, PDF)

Paste a list of URLs and get a **screenshot of every page**, each with its own **public image URL**. You can choose
full-page or viewport-only, **PNG, JPEG or PDF**, **desktop or mobile**, and set a custom viewport, wait strategy and delay.
**Common cookie consent banners are hidden** (best effort) so the page itself is what you see. Runs real Chromium (Playwright).

Use it to: archive or monitor landing pages, check that a redesign rendered correctly across many pages, get
competitor page snapshots, add thumbnails to a directory or CMS, make visual QA reports, collect evidence of how a
page looked on a date, or save pages as PDFs.

### How it works

1. You pass a list of URLs. Each is trimmed, given `https://` if it has no scheme, and exact duplicates are removed. Only `http` and `https` URLs are accepted.
2. Each URL is opened in a fresh, isolated Chromium browser context (no cookies, logged out) using your device and viewport settings. Up to 3 pages are captured at the same time.
3. The actor waits for the `load` event or for `networkidle`, then for your optional extra delay, and injects CSS that hides common cookie banners.
4. It takes the PNG, JPEG or PDF, saves it in the run's key-value store and writes one dataset row with the public link, final URL, HTTP status and image size.

### Features

- **Bulk**: any number of URLs, captured 3 at a time. If one URL fails, the error goes in its row and the run keeps going.
- **Formats**: PNG (lossless), JPEG (quality 85, much smaller), or PDF (screen styles, backgrounds kept, one tall page).
- **Full page or viewport**: `fullPage` scrolls the whole page into one image.
- **Devices**: Desktop (viewport default 1280×800, configurable from 200 to 3840 wide and 200 to 2160 high) or Mobile (iPhone-class 390×844 at 3× scale with a
  touch-enabled mobile user agent).
- **Wait control**: `load` (fast) or `networkidle` (better for JS-heavy apps), plus an extra delay of up to 30 seconds for animations
  and lazy-loaded content. If a page never reaches the wait condition within the timeout but something has rendered, whatever is there is captured and a note is added.
- **Animations disabled** in PNG/JPEG captures, so screenshots are stable and repeatable.
- **Cookie banner hiding** (best effort): CSS rules for OneTrust, Cookiebot, Didomi, Quantcast, TrustArc,
  Usercentrics, Osano, CookieYes, Complianz, iubenda, Sourcepoint, Funding Choices, HubSpot, Klaro, Axeptio,
  tarteaucitron, Borlabs, Termly and generic `cookie-banner`/`cookie-consent` patterns. Banners are hidden, never
  clicked, so no consent is given on your behalf.

### Use cases

#### Website monitoring and visual archiving

Schedule a run on key pages (pricing, landing pages, terms) and keep the image links as dated evidence of how a page looked.

#### Visual QA after a redesign

Capture the same URLs on desktop and on mobile, then review them in the dataset's image preview table.

#### Competitor snapshots and thumbnails

Take full-page shots of competitor pages, or viewport-only JPEGs (`fullPage: false`) as small previews for a directory or CMS.

#### PDF copies of web pages

Save documentation or article pages as PDFs with backgrounds kept.

### Input

```json
{
  "urls": ["https://example.com", "apify.com"],
  "format": "png",
  "fullPage": true,
  "device": "desktop",
  "viewportWidth": 1280,
  "viewportHeight": 800,
  "waitUntil": "load",
  "delayMs": 0,
  "hideCookieBanners": true,
  "timeoutSecs": 45
}
```

URLs without a scheme get `https://`. Duplicate URLs are captured only once. Optional `maxConcurrency` (1 to 3, default 3) lowers the number of pages captured in parallel. `timeoutSecs` is the navigation timeout per URL (5 to 180, default 45).

### Output (one dataset row per URL)

```json
{
  "url": "https://example.com/",
  "finalUrl": "https://example.com/",
  "status": 200,
  "screenshotUrl": "https://api.apify.com/v2/key-value-stores/<storeId>/records/0001-example.com.png",
  "width": 1280,
  "height": 800,
  "bytes": 20874,
  "format": "png",
  "device": "desktop",
  "error": null
}
```

- `screenshotUrl` is a direct link to the file in the run's key-value store. Open it in a browser, embed it, or download it. Files are named by input position and hostname (JPEG files end in `.jpg`).
- `width`/`height` are in pixels. Mobile images are 3× the CSS size, e.g. 1170 px wide. For PDFs they are the page size in CSS px.
- `status` is the HTTP status of the final response. 4xx/5xx pages are still captured and `error` says `HTTP 404`, etc.
- `error` is set when a page couldn't be loaded (DNS failure, timeout with nothing rendered, connection refused...). Those rows have no screenshot.
  It is also used for the partial-load note. Certificate errors do not fail a capture: the page is loaded anyway.

The Overview table in the Console shows image previews. Export the dataset as CSV, JSON or Excel, or fetch it via the API.

### Pricing

**$0.003 per screenshot** ($3 per 1,000). No subscription, and you also pay Apify platform usage as shown on your plan.

- 100 pages = $0.30
- 1,000 pages = $3.00
- 50 landing pages captured weekly = $0.15 per run

**What is charged:** one event for every URL where a screenshot file was saved. That includes pages that answered with an error status such as 404 (they are captured, so they are charged) and partially loaded pages. **What is not charged:** URLs that failed with no screenshot (DNS failure, timeout with nothing rendered, invalid URL). If you set a maximum cost per run, the actor stops once that limit is reached.

### Tips

- Single-page apps: use `waitUntil: "networkidle"` or a `delayMs` of 1000–3000.
- Very long pages make very large PNGs. Use JPEG, or turn off `fullPage`.
- PDFs are one continuous page (height capped at about 19,200 px by Chromium), not split into A4 sheets. With `fullPage: false`, the PDF contains one page of viewport height.
- Pages behind a login, a CAPTCHA or bot protection may capture as the challenge page.

### Limitations

- Cookie banner hiding is best effort. Uncommon or custom consent popups may still show.
- The actor captures what the page shows to a fresh, logged-out visitor with no cookies. There is no login, cookie or custom header input.
- There is no element selector or CSS-selector capture; it captures the page or viewport only.
- Respect the terms of the sites you capture.
- Built and maintained with AI assistance. Issues are answered asynchronously.

### FAQ

**Can I screenshot many URLs at once?**
Yes. Add any number of URLs; they are captured 3 at a time and each gets its own dataset row and image link.

**Can it capture the full scrollable page?**
Yes, `fullPage` is on by default for PNG and JPEG. Turn it off for viewport-only shots.

**How do I get a mobile screenshot?**
Set `device` to `mobile`. It uses a 390×844 iPhone-class viewport at 3× scale with a touch-enabled mobile user agent; the viewport fields are ignored.

**Are cookie banners removed?**
Common ones from the frameworks listed above are hidden with CSS. The actor never clicks "accept". Unusual banners can still appear.

**Am I charged for pages that fail?**
No. Only URLs that produced a saved screenshot are charged. A page that loads but returns 404 is captured and charged.

### Related tools

Other actors by the same developer (same flat pay-per-result pricing, no subscription):

- [Apple App Store Reviews Scraper (Multi-Country)](https://apify.com/forevertools/apple-app-store-reviews)
- [Article Extractor – Clean Text & Markdown for LLM/RAG](https://apify.com/forevertools/article-extractor)
- [Company Jobs Scraper: Workday, Greenhouse, Lever, Ashby](https://apify.com/forevertools/ats-company-jobs)
- [Bulk Domain Checker — WHOIS/RDAP, DNS, SPF/DMARC, SSL Expiry](https://apify.com/forevertools/domain-whois-dns-ssl)
- [Bulk PageSpeed Insights & Core Web Vitals Checker](https://apify.com/forevertools/pagespeed-core-web-vitals)
- [PDF to Text Extractor (Bulk, with Metadata)](https://apify.com/forevertools/pdf-to-text-extractor)
- [Website SEO Audit Crawler](https://apify.com/forevertools/website-seo-audit)
- [Sitemap Extractor & Bulk URL Status Checker](https://apify.com/forevertools/sitemap-url-status-checker)
- [Website Tech Stack Detector (CMS, Framework, Analytics)](https://apify.com/forevertools/website-tech-stack-detector)

### Integrations

Run it from the Apify API, a schedule, or no-code tools: the Apify apps for **Zapier**, **Make** and **n8n** can start any public actor ("Run Actor") and read its dataset. AI agents can call it through the **Apify MCP server**.

# Actor input Schema

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

Pages to capture. Domains without a scheme get https://.

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

PNG (lossless), JPEG (smaller) or PDF (printable, A4-free: sized to the page).

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

Capture the entire scrollable page instead of just the viewport (PNG/JPEG).

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

Desktop uses the viewport below. Mobile emulates an iPhone-class phone (390x844, touch, mobile user agent, 3x scale) and ignores the viewport fields.

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

Desktop viewport width.

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

Desktop viewport height.

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

'load' = page load event (fast). 'networkidle' = no network activity for 500 ms (better for JS-heavy sites, slower).

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

Wait this long after the page is ready (for animations, lazy content).

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

Best-effort: hide consent popups from common frameworks (OneTrust, Cookiebot, Didomi, Quantcast, TrustArc, Usercentrics, Osano, CookieYes, Complianz and more) with CSS. Does not click accept.

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

Navigation timeout per URL. Failed/timed-out URLs get an error row; the run continues.

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

Pages captured in parallel.

## Actor input object example

```json
{
  "urls": [
    "https://example.com",
    "https://apify.com"
  ],
  "format": "png",
  "fullPage": true,
  "device": "desktop",
  "viewportWidth": 1280,
  "viewportHeight": 800,
  "waitUntil": "load",
  "delayMs": 0,
  "hideCookieBanners": true,
  "timeoutSecs": 45,
  "maxConcurrency": 3
}
```

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

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

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

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,forevertools/website-screenshot"
        }
    }
}
```

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/6CAr9uEgG43EFyNK2/builds/NZLD5UveUXYeqlGQ0/openapi.json
