Lighthouse Audit: Core Web Vitals, SEO & Accessibility avatar

Lighthouse Audit: Core Web Vitals, SEO & Accessibility

Pricing

$40.00 / 1,000 lighthouse audits

Go to Apify Store
Lighthouse Audit: Core Web Vitals, SEO & Accessibility

Lighthouse Audit: Core Web Vitals, SEO & Accessibility

Run Lighthouse on any URL list: performance, accessibility, best-practices and SEO scores, lab Core Web Vitals, top fixes, HTML report. $40 per 1,000 audits.

Pricing

$40.00 / 1,000 lighthouse audits

Rating

0.0

(0)

Developer

Kaizoku Data

Kaizoku Data

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

3 hours ago

Last modified

Share

Run Lighthouse on a list of web pages and get one row per URL. Each row has the Performance, Accessibility, Best Practices and SEO scores (0–100), the lab Core Web Vitals (LCP, CLS, TBT, plus FCP, Speed Index and TTI), the top opportunities with their estimated savings, and the failed audits. Lighthouse's HTML report is optional. Lighthouse is the open-source npm package (Apache-2.0), run inside this Actor in its own Chromium. No Google API, no API key, no proxy.

Price: $40 per 1,000 audits ($0.04 each), plus Apify's default Actor-start event. Blocked, challenged, refused, failed and incomplete audits are free.

  • Four categories, one row: scores 0–100 for performance, accessibility, best practices and SEO. You can run fewer categories; they finish a little faster, but the price is the same.
  • Lab Core Web Vitals: LCP, CLS and TBT, plus FCP, Speed Index and TTI, in milliseconds. The top 10 opportunities come with estimated savings (ms and bytes), and up to 60 failed audits with their titles.
  • Mobile or desktop: Lighthouse's own presets, with its default simulated throttling.
  • Full detail when you need it: Include all audits adds every audit with its value and details. Save HTML report stores Lighthouse's own report and gives you a public link to it.
  • Quick start: press Start. The prefilled input audits https://books.toscrape.com/, a scraping sandbox, on mobile. It takes about 25 seconds and costs $0.04.

Lab scores vary between runs; compare like with like. This is a lab test in a cloud container with a shared CPU. Scores and timings move from run to run, and the Performance score most of all. A container's CPU is also slower than a typical desktop, so Total Blocking Time and the Performance score come out lower than on a fast laptop. These are not PageSpeed Insights numbers, and this Actor makes no claim to match them. They are also not field data from real users (CrUX). For tracking, compare runs of this Actor on the same device setting over time, and look at trends or medians across several runs rather than one number. Each row includes Lighthouse's benchmarkIndex (the CPU speed it measured), so you can spot an unusually slow run.

Safe and polite by design. robots.txt is read and obeyed for every page and every redirect hop. The browser's User-Agent says it is an automated Chrome and names this Actor. Every request a page makes goes through a guard that refuses private, internal and cloud-metadata addresses. Blocks and challenges become free rows: they are never retried or worked around.

What it does

For each URL:

  1. Guard. The URL must be http(s). Social-media, video and Google hosts are refused before any DNS lookup (platform), and so are private, loopback and link-local addresses (ssrf).
  2. robots.txt. The robots.txt of the page's origin is fetched once per run with the product token lighthouse-audit-actor and obeyed. A Crawl-delay is honoured in full, and pages on one host are loaded at most once per second.
  3. Fresh browser context. Each URL gets its own isolated context, with no cookies, cache or storage shared with other URLs. One Chromium is reused for the whole run, and the audits run one at a time, because parallel audits would share the CPU and distort every metric.
  4. Load. Lighthouse loads the page.
    • Every redirect hop, and every later navigation of the page itself, is checked against the same rules (platform list, addresses, robots.txt) before it is requested.
    • The main document's answer is checked before Lighthouse measures anything. A refusal (401, 403, 429, 503, 999), a Cloudflare challenge header, an HTTP error, a download or a non-HTML file gives a free row at once.
  5. Audit. Lighthouse runs the categories you chose, with its default settings for the device. It skips only the bf-cache audit (see Limits). A page that turns out to be a bot challenge or CAPTCHA wall is a free row.
  6. Row. The scores, metrics, opportunities and failed audits are written. With Save HTML report, the report is saved first. A row is charged only when every requested category has a score and the row (and report) is saved.

