# PageSpeed Insights Bulk Checker: Lighthouse, Core Web Vitals (`rs-automation-labs/bulk-pagespeed-core-web-vitals-monitor`) Actor

Bulk PageSpeed Insights & Lighthouse audit for hundreds of URLs or a whole sitemap: a website speed test with all 4 Lighthouse scores, real-user Core Web Vitals (LCP, INP, CLS) pass/fail, top fixes, budget and regression alerts, Slack/webhook, HTML report. No API key. $3/1,000 URLs.

- **URL**: https://apify.com/rs-automation-labs/bulk-pagespeed-core-web-vitals-monitor.md
- **Developed by:** [RS Automation Labs](https://apify.com/rs-automation-labs) (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

$3.00 / 1,000 url analyzeds

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

Run a **bulk website speed test** on hundreds or thousands of URLs, or a whole sitemap, with Google's official **PageSpeed Insights (Lighthouse)** API and **Chrome UX Report** real-user data. For every page you get the four Lighthouse scores, lab metrics, real-user **Core Web Vitals (LCP, INP, CLS) pass/fail**, and a prioritized fix list in plain English. Set budgets, then get Slack or webhook alerts when a page misses them or gets slower than your last run. A shareable HTML report is included.

**No API key needed. $0.003 per URL check ($3 per 1,000). Failed checks are free.**

Built only on Google's official [PageSpeed Insights API v5](https://developers.google.com/speed/docs/insights/v5/get-started) and the [Chrome UX Report (CrUX) API](https://developer.chrome.com/docs/crux/api). No scraping, no headless browser to break, and the numbers match what you see on pagespeed.web.dev.

### What does this PageSpeed Insights bulk checker do?

- ⚡ **Bulk PageSpeed checks**: paste a list of URLs, upload a CSV/TXT file, or give it your **sitemap.xml** (sitemap indexes and `.xml.gz` work too).
- 📱 **Mobile, desktop or both**: one clean row per URL and device.
- 🏆 **All 4 Lighthouse scores**: Performance, Accessibility, Best Practices, SEO (0–100).
- 🧪 **Lab metrics**: LCP, CLS, TBT, FCP, Speed Index, TTI and server response time.
- 👥 **Real-user Core Web Vitals** (28-day p75 from the Chrome UX Report): LCP, INP, CLS, FCP and TTFB with Google's FAST / AVERAGE / SLOW ratings and a **Core Web Vitals passed: true/false** verdict. Falls back to origin-level data when a page has too little traffic.
- 🛠️ **What to fix first**: the top failing audits ranked by estimated time saved, in plain English (for example *"Serve images in WebP/AVIF ... (~1.2 s faster, ~955 KiB smaller)"*).
- 🚨 **Alerts**: set budgets such as *Performance < 70* or *LCP > 2500 ms* and the pages that miss them get flagged.
- 📉 **Regression tracking**: compares every run with the previous one and flags pages whose score dropped or whose LCP, TBT or CLS got worse.
- 🔔 **Webhook notifications**: Slack, Google Chat, Discord, Zapier, Make, n8n or your own endpoint.
- 📊 **HTML report + JSON summary**: averages, medians, Core Web Vitals pass rate, worst pages and the most common issues across the site.
- 🧯 **Bad URLs don't break the run.** Invalid, private or unreachable URLs come back as rows with a clear error code, and you aren't charged for them.

### Use cases: who runs a bulk PageSpeed / Lighthouse audit?

**SEO agencies and consultants**

- Audit a client's whole sitemap in minutes and hand over the HTML report.
- Monitor Core Web Vitals for many clients on a schedule (one `monitorId` per client) and get a Slack ping when something regresses.
- Use the "most common issues" list to estimate the work in a proposal.

**Developers and performance engineers**

- Check every important template after a deploy and catch regressions before Google does.
- Call it from CI through the Apify API and fail the build when `alerts` is not empty.
- Get the raw Lighthouse JSON (`saveFullReports`) for deeper analysis.

**Marketers and site owners**

- Find out which landing pages are slow on mobile, where most of your paid traffic lands.
- Benchmark your pages against competitors' pages in one table.
- Export to Excel or Google Sheets without writing code.

### Why this Actor?

| | This Actor | Typical bulk PageSpeed tools |
|---|---|---|
| Official Google APIs only | ✅ PSI v5 + CrUX API | often PSI only, sometimes scraping |
| Real-user CWV with pass/fail | ✅ CrUX API, URL → origin fallback | PSI field data only, which Google plans to remove from PSI |
| Prioritized, plain-English fix list with savings | ✅ | raw audit IDs or nothing |
| Threshold alerts + regression detection | ✅ built in | ❌ |
| Slack/webhook alerts | ✅ | ❌ |
| HTML report + summary | ✅ | ❌ |
| Sitemap input | ✅ (indexes, gzip) | sometimes |
| Failed URLs | free error rows | sometimes charged or crash the run |

### Bulk Lighthouse vs PageSpeed Insights vs website speed test tools

This Actor runs **Google PageSpeed Insights**, which means Lighthouse executed on Google's own servers, and adds **real-user Core Web Vitals** from the Chrome UX Report API. The scores are the ones you'd get on pagespeed.web.dev, just for many URLs at once with alerts and history. It is **not** a self-hosted Lighthouse: you can't change throttling or the test location (Google uses a simulated mid-range phone on a throttled network for mobile, from US servers). If you need custom throttling, private pages or multi-location tests, a self-hosted Lighthouse or a dedicated speed-test service is the better fit.

### How to use it

1. Click **Try for free**.
2. Paste your URLs (or add a sitemap URL).
3. Optional: paste your own **free Google API key** for bigger and faster runs ([2-minute guide below](#how-to-get-a-free-google-api-key)). Without one, the Actor's built-in key is used.
4. Pick **Mobile**, **Desktop** or **Both**, then click **Start**.
5. Open the **Overview** table, download CSV/Excel/JSON, or open the **HTML report** under *Storage → Key-value store → REPORT*.

To monitor over time, turn on **Compare with previous run**, set a few **alert thresholds**, add a **Slack webhook URL**, and [schedule](https://docs.apify.com/platform/schedules) the Actor daily or weekly.

### Input example

```json
{
  "startUrls": [
    { "url": "https://example.com" },
    { "url": "https://www.wikipedia.org" },
    { "url": "https://web.dev" }
  ],
  "sitemapUrls": ["https://www.yoursite.com/sitemap.xml"],
  "maxSitemapUrls": 200,
  "strategy": "both",
  "categories": ["performance", "accessibility", "best-practices", "seo"],
  "minPerformanceScore": 70,
  "maxLcpMs": 2500,
  "failOnCoreWebVitals": true,
  "compareWithPrevious": true,
  "monitorId": "client-acme",
  "webhookUrl": "https://hooks.slack.com/services/T000/B000/XXXX"
}
```

All fields except the URLs are optional. Leave a threshold empty to switch it off. No Google API key is needed. To add your own for faster runs, see [How to get a free Google API key](#how-to-get-a-free-google-api-key).

### Output example

You get one dataset row per URL and device. This is a real row from a cloud run on 22 Oct 2026 (python.org, mobile; the fix list is shortened to the top 2):

```json
{
  "url": "https://www.python.org/",
  "strategy": "mobile",
  "status": "ok",
  "finalUrl": "https://www.python.org/",
  "scores": {
    "performance": 81,
    "accessibility": 75,
    "bestPractices": 100,
    "seo": 92
  },
  "lab": {
    "lcpMs": 4051,
    "cls": 0.003,
    "tbtMs": 16,
    "fcpMs": 3017,
    "speedIndexMs": 3017,
    "ttiMs": 4051,
    "ttfbMs": 5
  },
  "field": {
    "source": "crux-url",
    "lcpP75Ms": 1270,
    "lcpCategory": "FAST",
    "inpP75Ms": 88,
    "inpCategory": "FAST",
    "clsP75": 0,
    "clsCategory": "FAST",
    "fcpP75Ms": 1198,
    "fcpCategory": "FAST",
    "ttfbP75Ms": 543,
    "ttfbCategory": "FAST",
    "coreWebVitalsPassed": true,
    "overallCategory": null,
    "collectionPeriod": {
      "firstDate": "2026-09-22",
      "lastDate": "2026-10-19"
    }
  },
  "fieldDataNote": null,
  "opportunities": [
    {
      "id": "render-blocking-insight",
      "title": "Render-blocking requests",
      "fix": "Stop CSS/JS from blocking the first paint: inline critical CSS, add defer/async to scripts and load the rest later.",
      "estimatedSavingsMs": 2400,
      "estimatedSavingsKiB": null,
      "estimatedClsReduction": null,
      "affectedMetrics": [
        "FCP",
        "LCP"
      ],
      "auditScore": 0,
      "displayValue": "Est savings of 2,380 ms",
      "savingsType": "load-time"
    },
    {
      "id": "unused-css-rules",
      "title": "Reduce unused CSS",
      "fix": "Remove unused CSS, or split CSS per page so each page loads only what it needs.",
      "estimatedSavingsMs": 750,
      "estimatedSavingsKiB": 128.2,
      "estimatedClsReduction": null,
      "affectedMetrics": [
        "FCP",
        "LCP"
      ],
      "auditScore": 0,
      "displayValue": "Est savings of 128 KiB",
      "savingsType": "load-time"
    }
  ],
  "fixList": "1. Stop CSS/JS from blocking the first paint: inline critical CSS, add defer/async to scripts and load the rest later. (~2.4 s faster)\n2. Remove unused CSS, or split CSS per page so each page loads only what it needs. (~750 ms faster, ~128 KiB smaller)",
  "alerts": [],
  "hasAlerts": false,
  "regression": {},
  "error": null,
  "psiReportUrl": "https://pagespeed.web.dev/report?url=https%3A%2F%2Fwww.python.org%2F&form_factor=mobile",
  "lighthouseVersion": "13.5.0",
  "analysisTimestamp": "2026-10-22T08:42:03.694Z",
  "checkedAt": "2026-10-22T08:42:17Z",
  "durationMs": 16663,
  "attempts": 1,
  "runWarnings": [],
  "lighthouseRuntimeError": null
}
```

#### Main fields

| Field | Meaning |
|---|---|
| `scores.performance / accessibility / bestPractices / seo` | Lighthouse scores, 0–100 |
| `lab.lcpMs, cls, tbtMs, fcpMs, speedIndexMs, ttiMs, ttfbMs` | Lighthouse lab metrics |
| `field.lcpP75Ms, inpP75Ms, clsP75, fcpP75Ms, ttfbP75Ms` | Real-user 75th percentile (Chrome UX Report, last 28 days) |
| `field.*Category` | Google's FAST / AVERAGE / SLOW rating |
| `field.coreWebVitalsPassed` | `true` if p75 LCP ≤ 2.5 s, INP ≤ 200 ms and CLS ≤ 0.1 (`null` = not enough traffic) |
| `field.source` | `crux-url`, `crux-origin`, `psi-url` or `psi-origin` (`field` is `{}` when no real-user data exists) |
| `opportunities[]` | Top fixes: `title`, plain-English `fix`, `estimatedSavingsMs`, `estimatedSavingsKiB`, `affectedMetrics` |
| `fixList` | The same fixes as numbered text, handy in CSV/Excel |
| `alerts[]` | Threshold violations with a readable `message` |
| `regression` | Deltas against the previous run and the list of `regressions` (`{}` when comparison is off or there is no previous result) |
| `error` | `null`, or `{code, message, httpStatus}` when the page could not be analyzed |
| `psiReportUrl` | Opens the same test on pagespeed.web.dev |
| `analysisTimestamp`, `checkedAt` | When Google ran Lighthouse, and when the Actor saved the row (UTC) |

#### Dataset views

- **Overview**: scores, key metrics, CWV verdict, alert and regression flags.
- **Details & fixes**: every lab and field metric plus the fix list.
- **Alerts, regressions & errors**: only the rows that need attention.

#### Key-value store

- `OUTPUT`: a JSON summary with average scores and median metrics per device, Core Web Vitals pass rate, the 10 worst pages, the most common issues, all alerts, regressions and errors.
- `REPORT`: a self-contained HTML report you can send to a client.

#### Error codes

| Code | What happened | Charged? |
|---|---|---|
| `INVALID_URL` | Malformed, non-http(s), localhost or private IP | No |
| `LIGHTHOUSE_ERRORED_DOCUMENT_REQUEST` | The page answered with an HTTP error (404, 500 ...) | No |
| `LIGHTHOUSE_FAILED_DOCUMENT_REQUEST`, `LIGHTHOUSE_DNS_FAILURE` | Google could not reach the site | No |
| `LIGHTHOUSE_NO_FCP` | Blank page, bot protection or extremely slow page | No |
| `RATE_LIMITED`, `GOOGLE_SERVER_ERROR`, `TIMEOUT` | Still failing after all retries | No |
| `DAILY_QUOTA_EXCEEDED` | The Google key's daily quota is used up | No |
| `API_KEY_INVALID` | Wrong key, or the API isn't enabled in your Google project | No |
| `SKIPPED_*` | Not attempted because the quota or your max cost was reached | No |

### Alerts, budgets and regression tracking (Core Web Vitals monitor)

- **Budgets:** `minPerformanceScore`, `maxLcpMs` and `failOnCoreWebVitals` flag every page that misses them, in `alerts[]` with a readable message.
- **Regressions:** turn on `compareWithPrevious` and keep the same `monitorId`. Each run is compared with the previous one, and pages whose score dropped or whose LCP, TBT or CLS got worse are listed in `regression`.
- **Notifications:** paste a Slack, Google Chat, Discord, Zapier, Make, n8n or custom webhook URL. By default it only posts when there are alerts or regressions.
- **Schedule** the Actor daily or weekly to turn it into a Core Web Vitals monitor.

### How much does a bulk PageSpeed test cost?

This Actor uses **pay-per-event** pricing. You pay a fixed price **only for each URL + device that was analyzed successfully** (`url-analyzed` event). There's no start fee and no monthly rental, and Apify platform usage is included.

- **Price: $0.003 per URL check, i.e. $3.00 per 1,000.** One check = one URL on one device (mobile or desktop).
- **No Google API key needed.** The built-in key is included in the price; add your own free key only for bigger or faster runs.
- **Failed checks are free**: invalid URLs, pages Google can't load, quota errors and skipped rows cost nothing.
- **Both** devices count as 2 results per URL.
- Set **Maximum cost per run** in the run options and the Actor stops cleanly at that budget. URLs that didn't fit are listed as free `SKIPPED_CHARGE_LIMIT_REACHED` rows.

| You analyze | You pay (at $0.003/URL) |
|---|---|
| 100 URLs | $0.30 |
| 1,000 URLs | $3.00 |
| 10,000 URLs | $30.00 |

The Google APIs themselves are free.

### How to get a free Google API key

A key gives you your **own quota of 25,000 checks per day** (about 240 per minute) and lets the Actor run 5–20 URLs in parallel. It takes about 2 minutes and costs nothing:

1. Open the [Google Cloud Console](https://console.cloud.google.com/) and sign in with any Google account.
2. Create a project (top bar → **New project**), or select an existing one.
3. Go to **APIs & Services → Library**, search for **PageSpeed Insights API** and click **Enable**.
4. Recommended: also enable the **Chrome UX Report API** to get better real-user data.
5. Go to **APIs & Services → Credentials → Create credentials → API key** and copy the key (it starts with `AIza`).
6. Recommended: click the key → **API restrictions → Restrict key** and select only the two APIs above.
7. Paste the key into the **Google API key** field. Apify stores it encrypted, and it is never written to the log or the results.

A billing account is **not** needed for these APIs. Google's quick link is on its [get-started page](https://developers.google.com/speed/docs/insights/v5/get-started#APIKey).

### FAQ

**Do I need a Google API key?**
No. The Actor has a built-in Google API key, so it works out of the box. That key's quota is shared by all users, so the Actor runs at most 3 URLs in parallel with it. For big or frequent runs, add your own free key: you get your own 25,000 checks a day and up to 20 parallel requests. If no key were available at all, Google's anonymous quota is often exhausted for the day, and the Actor would stop with a free `DAILY_QUOTA_EXCEEDED` row.

**Why are the scores slightly different from my last run?**
Lighthouse lab tests vary a little between runs because of network and server conditions. Regression detection ignores small changes by default (a score drop under 5 points or an LCP increase under 500 ms). You can tune both values.

**Why is `field` empty for some pages?**
The Chrome UX Report only has data for pages and sites with enough Chrome traffic. The Actor tries page-level data first, then the whole origin. If neither has enough traffic, `fieldDataNote` explains why the field is empty.

**What's the difference between lab and field data?**
Lab data comes from a single simulated Lighthouse load (a mid-range phone on a throttled network for mobile). Field data is what real Chrome users experienced over the last 28 days. **Google uses field data for ranking.**

**Can I test pages behind a login, on localhost or on staging?**
No. Google's servers load the page, so it must be publicly reachable. Private and local addresses are rejected upfront as free `INVALID_URL` rows.

**How fast is it?**
Google takes about 10–60 seconds per analysis. With your own key and 5 parallel requests, expect around 300–600 URL checks per hour. Raise **Parallel requests** for more speed.

**How do I get alerts in Slack?**
Create a Slack [incoming webhook](https://api.slack.com/messaging/webhooks) and paste its URL into **Alert webhook URL**. The payload has a `text` field, so Slack displays it as is. Discord (`content`), Zapier, Make and n8n work too.

**Can I monitor several clients separately?**
Yes. Give each scheduled task its own **Monitor ID** (for example `client-acme`). Each one keeps its own history.

**Is this the same score as pagespeed.web.dev?**
Yes, it uses the same PageSpeed Insights API. Lighthouse scores vary a little from run to run on PageSpeed Insights itself too, so compare trends rather than single points.

**Can I test a whole sitemap?**
Yes. Add the sitemap URL (sitemap indexes and `.xml.gz` work). Use **Max URLs from sitemaps** to cap how many pages are tested.

**Can I use it from an AI agent or MCP client?**
Yes. Like every Apify Actor, it can be called through Apify's MCP server or the API.

**Can I use it from code or CI?**
Yes. Use the [Apify API](https://docs.apify.com/api/v2) or the JavaScript/Python clients, run the Actor synchronously and read the dataset. You can fail your pipeline when any row has `hasAlerts: true`.

### Speed and limitations

- Google takes about 10–60 seconds per analysis. With the built-in key, at most 3 URLs run in parallel; with your own free key, up to 20 (about 300–600 checks per hour at 5 parallel).

- PageSpeed Insights tests one page load from Google's servers (US-based) with simulated throttling. That load is not your users' real network.

- Pages behind logins, paywalls, cookie walls that block bots, or IP allowlists can't be tested.

- The built-in key is shared by all users (max 3 parallel requests, 25,000 checks/day in total). For large or frequent jobs, use your own key.

- Your own key is limited to 25,000 checks a day and about 240 a minute, per Google Cloud project.

- Google has announced it will **remove real-user (CrUX) data from the PageSpeed Insights API**. This Actor already reads field data from the dedicated CrUX API, using your key or the built-in one.

- Fix advice is in English. Lighthouse audit titles follow the `locale` input.

### Support

Found a bug or missing a feature? Open an issue on the **Issues** tab of this Actor.

# Changelog

This Actor's version history is a separate document: https://apify.com/rs-automation-labs/bulk-pagespeed-core-web-vitals-monitor/changelog.md

# Actor input Schema

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

Pages to test. Paste one URL per line, upload a text/CSV file, or link to a remote list. URLs without https:// are fixed automatically, duplicates are removed, and invalid or private URLs (localhost, 192.168.x.x ...) are reported as free error rows instead of failing the run.

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

Sitemap or sitemap-index URLs (e.g. https://yoursite.com/sitemap.xml). Every page found is added to the list above. Gzipped sitemaps and nested sitemap indexes are supported.

## `maxSitemapUrls` (type: `integer`):

Upper limit of pages taken from each sitemap, so a huge sitemap can't create a surprise bill.

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

Hard cap on unique URLs analyzed in one run (after de-duplication). Each URL is checked once per device, so 'Both' doubles the number of results.

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

Run Lighthouse with mobile emulation, desktop, or both (one result row per device).

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

Which scores to compute. Fewer categories = slightly faster responses. Lab metrics and fix suggestions come from the Performance category.

## `googleApiKey` (type: `string`):

Optional. Leave empty to use the Actor's built-in key (shared by all users, max 3 parallel requests). Add your own free Google Cloud API key with the 'PageSpeed Insights API' (and optionally 'Chrome UX Report API') enabled to get your own 25,000 checks/day and up to 20 parallel requests. See the README for a 2-minute setup guide. The key is stored encrypted and never logged or saved in results.

## `includeCruxData` (type: `boolean`):

Query the Chrome UX Report API for real-user Core Web Vitals (p75 LCP, INP, CLS, FCP, TTFB) per page, falling back to the whole origin when a page has too little traffic. Google is phasing field data out of the PageSpeed API, so this keeps your field data reliable.

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

How many URLs to analyze at the same time (each Google analysis takes 10-60 s). Up to 20 with your own key; capped at 3 with the built-in key.

## `maxRetries` (type: `integer`):

Retries for temporary failures (rate limits, Google 5xx errors, timeouts) with exponential backoff. Pages that cannot load (404, DNS errors) are retried at most once.

## `requestTimeoutSecs` (type: `integer`):

How long to wait for Google to finish one analysis before retrying.

## `maxOpportunities` (type: `integer`):

Number of prioritized, plain-English fixes (with estimated time and size savings) returned for each page. 0 disables them.

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

Language for Lighthouse audit titles (e.g. en, de, fr, es, pt-BR). Fix advice is in English.

## `saveFullReports` (type: `boolean`):

Also save the complete PageSpeed API response of each page to the key-value store (key in 'fullReportKey'). Useful for developers; makes runs larger.

## `minPerformanceScore` (type: `integer`):

0-100. Leave empty to disable. Matching pages get an entry in 'alerts' and are listed in the summary and webhook.

## `minAccessibilityScore` (type: `integer`):

0-100. Leave empty to disable.

## `minBestPracticesScore` (type: `integer`):

0-100. Leave empty to disable.

## `minSeoScore` (type: `integer`):

0-100. Leave empty to disable.

## `maxLcpMs` (type: `integer`):

Largest Contentful Paint from the Lighthouse test. Google's 'good' limit is 2500 ms.

## `maxCls` (type: `number`):

Cumulative Layout Shift from the Lighthouse test, e.g. 0.1 (Google's 'good' limit).

## `maxTbtMs` (type: `integer`):

Total Blocking Time from the Lighthouse test. 200 ms is considered good.

## `maxFieldLcpMs` (type: `integer`):

Uses Chrome UX Report field data when available.

## `maxFieldInpMs` (type: `integer`):

Interaction to Next Paint. Google's 'good' limit is 200 ms.

## `maxFieldCls` (type: `number`):

Real-user p75 CLS from the Chrome UX Report, e.g. 0.1 (Google's 'good' limit).

## `failOnCoreWebVitals` (type: `boolean`):

Alert if real-user p75 LCP, INP or CLS is not 'good' (pages without field data are ignored).

## `compareWithPrevious` (type: `boolean`):

Remember results in a named key-value store and flag pages that got worse since the last run. Perfect for scheduled (daily/weekly) monitoring.

## `historyStoreName` (type: `string`):

Named key-value store that keeps the previous results (persists between runs on your account). Letters, digits and dashes.

## `monitorId` (type: `string`):

Separate histories for different clients/projects that share one store, e.g. 'client-acme'.

## `regressionScoreDrop` (type: `integer`):

A category score must fall by at least this many points to count as a regression. Lighthouse naturally varies by a few points between runs, so 5+ is recommended.

## `regressionLcpIncreaseMs` (type: `integer`):

Lab LCP must grow by at least this much to count as a regression.

## `webhookUrl` (type: `string`):

We POST a JSON summary here when the run finishes. It includes a 'text' field, so a Slack/Google Chat incoming-webhook URL works as is (Discord uses 'content', also included). Zapier/Make/n8n webhooks work too.

## `webhookOnlyOnIssues` (type: `boolean`):

Turn off to receive the summary after every run.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://example.com"
    },
    {
      "url": "https://www.wikipedia.org"
    },
    {
      "url": "https://web.dev"
    }
  ],
  "maxSitemapUrls": 100,
  "maxUrls": 1000,
  "strategy": "mobile",
  "categories": [
    "performance",
    "accessibility",
    "best-practices",
    "seo"
  ],
  "includeCruxData": true,
  "concurrency": 5,
  "maxRetries": 3,
  "requestTimeoutSecs": 120,
  "maxOpportunities": 5,
  "locale": "en",
  "saveFullReports": false,
  "failOnCoreWebVitals": false,
  "compareWithPrevious": false,
  "historyStoreName": "pagespeed-monitor-history",
  "monitorId": "default",
  "regressionScoreDrop": 5,
  "regressionLcpIncreaseMs": 500,
  "webhookOnlyOnIssues": true
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

## `details` (type: `string`):

No description

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

No description

## `summary` (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 = {
    "startUrls": [
        {
            "url": "https://example.com"
        },
        {
            "url": "https://www.wikipedia.org"
        },
        {
            "url": "https://web.dev"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("rs-automation-labs/bulk-pagespeed-core-web-vitals-monitor").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://example.com" },
        { "url": "https://www.wikipedia.org" },
        { "url": "https://web.dev" },
    ] }

# Run the Actor and wait for it to finish
run = client.actor("rs-automation-labs/bulk-pagespeed-core-web-vitals-monitor").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://example.com"
    },
    {
      "url": "https://www.wikipedia.org"
    },
    {
      "url": "https://web.dev"
    }
  ]
}' |
apify call rs-automation-labs/bulk-pagespeed-core-web-vitals-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,rs-automation-labs/bulk-pagespeed-core-web-vitals-monitor"
        }
    }
}
```

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/6tK7Nl7Mn68zAx1oq/builds/JCxVPaytRLWTy87sv/openapi.json
