# PageSpeed Batch - Lighthouse & Core Web Vitals for Many URLs (`fabrikit/pagespeed-batch`) Actor

Audit many URLs or a sitemap with Lighthouse: performance, SEO, accessibility scores, LCP, CLS, TBT, top fixes, mobile and desktop. No key needed; add a free Google key for CrUX data. From US$1.50 per 1,000 API audits.

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

## Pricing

from $1.50 / 1,000 url audit (google api)s

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

## PageSpeed Batch - Lighthouse scores and Core Web Vitals for hundreds of URLs

Audit many pages with **Google PageSpeed Insights** in one run and get a clean, flat dataset you can sort, chart or export:

- **Scores** (0-100): performance, accessibility, best practices, SEO
- **Lab Core Web Vitals**: LCP, CLS, TBT, FCP, Speed Index, TTI, server response time
- **Field data from real Chrome users (CrUX)**: LCP, INP, CLS, FCP, TTFB with FAST / AVERAGE / SLOW verdicts, for the exact URL and for the whole origin when Google has enough traffic data
- **Top fixes**: the biggest opportunities ranked by estimated time and byte savings
- **Failing checks** for accessibility, SEO and best practices, by name
- Final URL after redirects, page weight, request count, DOM size, Lighthouse version
- **Mobile, desktop or both**, and optional **sitemap.xml expansion** (sitemap indexes and `.gz` files are followed; `robots.txt` is used to find the sitemap of a site)

Concurrency respects Google's quota, HTTP 429 is retried with backoff, and a URL Google cannot load produces a free "failed" row instead of stopping the run.

### Two engines: no key needed, or faster with a free Google key

| | Local Lighthouse (default, no key) | Google PageSpeed API (with key) |
|---|---|---|
| Setup | none | free Google API key (steps below) |
| Speed | about 10-25 s per audit, run inside the Actor | Google runs it; many in parallel |
| Real-user CrUX field data | no (`fieldData` is `null`) | yes |
| Price | US$20 per 1,000 audits (`local-audit`) | US$1.50 per 1,000 audits (`url-audit`) |
| `engine` in output | `local-lighthouse` | `psi-api` |

`engine: auto` (default) uses the API when you give a key and local Lighthouse otherwise. The default input works out of the box, so you can try the Actor with no key.

Google serves its API with a project quota, and **without a key that quota is 0** (checked 13 Oct 2026), which is why the local engine exists. Getting a free key takes about two minutes (25,000 audits per day, no billing account):

