# PageSpeed Insights Bulk Checker - Core Web Vitals & Lighthouse (`ventura_workalong/pagespeed-insights-bulk`) Actor

Bulk Google PageSpeed Insights test for many URLs or a whole sitemap. Returns Lighthouse scores, lab metrics, real-user Core Web Vitals (LCP, INP, CLS) pass/fail and top fixes, mobile and desktop. Uses the official API with your free Google API key. $0.001 per page audited.

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

## Pricing

from $1.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.

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 Checker: Core Web Vitals & Lighthouse

**PageSpeed Insights Bulk Checker** runs Google PageSpeed Insights on many URLs at once, or on every page in a site's sitemap. You get one flat, comparable row per page and device:

- **Lighthouse scores** (0–100): performance, accessibility, best practices, SEO.
- **Lab metrics:** LCP, FCP, TBT, CLS, Speed Index, TTI and server response time.
- **Real-user Core Web Vitals** from the Chrome UX Report: LCP, INP, CLS, FCP and TTFB at the 75th percentile, with Google's **passed/failed assessment**, for the page and for the whole site (origin).
- **Top opportunities:** the biggest fixes, ranked by estimated time saved.

It uses Google's **official PageSpeed Insights API v5** with **your own free API key**: no scraping, no browser, no proxies. **$0.001 per page audited.** Failed audits are free.

### Why bring your own key?

Google's PageSpeed Insights API is free: 25,000 audits per day per key, and 400 per 100 seconds. Without a key, every caller shares one tiny global quota that is almost always exhausted, so keyless runs usually fail. With your key, audits run under your own quota and your own agreement with Google ([Google APIs Terms of Service](https://developers.google.com/terms)). This Actor adds batching, retries, sitemap discovery and clean output on top. The key is stored encrypted as a secret input, sent to Google only in a request header, and never logged or written to the output.

#### How to get a free PageSpeed Insights API key (about 2 minutes)

