# Core Web Vitals & PageSpeed Monitor – CrUX & Lighthouse (`datarelay/core-web-vitals-monitor`) Actor

Bulk Core Web Vitals & PageSpeed Insights monitor powered by Google's Chrome UX Report (CrUX) API, 25-week CrUX History and Lighthouse. Track LCP, INP, CLS, FCP and TTFB across URLs and sitemaps with regression alerts and Slack digests.

- **URL**: https://apify.com/datarelay/core-web-vitals-monitor.md
- **Developed by:** [DataRelay](https://apify.com/datarelay) (community)
- **Categories:** SEO tools, Developer tools, AI
- **Security:** Limited permissions
- **Stats:** 1 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.99 / 1,000 core web vitals field check (crux)s

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

## Core Web Vitals & PageSpeed Monitor – Real User CrUX, History & Lighthouse

Check **Core Web Vitals (LCP, INP, CLS, FCP, TTFB)** for any list of URLs or domains directly from Google's **Chrome UX
Report (CrUX) API** and **CrUX History API** (up to 40 weeks of weekly trends from the very first run), with optional
**PageSpeed Insights (Lighthouse)** audits for lab diagnostics. Schedule it with a `syncKey` to receive **regression
alerts in Slack or your workflow** whenever real-user metrics cross Google's thresholds or degrade.

### Why this Actor

- **Real Chrome user data first (`mode: "field"`).** Most PageSpeed tools run a slow Lighthouse lab test on every URL
  and read CrUX only as a side field of PageSpeed Insights — which Google has announced it will remove from the PSI API.
  This Actor queries the **Chrome UX Report API** and **CrUX History API** directly: thousands of URLs in minutes,
  28-day rolling p75 + good / needs-improvement / poor distributions, and a **25–40 week historical trend** on the very
  first run.
- **Page-level and domain-level data Together.** Smaller pages and subpages often lack URL-level CrUX traffic. Each row
  includes both `urlMetrics` and `originMetrics` (queried once per domain per run) with an explicit
  `fieldSource: "url" | "origin" | "none"`.
- **Redirect normalization before CrUX.** The CrUX API does not follow redirects (`http://wikipedia.org` returns 404,
  while `https://www.wikipedia.org/` has full data). This Actor resolves redirects and checks DNS/HTTP status before
  querying CrUX or PageSpeed Insights.
- **Noise-free monitoring alerts.** Single-run Lighthouse scores fluctuate by 5–28 points between identical runs. This
  Actor bases monitoring alerts (`syncKey`) on **stable 28-day CrUX field metrics**: it alerts when a page drops from
  `passed` to `failed`, crosses a Google threshold (`good` → `needs-improvement` / `poor`), or worsens by at least
  `minChangePercent`.
- **Lighthouse diagnosis when you need it (`mode: "audit"`).** Adds Google PageSpeed Insights v5 (Lighthouse 13): 4
  category scores (`performance`, `accessibility`, `bestPractices`, `seo`), lab metrics (`lcpMs`, `cls`, `tbtMs`,
  `fcpMs`, `speedIndexMs`, `ttfbMs`) and the top 3–5 actionable opportunities with estimated millisecond and byte
  savings.
- **Built-in sitemap discovery and domain report.** Pass `domains` with `fromSitemap: true` to automatically discover
  and check up to `maxPagesPerDomain` URLs from `/robots.txt` and `/sitemap.xml`. Every run writes a domain-level roll-up
  (`domainsReport`, `worstPages`, regressions) to `OUTPUT`.

### Who uses it

- **SEO & web performance teams**: track Core Web Vitals pass rates across key templates, product pages and sitemaps.
- **Agencies**: automated weekly client reports with 25–40 week CrUX trends and Slack regression digests.
- **Lead generation & sales**: enrich domain lists with real-user mobile speed (`cwvAssessment: "failed"`, slow LCP/INP)
  to find sites that need optimization.
- **AI agents & MCP workflows**: structured JSON records, clear `statusReason` codes and a run-level `OUTPUT` summary.

### Quick start

```json
{
    "urls": ["https://www.wikipedia.org/", "https://developer.chrome.com/"],
    "mode": "field",
    "devices": ["phone", "desktop"]
}
```

| Goal                                            | Input                                                                                                                               |
| ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| Fast real-user check (CrUX + 25-week trend)     | `{"urls": ["https://www.wikipedia.org/", "https://shopify.com/"], "mode": "field"}`                                                 |
| Full Lighthouse + CrUX audit                    | `{"urls": ["https://www.wikipedia.org/"], "mode": "audit", "devices": ["phone", "desktop"]}`                                        |
| Audit a domain from its sitemap                 | `{"domains": ["developer.chrome.com"], "fromSitemap": true, "maxPagesPerDomain": 25, "mode": "field"}`                              |
| Daily/weekly monitoring, deliver only changes   | `{"urls": ["https://www.wikipedia.org/"], "syncKey": "prod-sites", "onlyChanges": true}`                                            |
| Slack alerts when Core Web Vitals degrade       | `{"domains": ["example.com"], "fromSitemap": true, "syncKey": "client-a", "slackWebhookUrl": "https://hooks.slack.com/services/…"}` |
| 40-week historical CrUX trend                   | `{"urls": ["https://www.wikipedia.org/"], "historyWeeks": 40}`                                                                      |
| Strict custom thresholds (e.g. LCP ≤ 2000 ms)   | `{"urls": ["https://www.wikipedia.org/"], "lcpGoodMs": 2000, "inpGoodMs": 150}`                                                     |
| Large Lighthouse audit with your own Google key | `{"domains": ["example.com"], "fromSitemap": true, "maxPagesPerDomain": 250, "mode": "audit", "googleApiKey": "AIza…"}`             |

### Input

| Field                                    | What it does                                                                                                                                    |
| ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `urls`                                   | Page URLs to check. HTTP redirects are followed before querying CrUX and PSI.                                                                   |
| `domains`                                | Domains or origins (e.g. `wikipedia.org`). Checks the homepage and origin CrUX; combine with `fromSitemap: true` to sample pages from sitemaps. |
| `fromSitemap`, `maxPagesPerDomain`       | Discover URLs from `/robots.txt` and `/sitemap.xml` (including `<sitemapindex>`), up to `maxPagesPerDomain` (default 50).                       |
| `mode`                                   | `field` (default: CrUX + History API, fast) or `audit` (adds PageSpeed Insights Lighthouse lab audit).                                          |
| `devices`                                | `phone`, `desktop` (default both), plus `tablet` in `field` mode.                                                                               |
| `includeHistory`, `historyWeeks`         | Include weekly CrUX History trend (default on, 25 weeks; configurable 1–40 weeks).                                                              |
| `syncKey`, `onlyChanges`, `syncReset`    | Monitoring across runs in your account's key-value store (`cwv-monitor-sync-<key>`).                                                            |
| `minChangePercent`                       | Minimum percentage p75 worsening (default 10%) to flag a metric as degraded.                                                                    |
| `lcpGoodMs`, `lcpPoorMs`, `inp…`, `cls…` | Custom thresholds (defaults match Google's official Core Web Vitals thresholds: LCP 2500/4000 ms, INP 200/500 ms, CLS 0.1/0.25).                |
| `slackWebhookUrl`                        | Send the CWV digest to a Slack incoming webhook (encrypted secret).                                                                             |
| `googleApiKey`                           | Optional custom Google Cloud API key (`X-goog-api-key`). Recommended in `audit` mode for lists above ~200 pages.                                |
| `maxPages`, `maxRunSecs`                 | Cap on unique pages per run (default 200, max 2,000) and soft run time budget in seconds.                                                       |

#### Monitoring and scheduling

Set `syncKey` and schedule the Actor. The Actor stores compact metric state (p75 values, ratings, assessment, category
scores and timestamp — never full Lighthouse reports) in your account's key-value store `cwv-monitor-sync-<key>` (entries
kept for 180 days, up to 50,000 page × device pairs).

- **Schedule daily or weekly, not hourly.** Google updates the 28-day CrUX dataset once a day around 04:00 UTC, and CrUX
  History once a week on Mondays. Running more than once a day returns the same CrUX numbers.
- **Unchanged checks cost less.** When a monitored page's CrUX metrics have not changed since the previous check
  (`changeType: "unchanged"`), it is billed at the discounted `monitor-check-unchanged` rate instead of `field-check` or
  `audit`. Set `onlyChanges: true` to omit unchanged rows from the dataset so downstream automations receive only new or
  changed rows.

### Output

Each row in the default dataset is one `page × device` check:

```json
{
    "url": "https://www.wikipedia.org/",
    "finalUrl": "https://www.wikipedia.org/",
    "origin": "https://www.wikipedia.org",
    "device": "phone",
    "mode": "audit",
    "status": "ok",
    "statusReason": "ok",
    "statusDetail": null,
    "fieldSource": "url",
    "cwvAssessment": "passed",
    "collectionPeriod": { "firstDate": "2026-10-06", "lastDate": "2026-11-02" },
    "lcpP75Ms": 1301,
    "inpP75Ms": 100,
    "clsP75": 0,
    "fcpP75Ms": 1170,
    "ttfbP75Ms": 546,
    "fieldMetrics": {
        "lcp": { "p75": 1301, "good": 0.9161, "needsImprovement": 0.0538, "poor": 0.0302, "rating": "good" },
        "inp": { "p75": 100, "good": 0.9346, "needsImprovement": 0.0519, "poor": 0.0136, "rating": "good" },
        "cls": { "p75": 0, "good": 0.986, "needsImprovement": 0.0115, "poor": 0.0025, "rating": "good" },
        "fcp": { "p75": 1170, "good": 0.8714, "needsImprovement": 0.0822, "poor": 0.0464, "rating": "good" },
        "ttfb": { "p75": 546, "good": 0.8471, "needsImprovement": 0.109, "poor": 0.0439, "rating": "good" },
        "rtt": { "p75": 134, "good": 0.451, "needsImprovement": 0.4693, "poor": 0.0796, "rating": null }
    },
    "urlMetrics": { "...": "same shape as fieldMetrics" },
    "originMetrics": { "...": "same shape as fieldMetrics" },
    "trend": {
        "weeksAvailable": 25,
        "firstDate": "2026-05-16",
        "lastDate": "2026-10-31",
        "direction": "stable",
        "lcp": { "firstP75": 1295, "lastP75": 1297, "changePercent": 0.2, "direction": "stable" },
        "inp": { "firstP75": 99, "lastP75": 100, "changePercent": 1, "direction": "stable" },
        "cls": { "firstP75": 0, "lastP75": 0, "changePercent": 0, "direction": "stable" },
        "series": [
            { "endDate": "2026-10-31", "lcpP75": 1297, "inpP75": 100, "clsP75": 0, "fcpP75": 1168, "ttfbP75": 544 }
        ]
    },
    "labPerformanceScore": 96,
    "labCategories": { "performance": 96, "accessibility": 99, "bestPractices": 81, "seo": 100 },
    "labMetrics": { "lcpMs": 1120, "cls": 0, "tbtMs": 15, "fcpMs": 890, "speedIndexMs": 1150, "ttfbMs": 120 },
    "recommendations": [
        {
            "id": "document-latency-insight",
            "title": "Document request latency",
            "displayValue": "Est savings of 850 ms",
            "savingsMs": 850,
            "savingsBytes": null
        }
    ],
    "lighthouseWarnings": [],
    "lighthouseVersion": "13.6.0",
    "changeType": "first-check",
    "changedMetrics": [],
    "previousCheckedAt": null,
    "alerts": [],
    "source": "Chrome UX Report, Google, CC BY 4.0; Google PageSpeed Insights (Lighthouse)",
    "checkedAt": "2026-11-04T06:30:00.000Z"
}
```

The dataset provides four table views: **Overview**, **Field data (CrUX)**, **Lab audit (Lighthouse)** and **Alerts & Monitoring**.

#### Run report (`OUTPUT`)

Stored in the default key-value store as `OUTPUT`:

- `cwvByDevice`: counts of `passed`, `failed` and `insufficientData` per device (`phone`, `desktop`, `tablet`).
- `domainsReport`: per-origin summary with origin CWV assessment, p75 metrics, weekly trend direction, and how many
  checked pages on that domain passed or failed.
- `worstPages`: up to 10 slowest pages sorted by CWV failure and LCP p75.
- `degraded`, `improved`, `failedPages`: pages that worsened or improved since the previous run under `syncKey`.
- `noFieldDataUrls`: URLs that had neither URL-level nor origin-level CrUX data.
- `statusCounts`, `statusReasons`: breakdown of `ok`, `no-field-data`, `http-404`, `blocked-lab`, `dns-error`, `timeout`
  and `lab-error`.
- `requests`: request counts and rate-limit wait times for HTTP pre-checks, CrUX API and PageSpeed Insights API.

### Measured

Measured against live Google Chrome UX Report API and PageSpeed Insights v5 API (2026-11-04, 147 CrUX queries and 120
PSI audits across 32 diverse domains and subpages):

| What                                               | Result                                                                                                   |
| -------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| CrUX API response time                             | Median **0.45 s**; 0 server errors across 147 queries                                                    |
| CrUX coverage (32 diverse URLs: major, mid, small) | **72%** had URL-level data; **94%** had origin-level data (`fieldSource: "origin"` covers subpages)      |
| CrUX History availability                          | **100%** of URLs and origins with daily CrUX data also had full 40-week history                          |
| CrUX API vs PageSpeed Insights `loadingExperience` | **90 / 90 identical** p75 values                                                                         |
| PageSpeed Insights audit duration                  | Median **16.7 s**, p90 **61.7 s**, max **110.5 s** (heavy sites like `github.com` can exceed 100 s)      |
| Lighthouse score spread across 3 consecutive runs  | Median **4.5–5 pts**, max **17 pts** (mobile) and **28 pts** (desktop) — why alerts use CrUX, not lab    |
| Edge cases caught automatically                    | HTTP 404 pages (PSI scores them 90–100 with a warning), bot-blocked labs (`nytimes.com`), HTTP redirects |

### Pricing

Pay per event; platform compute usage is included.

| Event                     | Price (FREE / BRONZE) | SILVER / GOLD    | When                                                                                  |
| ------------------------- | --------------------- | ---------------- | ------------------------------------------------------------------------------------- |
| `run-start`               | $0.0045               | $0.0035 / $0.003 | Once per run, charged only when the run delivers at least one paid check              |
| `field-check`             | $1.95 per 1,000       | $1.50 / $0.99    | One `page × device` check with CrUX field data in `field` mode                        |
| `audit`                   | $3.90 per 1,000       | $3.20 / $2.50    | One `page × device` Lighthouse + CrUX audit in `audit` mode                           |
| `monitor-check-unchanged` | $0.95 per 1,000       | $0.75 / $0.50    | One monitored `page × device` check under `syncKey` whose CrUX metrics did not change |

| Typical job                                                        | Estimated cost (BRONZE) |
| ------------------------------------------------------------------ | ----------------------- |
| 100 URLs × 2 devices in `field` mode (200 checks + 25-wk history)  | ~$0.39                  |
| 50 URLs × 2 devices in `audit` mode (100 Lighthouse + CrUX)        | ~$0.39                  |
| Daily monitor of 100 URLs × 2 devices (all unchanged)              | ~$0.19                  |
| Pages without CrUX data (`no-field-data`), 404s, DNS or lab errors | **free ($0)**           |

**You never pay** for URLs without CrUX data in `field` mode (`no-field-data`), HTTP 404 pages, non-existent domains
(`dns-error`), pages that block Lighthouse (`blocked-lab`), timeouts or a run that delivers no billable results (no
start fee either).

### Limitations

- **Low-traffic pages have no URL-level CrUX data.** Google includes a URL or origin in the Chrome UX Report only when
  it is publicly discoverable and has sufficient real Chrome traffic. Product subpages and small sites often fall back
  to `fieldSource: "origin"`, and very small sites return `statusReason: "no-field-data"` (free of charge).
- **CrUX updates once a day (~04:00 UTC)** and reflects a 28-day rolling average (~2 days behind real time). CrUX
  History updates once a week on Mondays. Running `field` checks more than once a day returns the same numbers.
- **Lighthouse lab scores vary between runs.** In 3 back-to-back PSI runs on the same URL, Lighthouse performance scores
  varied by a median of 4.5–5 points and up to 28 points on complex pages. Treat `labCategories` and `labMetrics` as
  diagnostic snapshots, and rely on CrUX field metrics for regression alerts.
- **Google API quotas.** Google enforces 150 queries/min per Cloud project on the CrUX API (~3,000–4,500 pages/hour in
  `field` mode) and 30 queries/min (25,000/day) per project on the PageSpeed Insights API (~900 page × device audits/hour
  in `audit` mode). When multiple large runs share the built-in key, automatic pacing and 429 retries slow the run down
  rather than failing it (`OUTPUT.requests` reports any wait time). For `audit` runs over ~200 pages, supply your own
  free Google Cloud API key in `googleApiKey` for dedicated project quota.
- **Some sites block Lighthouse or time out.** Sites with strict bot protection (e.g. `nytimes.com`) return HTTP 403 to
  Lighthouse (`statusReason: "blocked-lab"`), and very heavy pages (e.g. `github.com`) can return HTTP 500 or time out
  after 150 s (`statusReason: "lab-error"`). In both cases, CrUX real-user metrics are still returned when available,
  and the failed lab audit is not charged.

### Data license and attribution

Field performance data in `fieldMetrics`, `urlMetrics`, `originMetrics` and `trend` is sourced from the
**Chrome UX Report, Google, licensed under the [Creative Commons Attribution 4.0 International License (CC BY 4.0)](https://creativecommons.org/licenses/by/4.0/)**. Every dataset row carries this attribution in the `source` field.

### Not affiliated with Google

This is an independent tool by DataRelay, not affiliated with, endorsed by, or sponsored by Google LLC.

### Usage statistics

The Actor sends anonymous run statistics to the developer (input options, counts of statuses and assessments, Google API
request counts, duration). Customer URLs, domains and your Apify user id are never sent — only keyed HMAC-SHA256 hashes
used to count repeated targets and distinct users. Custom API keys (`googleApiKey`) and Slack webhook URLs are never
logged or transmitted.

### Changelog

- 0.1 – Initial release: CrUX API + 40-week CrUX History, PageSpeed Insights v5 (Lighthouse), HTTP redirect & 404
  pre-checks, sitemap discovery, cross-run monitoring (`syncKey`) and Slack alert digests.

# Actor input Schema

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

List of page URLs to check (e.g. `https://www.wikipedia.org/`). Redirects (`http://` → `https://www.`) are resolved automatically before querying CrUX so redirected URLs do not return false 404s. Give at least one URL in `urls` or one domain in `domains`.

## `domains` (type: `array`):

List of domains or origins (e.g. `wikipedia.org`, `https://shopify.com`). Checks each domain's homepage and origin-level Core Web Vitals; enable `fromSitemap` to also discover and check pages from each domain's sitemap.

## `fromSitemap` (type: `boolean`):

For each entry in `domains`, read `/robots.txt` and `/sitemap.xml` (including `<sitemapindex>`) and check up to `maxPagesPerDomain` URLs.

## `maxPagesPerDomain` (type: `integer`):

Maximum number of URLs to take from each domain in `domains` when `fromSitemap` is enabled.

## `mode` (type: `string`):

`field` (default, fast and cheap): real Chrome user metrics from the Chrome UX Report (CrUX) API + weekly trend from CrUX History API. `audit`: adds a Google PageSpeed Insights (Lighthouse) lab audit with 4 category scores, lab metrics and actionable optimization recommendations.

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

Devices to check per page (`phone`, `desktop`, and in `field` mode optionally `tablet`). Each `(page, device)` pair produces one dataset row.

## `includeHistory` (type: `boolean`):

Fetch weekly historical p75 series (up to 40 weeks) from the CrUX History API and compute the trend direction (`improving`, `stable`, `worsening`) from the very first run.

## `historyWeeks` (type: `integer`):

Number of weekly collection periods to request from the CrUX History API (1–40; Google's default is 25).

## `syncKey` (type: `string`):

Name of the monitoring memory kept in your account (key-value store `cwv-monitor-sync-<key>`). Compares each page × device against its previous check, flags `changeType` (`first-check`, `worse`, `better`, `unchanged`) and generates regression alerts on stable CrUX metrics. Note: CrUX updates once daily (~04:00 UTC), so schedule runs daily or weekly.

## `onlyChanges` (type: `boolean`):

Monitoring: omit unchanged pages from the dataset so your integration receives only `first-check`, `worse` or `better` rows (unchanged checks are billed at the lower `monitor-check-unchanged` rate).

## `syncReset` (type: `boolean`):

Clear the saved state of `syncKey` before this run so all pages are treated as `first-check`.

## `minChangePercent` (type: `integer`):

Minimum percentage worsening in p75 (LCP, INP, CLS, FCP, TTFB) between runs (or across the history window) to flag a metric as changed/degraded, even if its good/needs-improvement/poor rating stayed the same.

## `lcpGoodMs` (type: `integer`):

Largest Contentful Paint p75 threshold for `good` (Google default: 2500 ms).

## `lcpPoorMs` (type: `integer`):

Largest Contentful Paint p75 threshold above which a page is rated `poor` (Google default: 4000 ms).

## `inpGoodMs` (type: `integer`):

Interaction to Next Paint p75 threshold for `good` (Google default: 200 ms).

## `inpPoorMs` (type: `integer`):

Interaction to Next Paint p75 threshold above which a page is rated `poor` (Google default: 500 ms).

## `clsGood` (type: `string`):

Cumulative Layout Shift p75 threshold for `good` (Google default: `0.1`).

## `clsPoor` (type: `string`):

Cumulative Layout Shift p75 threshold above which a page is rated `poor` (Google default: `0.25`).

## `slackWebhookUrl` (type: `string`):

Send the CWV alert digest to Slack via an incoming webhook (`https://hooks.slack.com/services/…`). In monitoring mode, sent only when at least one page degraded or improved. Stored encrypted.

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

Optional: use your own Google Cloud API key (with Chrome UX Report API and, for `audit` mode, PageSpeed Insights API enabled). Recommended when auditing more than ~200 pages in `audit` mode so your run uses your own 30 queries/min PageSpeed Insights project quota. Sent via the `X-goog-api-key` header and never logged.

## `maxPages` (type: `integer`):

Maximum number of unique URLs to check in this run (each checked across the selected `devices`). 0 = up to 2,000 pages.

## `maxRunSecs` (type: `integer`):

Stop starting new checks after this many seconds and keep what was already delivered. 0 = until the run timeout.

## Actor input object example

```json
{
  "urls": [
    "https://www.wikipedia.org/",
    "https://developer.chrome.com/"
  ],
  "fromSitemap": false,
  "maxPagesPerDomain": 50,
  "mode": "field",
  "devices": [
    "phone",
    "desktop"
  ],
  "includeHistory": true,
  "historyWeeks": 25,
  "onlyChanges": false,
  "syncReset": false,
  "minChangePercent": 10,
  "lcpGoodMs": 2500,
  "lcpPoorMs": 4000,
  "inpGoodMs": 200,
  "inpPoorMs": 500,
  "clsGood": "0.1",
  "clsPoor": "0.25",
  "maxPages": 10,
  "maxRunSecs": 0
}
```

# Actor output Schema

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

No description

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

No description

## `digest` (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 = {
    "urls": [
        "https://www.wikipedia.org/",
        "https://developer.chrome.com/"
    ],
    "mode": "field",
    "devices": [
        "phone",
        "desktop"
    ],
    "maxPages": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("datarelay/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 = {
    "urls": [
        "https://www.wikipedia.org/",
        "https://developer.chrome.com/",
    ],
    "mode": "field",
    "devices": [
        "phone",
        "desktop",
    ],
    "maxPages": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("datarelay/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 '{
  "urls": [
    "https://www.wikipedia.org/",
    "https://developer.chrome.com/"
  ],
  "mode": "field",
  "devices": [
    "phone",
    "desktop"
  ],
  "maxPages": 10
}' |
apify call datarelay/core-web-vitals-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,datarelay/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/6RyqB7qmfQW6fstoa/builds/3Srh2qSWVfOjzOufh/openapi.json
