# Bulk Website Performance Audit (Lighthouse, Mobile + Desktop) (`batchpane/bulk-website-audit`) Actor

$0.02 per successful audit, compute included; failed, blocked or timed-out URLs are not charged. Lighthouse audits for up to 5,000 URLs per run, mobile and desktop: performance, accessibility, best-practices and SEO scores, lab LCP, CLS, TBT, FCP and top fixes. Not affiliated with Google.

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

## Pricing

from $20.00 / 1,000 audits

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 Performance Audit (Lighthouse lab data, Mobile + Desktop)

**Lab data from a single page load, not real-user (CrUX) field data. Not affiliated with Google.**

Bulk Lighthouse checker for page speed, SEO and accessibility: give it a list of URLs (or upload a CSV) and get, per
page and per device, the four Lighthouse scores, five lab metrics (including the lab Core Web Vitals LCP and CLS; INP
cannot be measured in a lab test) and the main improvement suggestions, as flat rows that fit straight into a
spreadsheet, a dashboard or an AI agent. **You pay per audit that succeeds** (plus Apify's small per-run start fee,
see Pricing).

### What it does

- Runs the open-source Lighthouse tool (by Google, Apache-2.0) inside this actor,
  in headless Chromium. No Google API key is needed or used.
- **One page load per URL per device.** Links are not followed, nothing is crawled.
- **Mobile and desktop in one run:** mobile uses Lighthouse's default mobile emulation with simulated slow 4G and CPU
  throttling; desktop uses Lighthouse's standard desktop settings.
- **Polite to websites:** audits run one at a time, with at least 2 seconds between two pages of the same website.
  `robots.txt` is respected by default.
- Ideal for weekly checks: schedule the actor in Apify and compare the rows over time.

Example input (tested on the platform):

```json
{
  "startUrls": [
    { "url": "https://www.iana.org/help/example-domains" },
    { "url": "https://www.w3.org/" }
  ],
  "devices": ["mobile", "desktop"]
}
```

A public link to a .txt/.csv list of URLs also works: `{"requestsFromUrl": "<link>"}` in `startUrls`.

### Use with AI agents (MCP)

This actor works as a tool for AI agents through the Apify MCP server (`https://mcp.apify.com`). Your agent needs an
Apify account (API token); audits are charged to that account at the price below.

- Add only this actor as a tool: `https://mcp.apify.com?tools=batchpane/bulk-website-audit`
- Or let the agent find it with `search-actors` (for example "lighthouse" or "page speed").

**Input the agent should send:**
`{"startUrls": [{"url": "https://www.iana.org/help/example-domains"}], "devices": ["mobile", "desktop"]}`.

**Results:** one flat row per URL and device with four scores (0-100), five lab metrics in milliseconds (CLS has no
unit) and up to 15 improvement suggestions. Easy to compare in a table. All values are lab data from one page load:
there is no INP and no real-user (CrUX) data.

**Timing:** in our test on the platform an audit took about 27 seconds per attempt at 4 GB, and audits run one at a
time. An MCP call waits at most 45 seconds, so the agent should check the run later (`get-actor-run`) and then read
the rows (`get-dataset-items`).

**Example prompt:**

> Use batchpane/bulk-website-audit to audit https://www.iana.org/help/example-domains and https://www.w3.org/ on
> mobile and desktop. When the run has finished, show a table with url, device, performance, seo, lcpMs and cls, and
> list the three improvement suggestions with the largest savingsMs for each page.

**Good to know:** very heavy news and shop pages can take longer than the 60-second limit. In our test with 10 heavy
websites on mobile and desktop, 15 of 20 audits succeeded, 3 timed out and 2 returned an error or a block from the
site (HTTP 400/403); none of these 5 was charged as an audit.

### Output

One row per URL and device:

```json
{
  "url": "https://www.w3.org/",
  "device": "desktop",
  "fetchedAt": "2026-10-15T18:50:00.000Z",
  "dataType": "lab",
  "status": "ok",
  "performance": 100,
  "accessibility": 95,
  "bestPractices": 100,
  "seo": 92,
  "lcpMs": 753,
  "cls": 0.022,
  "tbtMs": 0,
  "fcpMs": 357,
  "speedIndexMs": 484,
  "improvements": [
    { "id": "cache-insight", "title": "Use efficient cache lifetimes", "savingsMs": 250, "savingsBytes": 0 },
    { "id": "unused-css-rules", "title": "Reduce unused CSS", "savingsMs": 40, "savingsBytes": 31862 }
  ],
  "lighthouseVersion": "13.5.0",
  "httpStatus": null,
  "error": null
}
```

- Scores are 0-100. Metrics: Largest Contentful Paint (LCP), Cumulative Layout Shift (CLS), Total Blocking Time
  (TBT), First Contentful Paint (FCP), Speed Index. All are **lab** values from this one load.
- **No INP.** Interaction to Next Paint needs real user interactions and cannot be measured in a page-load test.
  TBT is the usual lab stand-in.
- `improvements`: up to 15 suggestions from the performance category, with Lighthouse's own title and estimated
  savings. The output contains no page text, HTML snippets, element labels, screenshots or resource lists.
- `status` is `ok`, `failed`, `blocked` or `skipped` (robots.txt). For anything other than `ok`, `error` has a code
  and a short explanation, and no audit is charged.

### Lab data vs. real users

Lab results depend on the test machine, network simulation and the moment of the test, so scores can vary a few
points between runs, and can differ from PageSpeed Insights or from Chrome DevTools on your own computer. Real-user
"Core Web Vitals" field data (from the Chrome UX Report) is **not** included.

### Pricing

