Bulk Lighthouse Audit: PageSpeed, SEO & CWV avatar

Bulk Lighthouse Audit: PageSpeed, SEO & CWV

Pricing

from $25.00 / 1,000 successful url audits

Go to Apify Store
Bulk Lighthouse Audit: PageSpeed, SEO & CWV

Bulk Lighthouse Audit: PageSpeed, SEO & CWV

Run Lighthouse on up to 50 public URLs in one batch: performance, accessibility, best-practices and SEO score plus Core Web Vitals (LCP, CLS, TBT, FCP). Our own Chrome, so no Google API key, PageSpeed quota or baseline. Monitor mode confirms regressions over two runs.

Pricing

from $25.00 / 1,000 successful url audits

Rating

0.0

(0)

Developer

Vadim Bezrukov

Vadim Bezrukov

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Share

Paste up to 50 public URLs and get one Lighthouse row per page: performance, accessibility, best-practices and SEO scores, plus the Core Web Vitals lab metrics LCP, CLS, TBT and FCP. A batch audit needs no baseline, no Google API key and no PageSpeed Insights quota: every audit runs in our own Chrome with open-source Lighthouse.

Run it once for a site review, or switch to monitor mode and run it on a schedule. Monitor mode saves a last-good baseline per URL and confirms a performance regression only when two runs in a row breach it. A timeout or a blocked page never looks like a recovery.

Quick start: audit 10 pages in one run

{
"urls": [
{"url": "https://example.com", "externalId": "home"},
{"url": "https://example.com/pricing", "externalId": "pricing"},
{"url": "https://example.com/blog", "externalId": "blog"},
{"url": "https://example.com/contact", "externalId": "contact"},
{"url": "https://example.com/about", "externalId": "about"},
{"url": "https://example.org", "externalId": "org-home"},
{"url": "https://example.org/docs", "externalId": "org-docs"},
{"url": "https://example.net", "externalId": "net-home"},
{"url": "https://example.net/shop", "externalId": "net-shop"},
{"url": "https://example.net/help", "externalId": "net-help"}
],
"mode": "snapshot",
"formFactor": "mobile"
}

Replace the example URLs with your own pages. All four categories are on by default; pick fewer in Lighthouse categories if you only need some. Performance and Core Web Vitals always run, because the row status and the charge depend on them.

One row of the result (shortened; values differ per page and run):

{
"external_id": "home",
"status": "SUCCESS",
"requested_url": "https://example.com",
"form_factor": "mobile",
"performance_score": 96,
"accessibility_score": 88,
"best_practices_score": 100,
"seo_score": 90,
"lcp_ms": 1250,
"cls": 0.0,
"tbt_ms": 30,
"fcp_ms": 1100,
"category_errors": []
}

Scores use the 0-100 scale you know from Lighthouse reports. Open the Lighthouse scores Dataset view for the four scores side by side, or All URL audits for scores and Core Web Vitals together.

At $0.025 per successful audit, these 10 pages cost about $0.25. Set Maximum cost per run to at least $0.26 so every page fits in the budget.

Who uses this bulk Lighthouse audit?

  • SEO teams checking the SEO and accessibility score of every landing page before and after a release;
  • agencies reviewing a client portfolio in one run instead of one PageSpeed lookup per URL;
  • engineering teams that want a lab Core Web Vitals baseline and two-run confirmation before paging on noise;
  • webhook and MCP workflows that must tell UNCHANGED apart from TIMEOUT.

Monitor Core Web Vitals on a schedule

{
"urls": [{"url": "https://example.com", "externalId": "homepage"}],
"mode": "monitor",
"formFactor": "mobile"
}

The first successful monitor run creates a BASELINE. Run the same saved Task again and keep URL and form factor stable. A later breach of the performance thresholds is REGRESSION_PENDING until the next run confirms it (REGRESSION_CONFIRMED) or the metrics recover. Timeouts, HTTP errors, blocked pages and incomplete audits leave the last successful baseline intact. Monitor mode uses the named key-value store lighthouse-cwv-monitor-state.

Accessibility, best-practices and SEO scores are reported next to their previous value (previous_accessibility_score, previous_best_practices_score, previous_seo_score). They never raise an alert and never change the performance baseline, so adding or removing them keeps an existing monitor comparable.

Daily schedule

  1. Run a monitor input successfully once.
  2. In Apify Console, choose Save as task.
  3. Open Schedules, create a daily schedule, and select that Task.
  4. Keep URL and form factor unchanged.

Webhook on confirmed regressions

Attach an ACTOR.RUN.SUCCEEDED webhook to the scheduled Task. In the receiver, fetch the run dataset and act only on comparable successes:

