# PageSpeed Insights Bulk Audit: Lighthouse and Core Web Vitals (`boubap/pagespeed-bulk-audit`) Actor

Lighthouse and PageSpeed Insights audits for a URL list or a sitemap, on mobile and desktop. One flat row per page: scores, lab metrics, Core Web Vitals field data for the URL and its site, top fixes. $8 per 1,000 audits, failed ones free.

- **URL**: https://apify.com/boubap/pagespeed-bulk-audit.md
- **Developed by:** [Baptiste Bouton](https://apify.com/boubap) (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 $6.00 / 1,000 page auditeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
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

## PageSpeed Insights Bulk Audit: Lighthouse and Core Web Vitals

Give it a list of URLs or a sitemap and it runs PageSpeed Insights on each page, on mobile, desktop or both. You get
one flat row per page: the four Lighthouse scores, the lab metrics, the Core Web Vitals of real Chrome users (for the
URL and for the whole site) and the five fixes with the biggest estimated time saving.
It costs $0.008 per page audited ($8 per 1,000). Failed audits are free.

### What you get for each URL and device

- **Lighthouse scores** (0 to 100): Performance, Accessibility, Best Practices, SEO.
- **Lab metrics** measured by Lighthouse: LCP, FCP, CLS, Total Blocking Time, Speed Index, time to first byte.
- **Field data** from the Chrome UX Report (CrUX, real users over the last 28 days): 75th percentile LCP, INP and
  CLS with the FAST, AVERAGE or SLOW verdict, for the URL and for its origin. Pages without enough traffic get
  `null` for the URL and often still have origin data.
- **Top opportunities**: up to 5 failing performance audits, sorted by estimated saving in milliseconds. The saving
  is the one Lighthouse estimates for the metric it improves most (LCP, FCP, Total Blocking Time or INP), so two audits
  about the same JavaScript work can show the same saving.

### Use cases

- Audit a whole site from its sitemap and sort the slowest pages first.
- Check the Core Web Vitals of client sites every week with the Apify scheduler and spot regressions.
- Compare your pages with competitor pages on mobile and desktop.
- Add speed and SEO scores to a lead list before an agency pitch.
- Find which pages fail Core Web Vitals for real users, not only in the lab, with the CrUX verdict per URL and per site.

### Quick recipes

- **Lighthouse for a whole sitemap**: set `sitemapUrl`, `strategies` to mobile and desktop, sort the dataset by `performanceScore`.
- **Core Web Vitals report**: keep `performance` only and read `fieldCategory` and `originFieldCategory`.
- **Weekly monitoring**: schedule the run in Apify and send the dataset to Google Sheets, Make, Zapier or n8n.
- **From an AI assistant**: call the Actor through the Apify MCP server to audit a page on request.

### Input

| Field | Description | Default |
|---|---|---|
| `urls` | Pages to audit, full addresses | |
| `sitemapUrl` | XML sitemap whose pages are added after `urls`: a sitemap index is followed with one level of nested index, up to 50 sitemap files, `.xml.gz` supported | |
| `strategies` | `mobile`, `desktop` or both | `["mobile"]` |
| `categories` | `performance`, `accessibility`, `best-practices`, `seo` | all four |
| `maxUrls` | Maximum number of URLs in the run | `100` |
| `apiKey` | Your own PageSpeed Insights API key (optional, stored encrypted) | |

Set `urls`, `sitemapUrl` or both. Example:

```json
{ "sitemapUrl": "https://example.com/sitemap.xml", "strategies": ["mobile", "desktop"], "maxUrls": 200 }
```

Without `apiKey`, the Actor uses the owner's shared key: at most 500 URLs per run and 2000 audits per day for your
account. With your own key (free, from the Google Cloud console, PageSpeed Insights API enabled) the limit is 3000 URLs
per run and your key's own daily quota.

Invalid addresses in `urls` are skipped with a warning, `#fragments` are dropped, and a sitemap file that cannot be
read is skipped with a warning. The run fails only when no URL is left to audit.

### Output

One row per URL and device. Real output for `https://apify.com` on mobile, from a run on 22 October 2026:

```json
{
  "url": "https://apify.com/",
  "finalUrl": "https://apify.com/",
  "strategy": "mobile",
  "performanceScore": 34,
  "accessibilityScore": 100,
  "bestPracticesScore": 73,
  "seoScore": 85,
  "lcpMs": 14326,
  "fcpMs": 2701,
  "cls": 0,
  "tbtMs": 2497,
  "speedIndexMs": 8382,
  "ttfbMs": 601,
  "fieldLcpMs": 2437,
  "fieldInpMs": 396,
  "fieldCls": 0.02,
  "fieldCategory": "AVERAGE",
  "originFieldLcpMs": 1933,
  "originFieldInpMs": 370,
  "originFieldCls": 0,
  "originFieldCategory": "AVERAGE",
  "topOpportunities": [
    { "id": "bootup-time", "title": "Reduce JavaScript execution time", "savingsMs": 2950 },
    { "id": "mainthread-work-breakdown", "title": "Minimize main-thread work", "savingsMs": 2500 },
    { "id": "unused-javascript", "title": "Reduce unused JavaScript", "savingsMs": 2100 },
    { "id": "render-blocking-insight", "title": "Render-blocking requests", "savingsMs": 650 },
    { "id": "cache-insight", "title": "Use efficient cache lifetimes", "savingsMs": 150 }
  ],
  "lighthouseVersion": "13.5.0",
  "fetchedAt": "2026-10-22T08:38:31.406Z",
  "error": null
}
```

When a page cannot be audited (unreachable page, Lighthouse error), the row keeps `url` and `strategy`, the other
values are `null`, and `error` says why.

### Pricing

$0.008 per audit ($8 per 1,000). Pay per event: one `page-audited` event per URL and device with a successful audit. A URL audited on mobile and desktop counts twice. Rows with an `error` are free. The run stops as soon as your maximum charge per run is
reached, and if the platform restarts a run, audits already saved are skipped and never charged again.

### Tips

- Lab scores move a few points between runs, as with any Lighthouse test. For trends, compare weekly runs or read
  the field data, which covers 28 days of real visits.
- An audit takes about 40 seconds at Google and the Actor runs 32 at a time: 100 URLs on one device take about 2 to 3
  minutes, 3000 URLs on both devices about 2 hours.
- Picking fewer categories gives shorter rows. The price stays the same.

### FAQ

**Is this the official PageSpeed Insights data?** Yes. The Actor calls the official PageSpeed Insights API v5,
the same engine as pagespeed.web.dev.

**Why is the field data null for some pages?** CrUX only publishes pages and sites with enough Chrome traffic.
Small sites often have origin data but no URL data.

**Does it collect personal data?** No. It returns performance measures of web pages and aggregated, anonymous
Chrome statistics.

**Is my API key safe?** It is an encrypted secret input, it is never logged and never written to the dataset.

### Related Actors

- [Tech Stack Detector](https://apify.com/boubap/tech-stack-detector): See which CMS, analytics and frameworks the
  same sites run, to explain a slow score.
- [Google Trends Explore API](https://apify.com/boubap/google-trends-explore): Check search interest for the topics
  of your pages.

# Actor input Schema

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

Pages to audit, one full address per line, for example https://apify.com. Duplicates are removed. Leave empty if you use a sitemap.

## `sitemapUrl` (type: `string`):

Optional XML sitemap whose pages are audited after the URLs above, for example https://example.com/sitemap.xml. A sitemap index is followed, with one level of nested index, up to 50 sitemap files; .xml.gz files work too. A sitemap that cannot be read is skipped with a warning. Max URLs below caps the total.

## `strategies` (type: `array`):

Run the audit as a mobile phone, a desktop browser, or both. Each URL and device gives one row and one charge. Default: mobile.

## `categories` (type: `array`):

Lighthouse categories to score. Default: all four. Lab metrics and opportunities need Performance. The price is the same whatever you pick.

## `maxUrls` (type: `integer`):

Maximum number of URLs audited in this run, from the list first, then the sitemap. Default 100. Up to 500 with the shared key, up to 3000 with your own API key (about 2 hours on both devices).

## `apiKey` (type: `string`):

Optional. Your own PageSpeed Insights API key from the Google Cloud console (free). Use it for runs above 500 URLs or more than 2000 audits a day, the allowance of the shared key per user. It is stored encrypted and never written to the logs or the dataset.

## Actor input object example

```json
{
  "urls": [
    "https://apify.com"
  ],
  "strategies": [
    "mobile"
  ],
  "categories": [
    "performance",
    "accessibility",
    "best-practices",
    "seo"
  ],
  "maxUrls": 100
}
```

# Actor output Schema

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

Dataset items of the run: one item per result, with the fields described in the dataset schema.

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

// Run the Actor and wait for it to finish
const run = await client.actor("boubap/pagespeed-bulk-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 = { "urls": ["https://apify.com"] }

# Run the Actor and wait for it to finish
run = client.actor("boubap/pagespeed-bulk-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 '{
  "urls": [
    "https://apify.com"
  ]
}' |
apify call boubap/pagespeed-bulk-audit --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,boubap/pagespeed-bulk-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/Rw5hDP4Xvl6LBRUXR/builds/DXcTj1iinlL3vSzCJ/openapi.json
