# Website Screenshots in Bulk, Desktop and Mobile (`usta/website-screenshots`) Actor

Bulk screenshots of public websites. One stored screenshot per successful page and viewport, with final URL, HTTP status, page title and capture time. Failures are not result rows.

- **URL**: https://apify.com/usta/website-screenshots.md
- **Developed by:** [US Tech Automations](https://apify.com/usta) (community)
- **Categories:** Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$4.00 / 1,000 result rows

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 Screenshots in Bulk, Desktop and Mobile

This tool takes bulk screenshots: a website screenshot of each public page you list, on a desktop or mobile screen.

Paste public page addresses. Each address is opened in a headless browser (no window on a screen). You get one result row per address and viewport that produced an image, with the final address, the HTTP status, the page title, and the time of the capture. The image itself is stored beside the row. A page that fails is not a result row.

### Input

| Field | What it does |
|---|---|
| **Page addresses** | One or more public http or https addresses. Private-network addresses are refused. |
| **Viewports** | `desktop` is 1366 by 768. `mobile` is 390 by 844. Default is desktop only. Pick one or both. |
| **Full page** | On by default. The image is the whole loaded page. Off keeps only the viewport. |
| **Image format** | `png` (default) or `jpeg`. |
| **Seconds to wait after load** | Default 2. Maximum 15. |
| **Maximum screenshots** | Hard ceiling on captures, counting each viewport separately. Default 50. Maximum 5,000. |
| **Proxy configuration** | Optional Apify proxy. Off by default, including on a local run. |

### Pricing

**Pay per result. $0.004 per stored screenshot. No start fee.**

Every row in the results is one charged result. Failed inputs are not rows; they are listed in the run log and the RUN\_SUMMARY record, and cost nothing. A run that stores no image adds no result rows. **Maximum screenshots** is the spend cap.

### Output (one row per capture)

One example row from a real local run on 2026-09-22 against `https://example.com/` (desktop, full page, png, 2 second wait):

```json
{
  "url": "https://example.com/",
  "final_url": "https://example.com/",
  "http_status": 200,
  "page_title": "Example Domain",
  "viewport": "desktop",
  "full_page": true,
  "image_key": "screenshot-0001-desktop.png",
  "image_bytes": 18800,
  "captured_at": "2026-09-22T19:28:53Z",
  "status": "ok"
}
```

The image for that row was a PNG, 1366 by 768 pixels, 18,800 bytes. It is stored in the run's key-value store under `image_key`, not inside the row.

| Field | What it holds |
|---|---|
| `url` | The address you pasted |
| `final_url` | The address after redirects. Empty only if the browser did not report one |
| `http_status` | The HTTP status the browser received. Empty only if the browser did not report one |
| `page_title` | The page title. Empty if the page had none. An email or phone number in the title is replaced with `[redacted]` |
| `viewport` | `desktop` or `mobile` |
| `full_page` | True when the whole page was requested |
| `image_key` | Name of the PNG or JPEG in the key-value store |
| `image_bytes` | Size of that image in bytes |
| `captured_at` | When this row was written, in UTC |
| `status` | `ok` on every result row |

A failed address is not in this table. The run log and the `RUN_SUMMARY` record list each failed address and the reason. `RUN_SUMMARY` also has `rows_pushed` and `failures`.

### What this does not do

- It does not log in, send cookies, or solve a CAPTCHA. You get what a signed-out visitor gets. If a CAPTCHA page loads, the image is that page, and this tool does not try to get past it.
- It does not open a page whose robots.txt disallows that path. That failure is in the run log and `RUN_SUMMARY`, not in the results.
- It does not invent a title, status, or image when the page could not be opened.
- It does not grant a licence to copy a site's design or words. A screenshot is a copy of what the page showed. The site's own terms still apply.
- It does not decide that you are allowed to use a page. It only reads robots.txt.
- It does not open addresses on a private network.
- It does not open a visible browser window.
- It does not promise how fast a run will be, or that every site will answer.

### Limits

- `maxItems` is 1 to 5,000 (default 50). Each viewport counts as its own capture.
- `waitSeconds` is 0 to 15 (default 2).
- Only desktop (1366x768) and mobile (390x844).
- Only png and jpeg.
- A failed address is not a result row. Other addresses in the same run still run.
- On a short page, a full-page image can be the same height as the viewport. That is what happened for example.com in the run above.

### Refunds and support

Refunds: if a run returns zero rows for a valid input, email operations@ustechautomations.com within 7 days and we refund that run. Support: same address, replies within 2 business days.

# Actor input Schema

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

Public http or https addresses. One screenshot is taken per address and per viewport that succeeds. Private-network addresses are refused. A page that fails is listed in the run log and RUN\_SUMMARY, not as a result row.

## `viewports` (type: `array`):

Subset of desktop (1366x768) and mobile (390x844). Default is desktop only.

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

When true, the image is the whole page. When false, it is only the viewport.

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

png or jpeg.

## `waitSeconds` (type: `integer`):

How long to wait after the page load event before taking the image. Default 2. Maximum 15.

## `maxItems` (type: `integer`):

Hard ceiling on captures, counting each viewport separately. Default 50. Maximum 5000. This is the spend cap for a pay-per-result run.

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

Optional Apify proxy. Leave off for a local run. Off by default.

## Actor input object example

```json
{
  "urls": [
    "https://example.com/"
  ],
  "viewports": [
    "desktop"
  ],
  "fullPage": true,
  "format": "png",
  "waitSeconds": 2,
  "maxItems": 50,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `screenshots` (type: `string`):

No description

## `images` (type: `string`):

No description

## `report` (type: `string`):

No description

## `runSummary` (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/"
    ],
    "viewports": [
        "desktop"
    ],
    "format": "png",
    "waitSeconds": 2,
    "maxItems": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("usta/website-screenshots").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/"],
    "viewports": ["desktop"],
    "format": "png",
    "waitSeconds": 2,
    "maxItems": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("usta/website-screenshots").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/"
  ],
  "viewports": [
    "desktop"
  ],
  "format": "png",
  "waitSeconds": 2,
  "maxItems": 50
}' |
apify call usta/website-screenshots --silent --output-dataset

```

## MCP server setup

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

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/CgB0rbqiQx0hrOasy/builds/m0ITqyoCadQKHeJeh/openapi.json