const confirmed = datasetItems.filter(
(item) => item.status === 'SUCCESS' && item.monitor_event === 'REGRESSION_CONFIRMED',
);

Never treat a missing monitor_event or a failed status as unchanged.

Ready-made example Tasks

The default Actor input audits one public page, https://example.com.

More inputs

Desktop lab profile

{
"urls": [{"url": "https://example.com"}],
"mode": "monitor",
"formFactor": "desktop"
}

Mobile and desktop keep separate last-good baselines. A Lighthouse or Chrome major change rebases as PROFILE_CHANGED instead of a false regression.

Performance only

{
"urls": [{"url": "https://example.com"}],
"categories": ["performance"]
}

Only the performance score and Core Web Vitals are filled; the other score columns are null. The price per audit is the same.

Input reference

FieldDefaultMeaning
urlsrequired1-50 public HTTP(S) pages, with optional externalId
modesnapshotsnapshot does not touch monitor state; monitor compares successful audits
formFactormobileLighthouse mobile or desktop lab profile
categoriesall fourany of performance, accessibility, best-practices, seo; performance always runs

Concurrency, Chrome flags and proxy settings are not inputs. The Actor runs one Chrome, one audit at a time.

Query strings, including UTM parameters, are part of identity. www vs bare host is distinct. Trailing slashes are preserved. Fragments are dropped. Credentials and private/loopback hosts are rejected before Chrome starts.

Output and failure semantics

Every row carries source, stable source_id, source_url, scraped_at, schema_version and fingerprint, plus lab metrics, the four category scores and an explicit status. One bad URL does not stop the others: ten inputs always produce ten rows. Repeated normalized URLs share one audit: alias rows retain each external_id, carry duplicate_of, and incur no extra event charge.

If Lighthouse cannot score a requested category (for example because one of its audits errored), that score is null and category_errors says which category and why. The audit itself still counts as SUCCESS when performance and Core Web Vitals are complete.

Statuses:

  • SUCCESS - comparable lab audit with performance score, LCP, CLS, TBT, FCP and Chrome major;
  • INVALID_URL - rejected before Chrome access;
  • UNREACHABLE - DNS/connection failure;
  • HTTP_ERROR - document HTTP 4xx/5xx other than a block;
  • TIMEOUT - navigation or hard audit timeout; Chrome is recycled;
  • BLOCKED - HTTP 401/403/407/429 or a Chrome interstitial on a page that loaded. A refusal with an empty body shows Chrome's own error page and is reported as UNREACHABLE, because the page gives Lighthouse no status code;
  • AUDIT_FAILED - Lighthouse ran but the row is not comparable, including off-host redirects and missing lab metrics;
  • FAILED - spending-limit rejection, Chrome/worker start failure (WORKER_START_FAILED), corrupt monitor state, or an unexpected per-item error.

Monitor events on a classified row:

  • BASELINE - first comparable success for this URL and form factor;
  • UNCHANGED - performance metrics stayed inside the noise thresholds;
  • REGRESSION_PENDING - one breach; last-good is kept;
  • REGRESSION_CONFIRMED - two consecutive breaches;
  • RECOVERED - metrics returned after a confirmed regression;
  • PROFILE_CHANGED - form factor, Lighthouse version, Chrome major or throttling changed, so the baseline is rebased;
  • AUDIT_FAILED - the check is not comparable.

failed_audits lists the lowest-scoring performance audits and opportunities the largest load-time savings. See examples/sample_output.json for a complete row.

API use

Use the standard Apify Actor API with your own token. Never place a token in source control.

import os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("automa-flow/lighthouse-cwv-monitor").call(
run_input={
"urls": [{"url": "https://example.com", "externalId": "homepage"}],
"mode": "snapshot",
},
)
items = list(client.dataset(run["defaultDatasetId"]).iterate_items())

Use with AI agents through Apify MCP

Expose the Actor as a typed MCP tool:

https://mcp.apify.com?tools=automa-flow/lighthouse-cwv-monitor

Example prompt:

Run automa-flow/lighthouse-cwv-monitor in snapshot mode for these public
landing-page URLs on mobile. Report the performance, accessibility,
best-practices and SEO score of each page, and keep TIMEOUT or AUDIT_FAILED
rows separate from successful audits.

Agent budget before a call (plus the platform apify-actor-start of about $0.0002 at the 4 GiB default): 1 URL $0.025, 10 URLs $0.25, maximum 50 URLs $1.25. Set maxTotalChargeUsd to that url-audit bill plus start. A $0.25 cap is too low for 10 successful audits at 4 GiB ($0.2502). If the limit cannot cover every valid URL, Chrome never starts and each URL gets a free BILLING_LIMIT_TOO_LOW row.