1. Open the [Google Cloud console](https://console.cloud.google.com/) and create (or pick) a project.
2. Go to **APIs & Services > Library**, search for **PageSpeed Insights API** and click **Enable**.
3. Go to **APIs & Services > Credentials > Create credentials > API key** and copy the key.
4. Paste it into the **Google API key** field (stored as a secret). Optionally restrict it to the PageSpeed Insights API.

### Input

```json
{
  "urls": ["https://example.com", "https://example.com/pricing"],
  "sitemapUrls": ["https://example.com"],
  "maxUrlsPerSitemap": 25,
  "strategy": "both",
  "engine": "auto",
  "apiKey": "YOUR_GOOGLE_API_KEY",
  "maxItems": 100
}
```

| Field | Default | Description |
|---|---|---|
| `urls` | - | Page URLs (a bare domain becomes `https://domain`). |
| `sitemapUrls` | `[]` | Sitemap URLs, or site URLs whose sitemap is found via `robots.txt`. |
| `maxUrlsPerSitemap` | `25` | URLs taken from each sitemap. |
| `strategy` | `mobile` | `mobile`, `desktop` or `both` (two audits per URL). |
| `engine` | `auto` | `auto`, `api` or `local`. |
| `apiKey` | - | Optional Google API key (secret). Enables the API engine. |
| `maxItems` | `50` | Maximum audits to attempt (one audit = one URL on one device). |
| `concurrency` | 10 (API) / 1 (local) | Parallel audits (local engine capped at 3). The Actor backs off automatically on 429. |
| `locale` | `en` | Language of audit texts. |

### Output example (shortened)

```json
{
  "url": "https://example.com/",
  "strategy": "mobile",
  "engine": "psi-api",
  "status": "ok",
  "finalUrl": "https://www.example.com/",
  "performanceScore": 58, "accessibilityScore": 86, "bestPracticesScore": 78, "seoScore": 92,
  "lcpMs": 3912, "cls": 0.043, "tbtMs": 212, "fcpMs": 1835, "speedIndexMs": 2750, "ttiMs": 5101, "ttfbMs": 180,
  "totalBytes": 2457600, "requestCount": 37,
  "fieldData": { "overallCategory": "AVERAGE", "lcpMs": 2900, "lcpCategory": "AVERAGE", "inpMs": 180, "cls": 0.04 },
  "originFieldData": { "overallCategory": "FAST", "lcpMs": 2500 },
  "opportunities": [{ "id": "render-blocking-resources", "title": "Eliminate render-blocking resources", "savingsMs": 1150, "savingsBytes": 0 }],
  "seoIssues": [{ "id": "meta-description", "title": "Document has a meta description" }],
  "lighthouseVersion": "12.8.2"
}
```

`fieldData` is `null` when Google has no real-user data for that URL (use `originFieldData` then) and always `null` with the local engine.

### Pricing (pay per event)

| Event | When | Price |
|---|---|---|
| `url-audit` | successful audit through the Google API (you gave a key) | **US$1.50 per 1,000 audits** |
| `local-audit` | successful audit with local Lighthouse (no key) | US$20.00 per 1,000 audits |

Failed audits (unreachable URL, Lighthouse error) are listed with `status: "failed"` and the error message, and are **not charged**. Google never bills you: the API key is free.

### Use cases

- Weekly Core Web Vitals report for every page in a sitemap
- Agency dashboards: compare client sites with competitors on mobile and desktop
- CI-style regression checks: schedule the Actor and alert when a score drops
- Prioritising SEO work by the pages with the worst LCP or the most savings available

### FAQ

**Why do scores differ from the PageSpeed website?** Lab results vary between runs (network and CPU variance). Audit the same URL a few times and look at medians for decisions.

**Rate limits (API engine)?** Keys allow roughly 400 requests per 100 seconds and 25,000 per day. If Google answers 429 the Actor waits and retries; if the daily quota is gone it stops with a clear message.

**Is field data always present?** No, only for URLs with enough Chrome user traffic.

### En español

Audita cientos de URLs (o un sitemap completo) con Google PageSpeed Insights: puntajes de rendimiento, accesibilidad, buenas prácticas y SEO, Core Web Vitals de laboratorio (LCP, CLS, TBT...), datos reales de usuarios (CrUX) y las mejoras con mayor ahorro estimado, en móvil y/o escritorio. Funciona sin API key (Lighthouse local, US$20 por 1.000 audits) o, con una key gratuita de Google, usa la API de PageSpeed (US$1,50 por 1.000 audits, con datos CrUX). Los audits fallidos no se cobran.

# Actor input Schema

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

Pages to audit, one per line (`https://example.com/pricing`). A bare domain such as `example.com` is treated as `https://example.com`. Duplicates are removed.

## `sitemapUrls` (type: `array`):

Optional. A `sitemap.xml` URL (indexes and .gz files are followed), or a site URL whose sitemap is found through `robots.txt`. Each sitemap adds up to the limit below to the URL list.

## `maxUrlsPerSitemap` (type: `integer`):

How many URLs to take from each sitemap.

## `engine` (type: `string`):

`auto` uses the Google PageSpeed Insights API when you provide an API key (cheapest, fastest, includes real-user CrUX data) and otherwise runs Lighthouse inside the Actor, which needs no key (about 10-25 seconds per audit, no CrUX field data, billed as `local-audit`).

## `strategy` (type: `string`):

`mobile` and `desktop` are separate audits (and separate charges). `both` audits every URL twice.

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

Optional. Your free Google API key for the PageSpeed Insights API (25,000 audits/day, no billing needed). With a key the Actor uses the Google API (US$1.50 per 1,000 audits, CrUX field data included); without one it runs Lighthouse locally. Setup takes 2 minutes: see the README.

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

Maximum audits to attempt (one audit = one URL on one device). Only successful audits are charged; failed ones are listed with their error and are free.

## `concurrency` (type: `integer`):

Audits running in parallel. Leave empty for the default: 10 with the API engine (max 30, the Actor backs off on HTTP 429), 1 with the local engine (capped at 3; parallel Chrome instances need more memory and make timings noisier).

## `locale` (type: `string`):

Locale for audit titles and descriptions, for example `en`, `es`, `de`, `pt-BR`.

## Actor input object example

```json
{
  "urls": [
    "https://example.com"
  ],
  "sitemapUrls": [],
  "maxUrlsPerSitemap": 25,
  "engine": "auto",
  "strategy": "mobile",
  "maxItems": 50,
  "locale": "en"
}
```

# Actor output Schema

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

All records collected during the run

# 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"
    ],
    "maxItems": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("fabrikit/pagespeed-batch").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"],
    "maxItems": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("fabrikit/pagespeed-batch").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"
  ],
  "maxItems": 50
}' |
apify call fabrikit/pagespeed-batch --silent --output-dataset

```

## MCP server setup

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

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/8OIk5ohq83GUvYLyz/builds/IBE68V5jCG6NfgDIa/openapi.json