Input

FieldWhat it does
URLs (urls)Pages to audit, one per line, up to 100 per run. example.org becomes https://example.org/. Duplicates are audited once.
Device (device)mobile (default; Lighthouse's mobile preset with slow-4G and 4× CPU simulation) or desktop (Lighthouse's desktop preset).
Categories (categories)Any of performance, accessibility, best-practices, seo. Default: all four.
Throttling (throttling)simulated (default, and the only method offered). See Limits.
Include all audits (includeAudits)Default off. On: adds the audits array (every audit of the chosen categories, with its details cut to 20 items each, about 2 MB per row at most).
Save HTML report (saveHtmlReport)Default off. On: Lighthouse's HTML report is saved in the run's key-value store, and reportUrl links to it.

Example inputs

The prefilled example (one mobile audit, all four categories):

{ "urls": ["https://books.toscrape.com/"] }

Desktop audit of a few pages, with HTML reports to share with a client:

{
"urls": ["https://quotes.toscrape.com/", "https://www.python.org/", "https://www.w3.org/"],
"device": "desktop",
"saveHtmlReport": true
}

Accessibility and SEO only, with every audit's details for your own dashboard:

{
"urls": ["https://www.python.org/", "https://go.dev/"],
"categories": ["accessibility", "seo"],
"includeAudits": true
}

Output

One row per URL. This is a real row from the prefilled input (mobile, 2 GB of memory). Your numbers will differ from run to run:

{
"url": "https://books.toscrape.com/",
"requestedUrl": "https://books.toscrape.com/",
"finalUrl": "https://books.toscrape.com/",
"httpStatus": 200,
"title": "All products | Books to Scrape - Sandbox",
"status": "ok",
"billable": true,
"chargedEvent": "audit",
"device": "mobile",
"throttling": "simulated",
"categories": [
"performance",
"accessibility",
"best-practices",
"seo"
],
"performanceScore": 98,
"accessibilityScore": 85,
"bestPracticesScore": 73,
"seoScore": 91,
"lcpMs": 1840,
"cls": 0,
"tbtMs": 0,
"fcpMs": 1720,
"speedIndexMs": 3070,
"ttiMs": 1840,
"opportunities": [
{
"id": "font-display-insight",
"title": "Font display",
"savingsMs": 500,
"savingsBytes": 0,
"displayValue": "Est savings of 510 ms"
},
{
"id": "cache-insight",
"title": "Use efficient cache lifetimes",
"savingsMs": 450,
"savingsBytes": 0,
"displayValue": "Est savings of 324 KiB"
}
],
"failedAudits": [
{
"id": "color-contrast",
"title": "Background and foreground colors do not have a sufficient contrast ratio.",
"category": "accessibility",
"score": 0,
"displayValue": null
},
{
"id": "target-size",
"title": "Touch targets do not have sufficient size or spacing.",
"category": "accessibility",
"score": 0,
"displayValue": null
}
],
"audits": null,
"auditsTruncated": false,
"lighthouseVersion": "13.5.0",
"chromeVersion": "156.0.8078.4",
"benchmarkIndex": 764,
"runWarnings": [],
"reportKey": null,
"reportUrl": null,
"auditMs": 18556,
"pageBytes": 348597,
"pageRequests": 6,
"blockedRequests": 5,
"blockedHosts": [
"www.google.com (platform)"
],
"errorCode": null,
"message": null,
"auditedAt": "2026-10-26T17:48:26.167Z",
"urlKey": "https://books.toscrape.com/"
}

