# Lighthouse

Run a real Google Lighthouse audit against a page and get back the category scores and key performance metrics as JSON — with an option to include the full set of 150+ audits for deep diagnostics.

It uses no AI, and costs **2 credits** per call — a full audit holds a browser for far longer than a page fetch does. See [Credits](https://urlpipe.dev/docs/credits). Audits can take a while, so this one pairs well with [async mode](https://urlpipe.dev/docs/async).

POST/lighthouse

## Run an audit

### Body parameters

- **Name**
  : `url`
  **Type**
  : string
  **Required**
  : Required
  **Description**
  : The absolute URL of the page to process. Rendered with headless Chrome, so JavaScript runs and redirects are followed. It must not include a username or password (`https://user:pass@example.com`).
- **Name**
  : `device`
  **Type**
  : string
  **Description**
  : Device to emulate: `mobile` (default) or `desktop`.
- **Name**
  : `include_audits`
  **Type**
  : string
  **Description**
  : Set to `"true"` to include the full `audits` object (150+ audits). Defaults to `"false"`.
- **Name**
  : `residential`
  **Type**
  : boolean
  **Description**
  : Fetch the page from a [residential exit](https://urlpipe.dev/docs/residential) — an address on a home broadband line rather than one in a datacentre. Reach for it when a site serves you less than it serves a browser, or nothing at all. Defaults to `false`. Adds **25 credits** per page fetch on top of what the operation costs, and its results are kept separate from the ordinary ones.
- **Name**
  : `report_to`
  **Type**
  : string
  **Description**
  : Webhook URL — an `http` or `https` address URLpipe POSTs the result to when it's ready. **Optional**: without it we deliver to your project's [default endpoint](https://urlpipe.dev/docs/async#where-results-go) if it has one, and otherwise send no webhook at all — the result still waits for you at [GET /result/:token](https://urlpipe.dev/docs/results). A value we cannot deliver to returns `422`. Ignored on a `sync=true` request. Deliveries can be [signed](https://urlpipe.dev/docs/async#signature) so your endpoint can verify they came from us.
- **Name**
  : `sync`
  **Type**
  : boolean
  **Description**
  : Process the request synchronously, returning the result inline in the response. Defaults to `false` (async: return a token now, and either receive the result at a [webhook](https://urlpipe.dev/docs/async#where-results-go) or fetch it with [GET /result/:token](https://urlpipe.dev/docs/results)). See [Async & sync modes](https://urlpipe.dev/docs/async) for the full contract.
- **Name**
  : `max_age`
  **Type**
  : string | integer
  **Description**
  : How fresh a cached result must be to be accepted. Either an **integer** number of seconds (`3600`) or a **duration string** of the form `"<number> <unit>"` — units `s`/`min`/`h`/`d`/`w` (e.g. `"2 hours"`, `"3 days"`, `"30m"`). Defaults to `7 days`, clamped to a max of `30 days`; `0` always bypasses the cache. See [Caching](https://urlpipe.dev/docs/caching) for all accepted units.
- **Name**
  : `labels`
  **Type**
  : object
  **Description**
  : Your own keys to find and account for this request by — a client, a project, a campaign: `{"client": "acme"}`. Returned with the result, in the webhook and in the `X-Labels` header, and your dashboard filters history and totals credits by them. Up to 16 keys; string values. See [Labels](https://urlpipe.dev/docs/labels).

```
curl -X POST https://urlpipe.dev/lighthouse \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com", "device": "desktop"}'
```

Response

```
{
  "url": "https://example.com",
  "fetchTime": "2026-01-01T00:00:00.000Z",
  "device": "desktop",
  "categories": {
    "performance":   { "score": 0.95, "title": "Performance" },
    "accessibility": { "score": 0.88, "title": "Accessibility" },
    "best-practices":{ "score": 0.92, "title": "Best Practices" },
    "seo":           { "score": 0.90, "title": "SEO" },
    "pwa": null
  },
  "metrics": {
    "first-contentful-paint": {
      "score": 0.95, "displayValue": "1.2 s",
      "numericValue": 1200, "numericUnit": "millisecond"
    },
    "largest-contentful-paint": {
      "score": 0.90, "displayValue": "2.5 s",
      "numericValue": 2500, "numericUnit": "millisecond"
    },
    "cumulative-layout-shift": {
      "score": 1.0, "displayValue": "0.05",
      "numericValue": 0.05, "numericUnit": "unitless"
    },
    "total-blocking-time": {
      "score": 0.93, "displayValue": "150 ms",
      "numericValue": 150, "numericUnit": "millisecond"
    }
  }
}
```

## Category scores

Each category has a `score` from `0` to `1`. The `pwa` key is always `null`: Lighthouse no longer audits Progressive Web Apps, and the key stays so the response keeps one shape. Categories reported: `performance`, `accessibility`, `best-practices` and `seo`.

## Metrics

Each metric includes `score`, `displayValue`, `numericValue` and `numericUnit`. Any metric may be `null` if Lighthouse couldn't compute it.

## Device emulation

- **Name**
  : `mobile`
  **Type**
  : default
  **Description**
  : 360×640 viewport, 4× CPU slowdown, slow-4G network. Simulates real-world mobile conditions and typically produces lower scores.
- **Name**
  : `desktop`
  **Description**
  : 1350×940 viewport, no CPU throttling, fast network. Generally produces higher scores.

## Core Web Vitals & INP

LCP and CLS are included in `metrics`. INP (Interaction to Next Paint) is a **field** metric that needs real user interactions and can't be measured in a lab test like Lighthouse. Use `total-blocking-time` (TBT) as the lab proxy for responsiveness — it correlates strongly with INP.

## Full audit data

Pass `include_audits: "true"` to add an `audits` object with all 150+ Lighthouse audits — performance diagnostics (`render-blocking-resources`, `unused-css-rules`), accessibility checks (`color-contrast`, `image-alt`), SEO audits and best-practices. Each audit carries a score, title, description and often a `details` object listing the specific elements to fix.

The mobile and desktop audits — and audits with and without `include_audits` — are cached separately, since those options change the result. See [Caching](https://urlpipe.dev/docs/caching).

## Responses

Whatever the status, the response carries [metadata headers](https://urlpipe.dev/docs/response-headers): the result token, whether it was served from cache and how old that result is, how long we took, what it cost in credits, and the allowance you have left.

Status

When

Body

`200 OK`

The request succeeded.

Sync: the result, in this endpoint's format (see Response above). Async: a job token and the request's labels — { "token": "…", "status": "accepted", "labels": {} }.

`422 Unprocessable Entity`

The analysis failed, or a parameter was invalid (a bad max\_age, a screenshot\_options value out of range, labels that break the rules, or a report\_to we will not deliver to).

{ "error": "<message>" }

`429 Too Many Requests`

Three causes, told apart by the error field: concurrency\_limit (too many of your requests already running), rate\_limited (sending too fast), or quota\_exceeded (Free plan only — out of credits with no card on file to bill the extra to, and checked only on a cache miss; a paid plan keeps serving at the overage rate and is never refused for credits).

All three carry "error" and "message". Extra fields: concurrency\_limit → "limit", "running" · rate\_limited → "retry\_after" · quota\_exceeded → "limit", "used", "needed", "resets\_at".

`504 Gateway Timeout`

Sync only: the analysis didn't finish within 60s. It keeps running — fetch it via GET /result/:token.

{ "error": "processing\_timeout", "token": "…" }

`401 Unauthorized`

Missing or invalid API key.

{ "error": "invalid\_api\_key", "message": "…" }

Try it live — no API key needed

Run this endpoint against any URL right in your browser.

[Open tool](https://urlpipe.dev/tools/lighthouse-audit)

Source: https://urlpipe.dev/docs/lighthouse