1. Open the [Google Cloud console](https://console.cloud.google.com/) and select or create 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**.
4. Recommended: under **API restrictions**, restrict the key to the PageSpeed Insights API.
5. Paste the key into this Actor's **Google API key** field.

### How to run a bulk PageSpeed test

1. Add pages to **Page URLs**, and/or domains to **Audit pages from sitemaps** (for example `example.com` audits up to 50 pages from its sitemap).
2. Paste your **Google API key**.
3. Pick a **Device**: mobile, desktop or both.
4. Click **Start**. Export the results as CSV/Excel, or schedule the Actor weekly to track Core Web Vitals over time.

### Input example

```json
{
  "urls": ["https://example.com/", "https://example.com/pricing"],
  "sitemapUrls": ["example.com"],
  "maxUrlsPerSitemap": 50,
  "sitemapUrlPatterns": ["/products/"],
  "apiKey": "YOUR_GOOGLE_API_KEY",
  "strategy": "both",
  "categories": ["performance", "accessibility", "best-practices", "seo"],
  "topOpportunities": 5
}
```

| Field | What it does | Default |
|---|---|---|
| `urls` | Pages to audit (a bare domain audits its homepage) | — |
| `apiKey` | Your Google API key (secret) | none (shared quota, usually exhausted) |
| `sitemapUrls` | Domains or sitemap URLs; their pages are audited | — |
| `maxUrlsPerSitemap` | Pages taken per sitemap source | 50 |
| `sitemapUrlPatterns` | Regexes; keep only matching sitemap URLs | all |
| `strategy` | `mobile`, `desktop` or `both` (both = 2 audits per page) | mobile |
| `categories` | Lighthouse categories to score | all four |
| `topOpportunities` | Biggest fixes to return per page (0–20) | 5 |
| `includeOriginFieldData` | Site-wide real-user metrics too | true |
| `locale` | Language of audit titles (`en`, `de`, …) | en |
| `maxConcurrency` | Audits in parallel (1–10) | 4 |

### Output example

One dataset item per page × device. Here is the output shape, with values taken from Google's own Lighthouse sample report (`lighthouse/core/test/results/sample_v2.json`, Lighthouse 13.5), shortened:

```json
{
  "url": "https://www.example.com/",
  "strategy": "mobile",
  "status": "ok",
  "performanceScore": 32,
  "scores": { "performance": 32, "accessibility": 75, "bestPractices": 31, "seo": 75 },
  "labMetrics": {
    "firstContentfulPaintMs": 6795, "largestContentfulPaintMs": 10885, "totalBlockingTimeMs": 1055,
    "cumulativeLayoutShift": 0.1, "speedIndexMs": 8296, "timeToInteractiveMs": 8012, "serverResponseTimeMs": 8
  },
  "fieldDataSource": "url",
  "fieldData": {
    "lcpP75Ms": 2100, "lcpCategory": "FAST", "inpP75Ms": 250, "inpCategory": "AVERAGE",
    "clsP75": 0.05, "clsCategory": "FAST", "overallCategory": "AVERAGE", "coreWebVitalsAssessment": "failed"
  },
  "originFieldData": { "inpP75Ms": 150, "overallCategory": "FAST", "coreWebVitalsAssessment": "passed" },
  "opportunities": [
    { "id": "cache-insight", "title": "Use efficient cache lifetimes", "estimatedSavingsMs": 3100, "metricSavings": { "LCP": 3100 } },
    { "id": "image-delivery-insight", "title": "Improve image delivery", "estimatedSavingsMs": 1200, "metricSavings": { "LCP": 1200 } }
  ],
  "lighthouseVersion": "13.5.0",
  "analyzedAt": "2026-10-07T12:00:00.000Z",
  "error": null
}
```

- **Field vs lab data:** `fieldData` is what real Chrome users experienced over the last 28 days. It is only available for pages and sites with enough traffic. `fieldDataSource` tells you whether it's page-level (`url`) or a site-wide fallback (`origin`), and is `null` when there's no data. `labMetrics` come from a single simulated Lighthouse load and vary between runs.
- **`coreWebVitalsAssessment`** is Google's pass/fail: `passed` when LCP, INP and CLS are all "good" at the 75th percentile.
- Failed audits are returned with `status: "failed"` and a plain-English `error` (e.g. `FAILED_DOCUMENT_REQUEST` when Google couldn't load the page). They aren't charged.
- The **Overview** dataset view is a one-row-per-audit table for spreadsheets.

### Pricing

Pay per event, with no platform usage charges on top:

| Event | Price |
|---|---|
| Page audited (`page-audited`), per page per device | $0.001 |

Examples: 100 pages on mobile cost $0.10; on both devices $0.20. A 50-page sitemap audit on both devices costs $0.10. Failed audits, invalid URLs, key and quota errors are free. Google's API itself is free under your key's quota.

### Use cases

- **SEO and web agencies:** monthly Core Web Vitals reports across all client sites in one run.
- **Ecommerce:** audit every product and category page from the sitemap and find the slowest templates.
- **Developers:** track performance after deployments with a scheduled run and export to your BI tool.
- **AI agents (MCP):** "Is example.com passing Core Web Vitals on mobile?" in one call.

### Error handling

- Transient API errors (HTTP 429 per-minute limits, 5xx, timeouts) are retried with backoff. Lighthouse page errors get one retry.
- If your key is invalid, the API isn't enabled, or the daily quota is used up, the Actor **stops immediately**. The remaining pages are listed as failed (free) with the reason, so you don't burn retries.

### Limits

- Results come from Google's PageSpeed Insights servers and locations, not from your users' network. Lab scores fluctuate from run to run; compare medians or field data for decisions.
- Pages behind a login or blocking Google's Lighthouse user agent can't be audited.
- Each page × device is one API call. Your key allows 25,000 per day by default; check quotas in your Google Cloud console.
- Up to 10,000 audits per run.

### FAQ

#### Is this an official Google product?

No. It's an independent Actor that calls Google's public, documented PageSpeed Insights API with your key. "PageSpeed Insights" and "Lighthouse" are Google's names for that service and tool.

#### Can I run it without an API key?

It will try Google's shared no-key quota, but that is exhausted most of the time. Expect free failed rows telling you to add a key.

#### Does it read my sitemap politely?

Yes. Sitemap reading uses the same engine as our [Sitemap URL Extractor](https://apify.com/ventura_workalong/sitemap-url-extractor): robots.txt is honored, 1 request per second per site, and gzip, indexes and broken XML are handled.

### Related Actors

- [Sitemap URL Extractor](https://apify.com/ventura_workalong/sitemap-url-extractor): get every URL of a site.
- [Tech Stack Detector](https://apify.com/ventura_workalong/tech-stack-detector): CMS, frameworks, analytics and CDN behind a site.
- [WHOIS Domain Lookup with DNS, SSL & Security Headers](https://apify.com/ventura_workalong/domain-lookup-bundle).

Questions or a page that won't audit? Open an issue with the URL. We respond fast.

# Actor input Schema

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

Pages to audit, e.g. `https://example.com/pricing`. A bare domain audits its homepage.

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

Your own free key: Google Cloud console > APIs & Services > enable 'PageSpeed Insights API' > Credentials > Create API key (about 2 minutes; 25,000 audits/day free). Without a key the Actor tries Google's shared no-key quota, which is almost always exhausted. Stored encrypted; never logged or returned.

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

Optional: domains or sitemap URLs. Page URLs are read from the site's sitemap (found via robots.txt or /sitemap.xml) and audited, up to the limit below per site.

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

Upper limit on pages taken from each entry in 'Audit pages from sitemaps'.

## `sitemapUrlPatterns` (type: `array`):

Optional: keep only sitemap URLs matching one of these regular expressions, e.g. `/products/`.

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

Audit as mobile, desktop, or both (both = two audits per page, each charged).

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

Any of `performance`, `accessibility`, `best-practices`, `seo`. Same price either way.

## `topOpportunities` (type: `integer`):

How many of the biggest performance fixes (by estimated time saved) to return. 0 = none.

## `includeOriginFieldData` (type: `boolean`):

Also return the whole site's real-user (CrUX) metrics, useful when a page has too little traffic for page-level data.

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

Language for audit titles, e.g. `en`, `de`, `fr`. Default English.

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

Google allows 400 requests per 100 seconds per key; each audit takes 10-40 s, so 4-10 is safe.

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

When reading sitemaps, skip files robots.txt disallows. (The audits themselves are run by Google.)

## Actor input object example

```json
{
  "urls": [
    "https://apify.com"
  ],
  "sitemapUrls": [],
  "maxUrlsPerSitemap": 50,
  "sitemapUrlPatterns": [],
  "strategy": "mobile",
  "categories": [
    "performance",
    "accessibility",
    "best-practices",
    "seo"
  ],
  "topOpportunities": 5,
  "includeOriginFieldData": true,
  "maxConcurrency": 4,
  "respectRobotsTxt": true
}
```

# Actor output Schema

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

One item per page x device: Lighthouse scores, lab metrics, real-user Core Web Vitals and top opportunities. Failed audits are included (free) with the reason.

# 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("ventura_workalong/pagespeed-insights-bulk").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("ventura_workalong/pagespeed-insights-bulk").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 ventura_workalong/pagespeed-insights-bulk --silent --output-dataset

```

## MCP server setup

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

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/3hv8w0GD82ztwt9Kd/builds/mI5xRppHpJPW7dCan/openapi.json