Authenticated MCP execution uses the caller's Apify account and pay-per-event. Direct ?tools=automa-flow/lighthouse-cwv-monitor requires a token; anonymous search-actors can discover the public listing. Discovery via MCP is not the same as an autonomous paid run.

  • On-page SEO for the same site: Website SEO Audit audits noindex, canonical, metadata and broken-link issues and reports which ones appear or recover between runs.
  • Search traffic of the same sites: Website Traffic Checker returns monthly organic search traffic since 2015 and the Chrome popularity tier for up to 10,000 domains, to read next to your audit results.
  • Build the URL list: Sitemap Extractor returns every URL in a sitemap tree. Choose the pages you want to measure and pass them as urls.

Each Actor runs and charges separately. This Actor does not call them.

Pricing

The price is $0.025 per successful URL audit ($25 per 1,000), with all four category scores included. In monitor mode it also includes the comparison with last-good. Platform usage is included in this pay-per-event price; the Apify Console price shown at run time is canonical.

The Actor does not define a custom start event. Console PPE still applies the synthetic apify-actor-start at the platform default of $0.00005 per GB of allocated memory ($0.0002 at the 4 GiB default) and covers the first five seconds of compute. That is not url-audit.

Successful URL auditsurl-audit chargePlus apify-actor-start at 4 GiB
1$0.025≈ $0.0252
10$0.25≈ $0.2502
50$1.25≈ $1.2502
1,000$25.00≈ $25.0002

An unchanged monitor check is billable because the page was audited and compared. Invalid URLs, blocked pages, HTTP errors, timeouts, unreachable hosts, failed audits, retries and duplicate aliases are not charged. If a run's maximum total charge cannot cover every potentially successful URL, the Actor stops before launching Chrome, writes one free BILLING_LIMIT_TOO_LOW result per otherwise valid URL and fails the run. No last-good is advanced without a deliverable paid result.

A completed run is not replayed after resurrection. If output delivery was interrupted, the Actor retains existing output and stops with DELIVERY_UNCERTAIN; start a new run for a new observation. If every URL fails because of the target pages, the run still succeeds with the status message NO_SUCCESS and keeps the free error rows. It fails only when our own runtime broke, for example when Chrome could not start.

Known limitations

  • Lab Lighthouse is not field Core Web Vitals. Scores vary with Chrome, Lighthouse version, CPU and simulated throttling.
  • Default memory is 4 GiB. A heavy page can take a minute and lab scores move with CPU. Keep 4 GiB unless you have measured the page.
  • One Chrome, sequential audits, maximum 50 URLs per run. A slow page can take tens of seconds.
  • No proxy, login, cookie jar or CAPTCHA solving. Pages that require those will fail explicitly.
  • Off-host redirects are AUDIT_FAILED, not success. www to bare host on the same registrable host is allowed.
  • This Actor does not crawl a site, does not list every accessibility or SEO issue, and does not call the PageSpeed Insights API or return field CrUX data.

FAQ and troubleshooting

Is this PageSpeed Insights? No. PageSpeed Insights is a Google service with its own quota and a mix of field and lab data. This Actor runs the same open-source Lighthouse engine in Chrome against the URLs you paste, so you need no API key and hit no PageSpeed quota. Scores can differ from a PageSpeed lab run, because CPU and network conditions differ.

Why is my SEO score null? Lighthouse could not score that category, usually because one of its audits errored on the page. category_errors names the category. The performance audit and its charge are unaffected.

Why was my successful-looking page AUDIT_FAILED? Missing performance score, LCP, CLS, TBT, FCP or Chrome major, or an off-host finalUrl, cannot be compared. The last-good baseline is kept.

Why did one slow run not alert? A single breach is REGRESSION_PENDING. The next comparable run must also breach to become REGRESSION_CONFIRMED.

Can I audit localhost? No. Private, loopback and metadata hosts are rejected.

You control the URL list. The Actor fetches only those public HTTP(S) pages in a headless Chrome lab audit. It does not log in, store cookies for later reuse, or collect personal data beyond what the requested page already exposes in a Lighthouse report extract (URL, lab metrics, category scores, selected audit titles). Monitor state stores last-good metrics and the latest category scores in the named KVS lighthouse-cwv-monitor-state until you delete that store. Dataset rows follow your Apify storage retention.

Respect each site's terms and robots.txt. Do not use it to access accounts, paywalled content or private networks.

Release history

See the Changelog for every update.