(The opportunities and failed audits are cut to 2 entries here; this row had 6 and 16. A row lists up to 10 and 60.)

  • Scores are Lighthouse's category scores × 100, rounded. A category you did not ask for is null.
  • Metrics are lab values from Lighthouse's simulation (throttling: simulated). They are only filled when Performance is requested.
  • opportunities are performance findings with an estimated saving: Lighthouse 13's insights and diagnostics, largest saving first.
  • failedAudits are scored audits below 0.9 (Lighthouse's "failed" threshold) in the requested categories, heaviest first. The performance metrics themselves are not repeated there.
  • runWarnings are Lighthouse's own warnings, for example when the page redirected or loaded too slowly to finish.
  • blockedHosts lists hosts the guard refused, with the reason. www.google.com (platform) appears in almost every row: it is Chrome's own warm-up connection to its default search engine, not a request of the page, and it is refused like any Google host.

Error codes (all free)

CodeMeaning
invalid-inputNot an http(s) URL, embedded credentials, or longer than 2,048 characters (file:, chrome:, javascript:, data: and the like are refused).
platformA social-media, video or Google host (YouTube, TikTok, Instagram, Facebook, X, Vimeo, SoundCloud, Spotify, Twitch, Reddit, LinkedIn, Google domains), also when reached by a redirect. Never contacted.
ssrfThe host is, or resolves to, a private, loopback, link-local, carrier-grade NAT or reserved address, also after a redirect or a page navigation.
robots-blockedrobots.txt disallows the page, or a redirect or navigation target, for this Actor. Not requested.
robots-unavailablerobots.txt answered 5xx or 429, or could not be read (tried twice). The page is not loaded without its rules.
slow-hostrobots.txt asks for a Crawl-delay over 30 s, or the run's 600 s of Crawl-delay waiting is used up. The delay is never shortened.
refusedThe page answered 401, 403, 429, 503 or 999. Not retried, and no other method is tried.
challengeA bot challenge or CAPTCHA wall (a Cloudflare challenge, hCaptcha or reCAPTCHA wall, PerimeterX, DataDome, or a bare "Access denied" page). Never solved or worked around.
host-skippedThe host refused or challenged 2 pages in this run, so it is not asked again.
httpAnother HTTP error (for example 404 or 500). An error page is not audited.
not-html, downloadThe URL is not an HTML page (for example a PDF), or it starts a file download.
dns, network, tlsThe name does not resolve, the connection failed, or the HTTPS certificate was not accepted.
timeoutThe page did not answer in time, stopped responding, or used up the audit's 120 s budget.
no-contentThe page painted nothing that Lighthouse could measure (NO_FCP).
incompleteLighthouse could not score a requested category because one of its audits errored. The row keeps what was measured but is not charged.
too-largeThe page downloaded more than 50 MB or made more than 1,500 requests.
redirects, invalid-urlMore than 5 redirects (HTTP or page-initiated), or a redirect to an unusable URL or port.
page-crashed, browser-crashedThe tab or the browser crashed, usually because the page needs more memory. The next URL gets a fresh browser.
navigation, lighthouse-errorAnother loading error, or Lighthouse could not audit the page.
report-too-large, store-failed, internalThe HTML report was over 20 MB or could not be saved, or an unexpected error in this Actor.

RUN_SUMMARY (key-value store record)

This record holds:

  • charged and free rows, and the charged events;
  • browser time (browserSecs, browserSecsUnpaid), bytes downloaded by pages, requests, and refused requests;
  • the Lighthouse and Chromium versions, browser launches and crashes;
  • errors by code;
  • stoppedBy: finished, max-charge, unpaid-work-cap, time-limit, migrating, aborted, browser-crashed, browser-launch or error.

Pricing

Pay per event: audit = $0.04, charged once for each URL with a complete Lighthouse result, after its row (and its HTML report, if asked) is saved. The price is the same for any device, any number of categories, and with or without the full audit list or the report.

These are free:

  • URLs whose page was blocked or showed a challenge;
  • URLs refused by robots.txt, the platform list or the address rules, and invalid URLs;
  • URLs that timed out, failed, crashed or gave an incomplete result.

There is no start fee of our own; Apify's default Actor-start event applies.

AuditsPrice
1 (the prefilled example)$0.04
10$0.40
100 (the per-run maximum)$4.00
1,000 (10 runs)$40

Set a maximum charge per run in the run options. The Actor stops cleanly before the next URL it could not pay for: that URL is not loaded. To protect you from paying for compute on bad lists, the run also stops when:

  • free rows reach 25 and outnumber the charged ones;
  • browser time spent on free rows passes 300 s plus 5 s per charged audit;
  • 300 MB were downloaded for free rows.

Memory. The default is 2 GB, which suits almost all pages. More memory also means more CPU on Apify, so audits finish sooner and simulated TBT comes out lower. The price per audit stays the same, but compare runs made with the same memory setting.

Use it via API, n8n or Make

Get an API token in Apify Console under Settings, API & Integrations, and keep it in an environment variable (APIFY_TOKEN below). Never paste it into shared code.

cURL (starts a run, waits and returns the rows; the synchronous endpoint waits up to 5 minutes, so use it for up to about 8 URLs):

curl -X POST "https://api.apify.com/v2/acts/ataism~lighthouse-audit/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"urls": ["https://books.toscrape.com/"], "device": "desktop"}'

Python (pip install "apify-client>=3"):

import os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("ataism/lighthouse-audit").call(run_input={
"urls": ["https://www.python.org/", "https://www.w3.org/"],
"device": "mobile",
"saveHtmlReport": True,
})
for row in client.dataset(run.default_dataset_id).iterate_items():
print(row["url"], row["performanceScore"], row["lcpMs"], row["reportUrl"], row["errorCode"])

(With apify-client versions before 3.0, call() returns a dict: use run["defaultDatasetId"].)

JavaScript (npm install apify-client):

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('ataism/lighthouse-audit').call({
urls: ['https://books.toscrape.com/'],
categories: ['performance', 'seo'],
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const row of items) console.log(row.url, row.performanceScore, row.seoScore, row.lcpMs, row.cls);

n8n:

  1. Add the Apify node, operation Run an Actor and get dataset, Actor ataism/lighthouse-audit, input {"urls": ["https://your-site.example/"]}.
  2. Use performanceScore, lcpMs or failedAudits in the next node, for example to alert in Slack when a score drops below your threshold.

Make:

  1. Add the Apify module Run an Actor, choose ataism/lighthouse-audit, put your URLs in the input JSON and set Run synchronously to Yes.
  2. Add the Apify module Get Dataset Items and map the run's default dataset ID (one bundle per URL).
  3. Send url, the four scores and lcpMs to Google Sheets or Airtable to chart them over time.

Privacy, rights and terms

  • You are responsible for having the rights to test the pages you list. Audit your own sites, sites whose terms allow automated access, or uses your law permits. Nothing here is legal advice.
  • No logins, no paywalls, no consent clicking. The Actor sends no cookies or credentials of yours, never clicks anything and never fills in forms. A page behind a login is audited as a visitor without one sees it.
  • What the output contains: scores, timings, audit titles and values, and, with Include all audits, the audits' details. The details can quote parts of the page, such as element snippets, link texts and resource URLs. Email addresses, and phone numbers marked as such (a leading + or a word like "phone" or "tel"), are replaced with [email removed] and [phone removed] in the dataset, also in the page title. The HTML report is Lighthouse's own and is not edited: it shows the page's snippets and screenshots of the page as it loaded, so it contains whatever the page shows.
  • Public links. HTML reports are saved in your run's key-value store, and anyone who has their links can open them (like any Apify record URL). Delete the store, or keep the links private, if that matters to you.
  • Polite access. robots.txt is obeyed for every page and every redirect. The browser's User-Agent says HeadlessChrome and ends with lighthouse-audit-actor/0.1 (+https://apify.com/ataism/lighthouse-audit), on the page and on Lighthouse's own requests. Blocks and challenges are reported, never worked around. No proxies are used. Social-media, video and Google sites are refused.
  • Not Google's service. This Actor runs the open-source Lighthouse package itself. It does not call PageSpeed Insights or any other Google API, and it is not affiliated with or endorsed by Google.

Security

The browser loads pages from the open web, so the Actor treats each page as untrusted:

  • Every request of the page is guarded. The browser has no direct network access. Each request goes through a small guard proxy inside the run: the page, every redirect, iframes, scripts, images, fonts, fetch/XHR, WebSockets, preconnects, and Lighthouse's own fetches.
    • The guard resolves the host name itself and refuses private, loopback, link-local and reserved addresses (IPv4 and IPv6, including IPv4-mapped, NAT64 and 6to4).
    • It then connects to exactly the address it checked, so a name that changes its answer (DNS rebinding) gains nothing.
    • Chrome's own DNS is switched off, WebRTC is limited to the proxy, and QUIC (HTTP/3) is off.
    • Only ports 80, 443, 8080, 8443 and the page's own port are allowed.
    • HTTPS is not intercepted: Chrome checks certificates as usual.
  • Not just the first request. Redirects and page-initiated navigations are paused and checked before they are sent. If the page navigates away during the audit and that navigation is refused, the row is free.
  • Nothing from the input runs. Lighthouse runs its own audits. The only script this Actor adds to a page is its own fixed challenge check.
  • No downloads and no popups. Downloads are refused, and popups and new tabs are never opened (nothing they would load is requested). Lighthouse dismisses dialogs. Service workers cannot answer the page's navigations (they are bypassed, so every navigation is checked), and anything a service worker fetches goes through the same guard. Chrome's preloading is off: speculation rules cannot prefetch or prerender other pages.
  • The browser holds no secrets. Chromium gets an allowlisted environment, without the run's API token. It is controlled over a pipe, with no debugging port that a page could reach.
  • Bounded. Each audit has a hard 120 s budget. A page that does not stop has its browser restarted. Each page is also limited to 50 MB and 1,500 requests. A crashed tab or browser gives a free row, and the next URL gets a fresh one.

Limits and honest caveats

  • Lab scores vary between runs. See the note at the top. A single number is a sample; a trend or a median over several runs is a measurement.
  • Not PageSpeed Insights, not field data. PSI runs Lighthouse on Google's own hardware and network and adds real-user data (CrUX). This Actor does neither. Its numbers will differ from PSI's, often with a lower Performance score on mobile, because the container's CPU is slower than PSI's machines.
  • Simulated throttling only. Lighthouse's other methods load the page throttled or wait longer for it to settle, which roughly doubles the time per audit (measured: 11% of the $0.04 price in compute). They are not offered at this price.
  • No preloading: Chrome runs with its "no preloading" setting, so a page's speculation rules (prefetch and prerender of other pages) are not acted on. Chrome otherwise preloads only pages a visitor might open next. The page under test loads normally.
  • Back/forward cache: the bf-cache audit is skipped. It reloads the page through a browser page this Actor does not allow, and this Chrome runs with the back/forward cache off.
  • Google and social content inside pages: pages may embed resources from Google, YouTube, Facebook, X and the like, including Google Analytics and ad scripts. Those are not loaded. A page therefore loads a little lighter than for a real visitor, and Lighthouse's third-party findings will not list those hosts. Web fonts from fonts.googleapis.com and fonts.gstatic.com are the one exception: they are loaded, so text renders and is measured with its real font.
  • Bot protection: many large sites refuse automated browsers. Those rows are free (refused or challenge); the Actor will not try to get around them. Challenge detection is best-effort: a challenge served in an unusual way can still be audited and charged.
  • Time: an audit takes about 10–50 s at the default 2 GB (median about 14 s over 13 public pages). Heavy news and app home pages take the longest, up to about 80 s. Per run: 100 URLs and 55 minutes. A run that reaches the time limit stops cleanly with stoppedBy: time-limit; split long lists.

FAQ

Why is my Performance score lower than in PageSpeed Insights? Different hardware. Lighthouse simulates a mobile device from what it observes, and a cloud container's CPU is slower than Google's machines, so blocking time comes out higher. Compare runs of this Actor with each other, not with PSI.

Can I audit pages behind a login? No. The Actor sends no cookies or credentials and never fills in forms.

Can I get Lighthouse's JSON? Include all audits gives every audit of the chosen categories, bounded in size. The HTML report embeds Lighthouse's full JSON result.

Open-source components

  • lighthouse 13.5.0 (Apache-2.0), unmodified, with its default audits and scoring.
  • puppeteer-core 25.16.0 (Apache-2.0), to drive the Chromium that ships in Apify's actor-node-playwright-chrome image.
  • apify SDK 3.7.2 (Apache-2.0).

These packages bring their own dependencies, all used unmodified under permissive licences (MIT, ISC, BSD, Apache-2.0). The exceptions are axe-core (MPL-2.0, file-level copyleft, which Lighthouse uses for its accessibility audits) and caniuse-lite's data (CC-BY-4.0).

The rest is written in this repository: the guard proxy, robots.txt, the URL guard, challenge detection and the result summary.