# Lighthouse Audit: Core Web Vitals, SEO & Accessibility (`ataism/lighthouse-audit`) Actor

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.

- **URL**: https://apify.com/ataism/lighthouse-audit.md
- **Developed by:** [Kaizoku Data](https://apify.com/ataism) (community)
- **Categories:** SEO tools, Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$40.00 / 1,000 lighthouse audits

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

## Lighthouse Audit: Core Web Vitals, SEO & Accessibility

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](#limits-and-honest-caveats)). 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

| Field | What 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](#limits-and-honest-caveats). |
| **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):

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

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

```json
{
  "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:

```json
{
  "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:

```json
{
  "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)

| Code | Meaning |
|---|---|
| `invalid-input` | Not an http(s) URL, embedded credentials, or longer than 2,048 characters (`file:`, `chrome:`, `javascript:`, `data:` and the like are refused). |
| `platform` | A 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. |
| `ssrf` | The 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-blocked` | robots.txt disallows the page, or a redirect or navigation target, for this Actor. Not requested. |
| `robots-unavailable` | robots.txt answered 5xx or 429, or could not be read (tried twice). The page is not loaded without its rules. |
| `slow-host` | robots.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. |
| `refused` | The page answered 401, 403, 429, 503 or 999. Not retried, and no other method is tried. |
| `challenge` | A 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-skipped` | The host refused or challenged 2 pages in this run, so it is not asked again. |
| `http` | Another HTTP error (for example 404 or 500). An error page is not audited. |
| `not-html`, `download` | The URL is not an HTML page (for example a PDF), or it starts a file download. |
| `dns`, `network`, `tls` | The name does not resolve, the connection failed, or the HTTPS certificate was not accepted. |
| `timeout` | The page did not answer in time, stopped responding, or used up the audit's 120 s budget. |
| `no-content` | The page painted nothing that Lighthouse could measure (`NO_FCP`). |
| `incomplete` | Lighthouse could not score a requested category because one of its audits errored. The row keeps what was measured but is not charged. |
| `too-large` | The page downloaded more than 50 MB or made more than 1,500 requests. |
| `redirects`, `invalid-url` | More than 5 redirects (HTTP or page-initiated), or a redirect to an unusable URL or port. |
| `page-crashed`, `browser-crashed` | The tab or the browser crashed, usually because the page needs more memory. The next URL gets a fresh browser. |
| `navigation`, `lighthouse-error` | Another loading error, or Lighthouse could not audit the page. |
| `report-too-large`, `store-failed`, `internal` | The 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.

| Audits | Price |
|---|---|
| 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):

```bash
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"`):

```python
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`):

```js
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.

# Actor input Schema

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

Pages to audit, one per line, up to 100 per run (about 20-40 s each, one at a time). "example.org" becomes https://example.org/. Only http and https pages; private, internal, social-media, video and Google hosts are refused. Audit only pages you have the right to test.

## `device` (type: `string`):

mobile: Lighthouse's mobile emulation (412x823 screen, slow 4G and a 4x slower CPU in the simulation), as in Lighthouse's own default. desktop: Lighthouse's desktop preset (1350x940, fast connection, no CPU slowdown).

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

Which Lighthouse categories to run and score. Fewer categories finish faster; the price per audit is the same. Core Web Vitals and opportunities come with Performance.

## `throttling` (type: `string`):

simulated (the only method offered): Lighthouse's default. The page loads once without throttling and the metrics are simulated for the device's network and CPU. Observed or DevTools throttling roughly double the time per audit and are not offered at this price.

## `includeAudits` (type: `boolean`):

Off: a compact row (scores, metrics, top 10 opportunities, up to 60 failed audits). On: also every audit of the chosen categories with its score, value and details, cut to 20 items per audit and about 2 MB per row (screenshots are never included).

## `saveHtmlReport` (type: `boolean`):

Save Lighthouse's own HTML report for each audited page in the run's key-value store and put its public link in reportUrl. Anyone with the link can open it. The report includes screenshots of the page as it loaded.

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

Internal: "selfTest" runs the maintainer health check and saves no items.

## Actor input object example

```json
{
  "urls": [
    "https://books.toscrape.com/"
  ],
  "device": "mobile",
  "categories": [
    "performance",
    "accessibility",
    "best-practices",
    "seo"
  ],
  "throttling": "simulated",
  "includeAudits": false,
  "saveHtmlReport": false,
  "mode": "run"
}
```

# Actor output Schema

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

One item per URL: Lighthouse scores (0-100), lab metrics (LCP, CLS, TBT, FCP, Speed Index, TTI), top opportunities, failed audits, run warnings, and for free rows the error code and message (JSON, CSV, Excel or XML).

## `files` (type: `string`):

With Save HTML report: Lighthouse's HTML reports in the run's key-value store (keys report-<host>-<hash>-<options>.html).

## `runSummary` (type: `string`):

Charged and free rows, browser time, bytes, refused requests, errors by code, Lighthouse and Chromium versions, browser launches and why the run stopped.

# 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://books.toscrape.com/"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("ataism/lighthouse-audit").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://books.toscrape.com/"] }

# Run the Actor and wait for it to finish
run = client.actor("ataism/lighthouse-audit").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://books.toscrape.com/"
  ]
}' |
apify call ataism/lighthouse-audit --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,ataism/lighthouse-audit"
        }
    }
}
```

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/oBaxfLg91CYOvBbfH/builds/YeepnYfKtoTmNitYU/openapi.json
