# Website Screenshot - Bulk URLs, Full Page, Mobile, PDF (`dariandanciu/website-screenshot`) Actor

Screenshot hundreds of URLs in one run: full page, desktop or mobile, PNG, JPEG or PDF, with cookie banners hidden. Get a shareable image link per URL. Failed URLs are never charged.

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

## Pricing

from $0.50 / 1,000 results

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 - bulk URLs, full page, mobile, PDF

Screenshot **hundreds of web pages in one run**. Full page or visible area, desktop or mobile,
PNG, JPEG or PDF, with **cookie banners and ads removed**. Every screenshot gets a shareable link,
listed in a table you can download as CSV, Excel or JSON.

### Why this one

- **Many URLs per run.** Paste a list, upload a file, or point it at a Google Sheet. Pages are
  captured in parallel.
- **Clean captures.** Cookie pop-ups from OneTrust, Cookiebot, Didomi, Usercentrics, Quantcast,
  Sourcepoint and others are hidden. Ad and tracking networks are blocked, so there are no empty ad
  slots, and pages load faster.
- **Real full-page screenshots.** The page is scrolled first so lazy-loaded images actually
  appear, and scroll locks left behind by consent pop-ups are released.
- **Mobile and tablet for real.** Mobile mode uses a phone user agent and touch screen, so sites
  serve their actual mobile layout, not a squeezed desktop page.
- **You never pay for failures.** Pages that can't be captured after 2 retries are listed in
  `RUN_SUMMARY` and cost nothing.

### Features

| Option | What it does |
|---|---|
| Format | PNG (sharpest), JPEG (smallest), or PDF (printable A4 of the whole page) |
| Full page | Whole scrollable page, or only the visible screen |
| Device | Desktop 1920x1080, laptop 1366x768, iPad, iPhone - or a custom size |
| Capture one element | Screenshot just `#pricing` or `.hero` instead of the page |
| Hide elements | Remove chat widgets, newsletter pop-ups, anything with a CSS selector |
| Dark mode | Ask the site for its dark theme |
| Wait for | HTML ready, page loaded, or network idle, plus an extra delay |
| Proxy | Optional, for sites that block data centers or to see a country's version |

### Output

One row per URL:

```json
{
    "url": "https://apify.com/",
    "finalUrl": "https://apify.com/",
    "title": "Apify: Full-stack web scraping and data extraction platform",
    "statusCode": 200,
    "screenshotUrl": "https://api.apify.com/v2/key-value-stores/<id>/records/apify-com_b2cbecea.png",
    "format": "png",
    "device": "desktop",
    "width": 1920,
    "height": 10036,
    "fullPage": true,
    "bytes": 1010631,
    "takenAt": "2026-10-27T03:55:22.508Z"
}
```

The Output tab shows the screenshots as thumbnails right in the table.

### Use cases

- **Website monitoring.** Schedule daily runs and keep a visual history of your own or
  competitors' pages.
- **Agencies and SEO.** Capture client sites, landing pages and SERP-adjacent pages for reports.
- **QA.** Check how pages render on desktop, tablet and phone after a release.
- **Archiving and compliance.** Keep PDF copies of terms pages, pricing pages or ads as shown.
- **AI agents and automations.** Call it from Zapier, Make, n8n or the Apify API and get image
  links back.

### Pricing

Pay per screenshot. See the Pricing tab. Runs, retries and failed URLs are free.

### Use it from code

```bash
curl -X POST "https://api.apify.com/v2/acts/dariandanciu~website-screenshot/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"urls":[{"url":"https://example.com"}],"device":"mobile","format":"jpeg"}'
```

### Good to know

- Very long pages are cut at **Max full-page height** (15,000 px by default; up to 30,000).
- Pages behind a login or a bot check (for example Cloudflare challenges) are captured as they
  appear to a visitor, which may be the challenge page itself.
- PNG full-page captures of long, image-heavy pages can be 5-10 MB. Choose JPEG for smaller files.

### Feedback

Missing an option or found a page that renders wrong? Open an issue on the Issues tab with the URL.

# Actor input Schema

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

Pages to capture. Paste a list, upload a file, or link a Google Sheet. 'https://' is added if missing.

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

PNG is sharpest, JPEG is smallest, PDF gives a printable A4 document of the whole page.

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

Capture the whole scrollable page instead of only what fits on screen.

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

Screen size and browser type to emulate. Mobile and tablet load the mobile version of the site.

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

Overrides the device width.

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

Overrides the device height (the visible area when Full page is off).

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

Ask the site for its dark theme, if it has one.

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

Hide common cookie consent pop-ups (OneTrust, Cookiebot, Didomi, Usercentrics and more) so they don't cover the page.

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

Skip ad and tracking networks. Pages load faster and screenshots show no ad slots.

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

Extra elements to hide, e.g. .chat-widget or #newsletter-popup.

## `selector` (type: `string`):

Screenshot only this element, e.g. #pricing-table. Leave empty for the whole page.

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

When the page counts as loaded. 'Network idle' is slowest but best for heavy JavaScript sites.

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

Wait this long after loading, for animations and late content.

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

Scroll through the page before capturing so lazy-loaded images appear.

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

Only for JPEG. Lower is smaller.

## `maxFullPageHeight` (type: `integer`):

Very long pages are cut at this height.

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

Give up on a page after this long. Each page gets 2 retries.

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

Pages captured at the same time. Raise memory for more than 5.

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

Optional. Use a proxy for sites that block data centers or to see a country-specific version.

## Actor input object example

```json
{
  "urls": [
    {
      "url": "https://apify.com"
    },
    {
      "url": "https://en.wikipedia.org/wiki/Screenshot"
    }
  ],
  "format": "png",
  "fullPage": true,
  "device": "desktop",
  "darkMode": false,
  "hideCookieBanners": true,
  "blockAds": true,
  "waitUntil": "load",
  "delayMs": 1000,
  "scrollToBottom": true,
  "jpegQuality": 80,
  "maxFullPageHeight": 15000,
  "timeoutSecs": 60,
  "maxConcurrency": 5,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

One row per URL with a link to its screenshot.

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

Screenshot count and any URLs that failed (failed URLs are not charged).

# 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"
        },
        {
            "url": "https://en.wikipedia.org/wiki/Screenshot"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("dariandanciu/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": [
        { "url": "https://apify.com" },
        { "url": "https://en.wikipedia.org/wiki/Screenshot" },
    ] }

# Run the Actor and wait for it to finish
run = client.actor("dariandanciu/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": [
    {
      "url": "https://apify.com"
    },
    {
      "url": "https://en.wikipedia.org/wiki/Screenshot"
    }
  ]
}' |
apify call dariandanciu/website-screenshot --silent --output-dataset

```

## MCP server setup

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