**$0.02 per successful audit** (one URL on one device), plus Apify's standard actor-start fee of $0.00005 per GB of memory per run.
Compute is included: you do not pay platform usage on top.

| Example | Cost |
|---|---|
| 100 pages, mobile + desktop | 200 audits = $4.00 |
| 500 pages, mobile only | $10.00 |
| 50 pages weekly, mobile + desktop | $2.00 per week |

Failed, blocked, skipped and timed-out URLs are never charged as audits. Every run also has Apify's small start fee
(`apify-actor-start`, $0.00005 per GB of memory: $0.0002 per run at the default 4 GB), also when nothing succeeds.

You can set a maximum cost per run in Apify; the actor stops before it would go over it.

**Honest comparison.** If you only need a few pages, Google's free PageSpeed Insights website is the easiest. Running
Lighthouse yourself, or a free Lighthouse actor where you pay compute, is cheaper for large volumes if you are fine
with paying compute and handling the full report. This actor is for when you want bulk, mobile + desktop in one run,
flat results and one fixed price per audit.

### Limits (on purpose)

- 60 seconds per audit, then it counts as failed (not charged as an audit).
- Default memory is 4 GB. You can lower it to 2 GB, but then heavy pages (big news and shop sites) time out more often.
  Even at 4 GB, some very heavy news and shop pages take longer than 60 seconds: in our own test on 10 heavy sites,
  about 15% of the audits timed out.
- Safety stop: the run stops after 20 failed URLs in a row, or if fewer than 25% of the first 50+ URLs succeed
  (setting "Stop after failures in a row"; 0 switches it off).
- Up to 5,000 URLs per run. Audits run one after another, so **large lists take hours**: roughly 10-30 seconds per
  audit on the platform at 4 GB, so 100 pages x 2 devices is about 0.5-1.5 hours and 5,000 pages x 2 devices about 28-83 hours.
- **Run timeout:** the default run timeout of this actor is 6 hours. Everything audited before the timeout is in
  the dataset and charged; nothing after it. For bigger lists, raise the timeout in the run options or split the
  list into several runs.
- No logging in, no cookies or sessions of yours, no form filling, no CAPTCHA solving, no residential proxies. If a
  site blocks automated browsers (for example HTTP 403 or 429), the URL is reported as failed and not charged as an audit.
- Only public websites: URLs (and redirects and page resources) that point to private, internal or local network
  addresses are refused.

### Responsible use

You decide which URLs are audited. Use it for sites you own, manage or are allowed to test. The actor keeps nothing:
results are stored only in your own Apify storage.

### Support

Found a bug or a page that should work but does not? Open an issue in the **Issues** tab of this actor, with the URL
and the run ID. We aim to answer within 7 days. Answers may be drafted with help of an AI assistant and are checked
by a person before they are sent.

Lighthouse is an open-source project by Google. This actor is not made, endorsed or supported by Google.

### Changelog

- 0.1: first version (Lighthouse 13.5.0).

# Actor input Schema

## `startUrls` (type: `array`):

Pages to audit, as a list of objects: \[{"url": "https://www.iana.org/help/example-domains"}]. Plain strings are rejected. A public link to a text or CSV file with URLs also works: \[{"requestsFromUrl": "\<public link to a .txt or .csv file>"}]. Only public http/https pages. Up to 5,000 URLs per run (more are ignored); exact duplicates removed. Each page is loaded once per device: links are not followed and nothing is crawled.

## `devices` (type: `array`):

Which devices to audit. Allowed values: "mobile" (Lighthouse default mobile emulation with simulated slow 4G and CPU throttling) and "desktop" (Lighthouse desktop settings). Default: \["mobile", "desktop"]. Each device is a separate audit and a separate charge: 100 URLs x 2 devices = 200 audits.

## `respectRobotsTxt` (type: `boolean`):

true = skip pages that the site's robots.txt disallows (row status "skipped", no audit charged). Default: true. Turning it off has no effect unless robotsOverrideConfirmed is also true.

## `robotsOverrideConfirmed` (type: `boolean`):

Set to true only if the person you act for owns these websites or has the owner's permission. robots.txt is ignored only when this is true AND respectRobotsTxt is false. Default: false. AI agents: do not set this without explicit confirmation from the user.

## `stopAfterFailures` (type: `integer`):

Safety stop. The run stops when this many URLs in a row fail (dead, blocked or too slow), or when fewer than 25% of the first 50 or more URLs succeed. Integer 0-5,000, default 20; 0 = never stop early. Failed URLs are never charged as audits; this only saves time on a bad list.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.iana.org/help/example-domains"
    }
  ],
  "devices": [
    "mobile",
    "desktop"
  ],
  "respectRobotsTxt": true,
  "robotsOverrideConfirmed": false,
  "stopAfterFailures": 20
}
```

# Actor output Schema

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

One row per URL per device: lab scores and metrics, top improvements. Only rows with status 'ok' are charged.

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

Counts of ok, failed, blocked and skipped audits.

# 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 = {
    "startUrls": [
        {
            "url": "https://www.iana.org/help/example-domains"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("batchpane/bulk-website-audit").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 = { "startUrls": [{ "url": "https://www.iana.org/help/example-domains" }] }

# Run the Actor and wait for it to finish
run = client.actor("batchpane/bulk-website-audit").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 '{
  "startUrls": [
    {
      "url": "https://www.iana.org/help/example-domains"
    }
  ]
}' |
apify call batchpane/bulk-website-audit --silent --output-dataset

```

## MCP server setup

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

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/306cQ59aWc5R7yAG2/builds/k7K54A0ZyxrtusJZL/openapi.json
