# PageSpeed Checker — Core Web Vitals & Performance Score (`accountable_eel/site-performance-lookup`) Actor

Real Google PageSpeed Insights score and Core Web Vitals (LCP, CLS, FCP, TBT, Speed Index) for any domain or URL, one flat row per page. A per-domain enrichment column for lead lists, not a multi-page audit. Runs on Google's official PSI v5 API. Bring your own free key for a higher rate limit.

- **URL**: https://apify.com/accountable\_eel/site-performance-lookup.md
- **Developed by:** [Adrian Voss](https://apify.com/accountable_eel) (community)
- **Categories:** Developer tools, Lead generation
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 domain scoreds

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Site Performance Lookup — PageSpeed Score & Core Web Vitals

**Paste a list of domains or URLs. Get back one row per page with the real Google PageSpeed Insights performance score and Core Web Vitals — Largest Contentful Paint, Cumulative Layout Shift, First Contentful Paint, Total Blocking Time, and Speed Index.** Every row is a genuine Lighthouse run on Google's own infrastructure, the same engine behind Chrome DevTools and Search Console's Core Web Vitals report.

### Who it's for

- **Outbound and RevOps teams** enriching a prospect list with a technical buying signal — a slow site is a lead for a redesign, CRO, or hosting pitch.
- **Agencies and freelance developers** triaging which prospects have the worst Core Web Vitals before reaching out.
- **SEO and marketing teams** tracking page speed across a set of landing pages or competitor sites over time.
- **AI agents and automations** that need one structured performance score per URL, callable over plain HTTP.

### Why this one

Most "SEO audit" actors on Apify return a single heavy, nested report per page — every Lighthouse audit, every opportunity, every diagnostic. That's the right shape for auditing one site in depth, and the wrong shape for scoring hundreds of prospects, where you just need the numbers to sort and filter on.

This actor asks a narrower question on purpose: **one input page → one flat output row**, sized and priced as an enrichment column, not an audit tool.

- **Flat, score-focused columns** — no nested audit-by-audit dump to parse.
- **Never charged for a miss.** A page PageSpeed Insights can't analyze costs you nothing.
- **Mobile by default.** Matches Google's own default strategy for Core Web Vitals, with desktop available per run.
- **Bring your own free API key.** The shared unauthenticated quota is confirmed at 0 requests/day; a personal key from Google raises it to 25,000 requests/day at no cost.

### What you get

One dataset row per input, with these columns (all included by default; select fewer with the `columns` input):

| Column | Meaning |
| --- | --- |
| `performanceScore` | Lighthouse's overall performance score, 0-100 |
| `lcpMs` | Largest Contentful Paint, in milliseconds |
| `clsScore` | Cumulative Layout Shift, unitless |
| `fcpMs` | First Contentful Paint, in milliseconds |
| `tbtMs` | Total Blocking Time, in milliseconds |
| `speedIndexMs` | Speed Index, in milliseconds |
| `strategy` | Which device Lighthouse emulated for this row — `mobile` or `desktop` |
| `lighthouseVersion` | The Lighthouse engine version that produced the run |
| `fetchedAt` | When Google fetched and measured the page |

### How to use

1. **In the Apify Console.** Open the actor page and click **Start** — the `urls` field is already pre-filled with a working example. Results land in the run's dataset as soon as each item is found.
2. **Via the API.** Call it directly with a POST request — no Console needed once you have an API token:
   ```bash
   curl "https://api.apify.com/v2/acts/accountable_eel~site-performance-lookup/run-sync-get-dataset-items?token=%3CYOUR_TOKEN%3E" \
     -X POST \
     -H "Content-Type: application/json" \
     -d '{"urls":["example.com"]}'
   ```
3. **On a schedule.** Save this actor as an Apify **Task** with the input you want, then add a **Schedule** (hourly, daily, weekly) so it runs on its own — no server of your own required.

### Input

```json
{
  "urls": [
    "example.com"
  ]
}
```

One per line: a domain ("example.com") or a full URL ("https://example.com/pricing"). Each one gets a real Google PageSpeed Insights / Lighthouse run. Accepted formats: example.com, https://example.com/pricing.

Two extra run-level settings, next to the main input field: your own optional free **API key**, and **Strategy** (`mobile`, the default, or `desktop`).

### Output

| query | found | status | performanceScore | lcpMs | clsScore | fcpMs | tbtMs | speedIndexMs | strategy | lighthouseVersion | fetchedAt | scrapedAt |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| https://example.com | true | OK | 100 | 756 | 0 | 756 | 0 | 756 | mobile | 13.4.1 | 2026-08-31T06:01:06.193Z | 2026-08-31T06:01:11.288Z |

A miss comes back as a row with `"found": false` and is never charged.

### Pricing

$4 per 1,000 domains or URLs, plus a $0.00005 start fee. Misses (`found:false`) are never charged.

### Use it from Clay, n8n, Make, or an AI agent

This actor runs synchronously over plain HTTP — call it directly from a script, a workflow tool, or an AI agent, no Apify Console needed once you have an API token.

```bash
curl "https://api.apify.com/v2/acts/accountable_eel~site-performance-lookup/run-sync-get-dataset-items?token=%3CYOUR_TOKEN%3E" \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{"urls":["example.com"]}'
```

**n8n.** Add an HTTP Request node: Method `POST`, URL `https://api.apify.com/v2/acts/accountable_eel~site-performance-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>`, Body Content Type `JSON`, JSON Body `{"urls":["example.com"]}` (swap in an expression from an earlier node for a real value).

**Clay.** Add an "HTTP API" column: Method `POST`, URL `https://api.apify.com/v2/acts/accountable_eel~site-performance-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>`, Body `{"urls":["{{domain or URL}}"]}`, mapping the row's domain or URL into the `urls` array.

**MCP.** In Claude, Cursor, or any MCP client with the Apify MCP server, ask for "Site Performance Lookup | Apify" — the agent will find and run this actor.

### Tips

- **Add your own free API key.** Run input > "Your free Google PageSpeed Insights API key" — get one at [Google's PSI v5 get-started page](https://developers.google.com/speed/docs/insights/v5/get-started). It's free, takes a minute, and raises your quota to 25,000 requests/day; without one, requests share Google's unauthenticated quota, which is confirmed at 0/day, so every row comes back `BLOCKED`.
- **Keep concurrency low.** Each item is a real Lighthouse run that takes Google's servers 10-30+ seconds — a high `maxConcurrency` mostly just queues requests against your own rate limit, it doesn't make results arrive faster.
- **Mobile and desktop scores differ a lot.** Mobile emulates a mid-tier phone on a throttled connection, so its scores are almost always lower than desktop for the same page — pick the strategy that matches what you're optimizing for (Google's own ranking signals are mobile-first).
- **A rate-limited row still shows up as `BLOCKED`, never as a silent gap.** Check the `message` column on any `found:false` row — it tells you whether to add a key, slow down, or that the page itself couldn't be analyzed.

### FAQ

**What does "not found" (`found: false`) actually mean?**
One of three things, distinguished in the `status` and `message` columns: the input wasn't a URL/domain (`BAD_FORMAT`), the request was rate-limited or an API key was rejected (`BLOCKED`), or PageSpeed Insights ran but couldn't produce a usable score for that page (`NOT_FOUND`). Misses are never charged.

**How fresh is the data?**
Every row is a live Lighthouse run performed at request time — not a cached or historical score. Scores can vary slightly run to run, the same way Google's own PageSpeed Insights website does.

**Do I need an API key?**
Yes, in practice. Google's shared unauthenticated PageSpeed Insights quota is confirmed at 0 requests/day — every row will come back `BLOCKED` without a key. Add your own free key in the run input (it's masked once saved) to get 25,000 requests/day at no cost.

**Why don't I get every Lighthouse audit, like the SEO/accessibility scores?**
This actor only requests the `performance` category, on purpose — it's built as a fast, flat enrichment column for a list of prospects, not a full-site audit tool. If you need the full audit breakdown for one site at a time, Google's own PageSpeed Insights website or a dedicated SEO audit actor is the better fit.

**Does mobile vs desktop change the price?**
No — both are priced the same per item; `strategy` just changes which Lighthouse run is performed.

### Related actors

- [Tech Stack Lookup](https://apify.com/accountable_eel/tech-stack-lookup) — what a website is built on (CMS, analytics, payments), another per-domain enrichment column.
- [Security Headers Lookup](https://apify.com/accountable_eel/security-headers-lookup) — HTTP security header grade for a domain.
- [Company Domain Enrichment](https://apify.com/accountable_eel/company-domain-enrichment) — RDAP, DNS, email route, tech and hiring signals for a domain in one call.

# Actor input Schema

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

One per line: a domain ("example.com") or a full URL ("https://example.com/pricing"). Each one gets a real Google PageSpeed Insights / Lighthouse run. Accepted formats: example.com, https://example.com/pricing. You're only charged for the ones we actually find — a miss costs nothing.

## `testRun` (type: `boolean`):

Turn this on to test your input on a small sample before running the full list. Turn it off to process everything.

## `onlyFound` (type: `boolean`):

Only keep rows where something was actually found. Misses are always free, whether or not you show them here.

## `includeKeywords` (type: `array`):

Optional. Only keep results that mention at least one of these words (e.g. a job title, a city, a product name). Leave empty to keep everything.

## `excludeKeywords` (type: `array`):

Optional. Drop any result that mentions one of these words. Leave empty to skip nothing.

## `maxResults` (type: `integer`):

Optional. Stop the run once this many results have been found — useful for a quick, cheap sample. Leave blank for no limit.

## `columns` (type: `array`):

Choose which pieces of information to include in each result row. All are included by default.

## `apiKey` (type: `string`):

Get one free at https://developers.google.com/speed/docs/insights/v5/get-started (25,000 requests/day). Without one, requests share Google's unauthenticated quota, which is very small and gets rate-limited fast — confirmed live at 0/day at build time.

## `strategy` (type: `string`):

Which device Lighthouse emulates for the run. Mobile matches what Google itself uses as the default for ranking-relevant Core Web Vitals.

## `maxConcurrency` (type: `integer`):

Parallel requests. Keep conservative — this target has no browser fallback, so getting blocked costs more than slow-and-steady.

## `proxyConfiguration` (type: `object`):

Apify Proxy config. Residential recommended for anti-bot-sensitive targets.

## Actor input object example

```json
{
  "urls": [
    "example.com"
  ],
  "testRun": false,
  "onlyFound": false,
  "includeKeywords": [],
  "excludeKeywords": [],
  "columns": [
    "performanceScore",
    "lcpMs",
    "clsScore",
    "fcpMs",
    "tbtMs",
    "speedIndexMs",
    "strategy",
    "lighthouseVersion",
    "fetchedAt"
  ],
  "strategy": "mobile",
  "maxConcurrency": 2,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (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": [
        "example.com"
    ],
    "includeKeywords": [],
    "excludeKeywords": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("accountable_eel/site-performance-lookup").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": ["example.com"],
    "includeKeywords": [],
    "excludeKeywords": [],
}

# Run the Actor and wait for it to finish
run = client.actor("accountable_eel/site-performance-lookup").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": [
    "example.com"
  ],
  "includeKeywords": [],
  "excludeKeywords": []
}' |
apify call accountable_eel/site-performance-lookup --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,accountable_eel/site-performance-lookup"
        }
    }
}

```

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/mPogiSd9FfTAiFLzS/builds/QMYFZkbdsGmjp6BPr/openapi.json
