# Best Damn PageSpeed Insights Audit (`josh99smith/pagespeed-insights-audit`) Actor

Audit hundreds of URLs with Google's official PageSpeed Insights API: Lighthouse performance, SEO and accessibility scores plus LCP, INP and CLS for mobile and desktop. Built-in API key, pay per page, failures free.

- **URL**: https://apify.com/josh99smith/pagespeed-insights-audit.md
- **Developed by:** [Joshua Smith](https://apify.com/josh99smith) (community)
- **Categories:** SEO tools, Developer tools, Open source
- **Stats:** 9 total users, 7 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$4.00 / 1,000 page auditeds

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

![pagespeed-insights-audit banner](https://raw.githubusercontent.com/josh99smith/apify-actor-assets/main/banners/pagespeed-insights-audit.png?v=bd1)

Audit any list of pages with the official **PageSpeed Insights API** and get back Core Web Vitals plus the **Lighthouse performance, accessibility, best-practices and SEO scores**, the lab metrics behind them (LCP, CLS, TBT, FCP, Speed Index, TTI) and real-user field data, for mobile and desktop, in one downloadable dataset.

Built for **SEO agencies, web developers and site owners** who need the same numbers as pagespeed.web.dev for dozens or thousands of URLs at once. You pay a flat price per audited page; pages Google cannot audit are reported free of charge.

### Features

- Check Core Web Vitals for a list of URLs in bulk
- Get Lighthouse performance, accessibility, SEO and best-practices scores via API
- Run PageSpeed Insights on mobile and desktop in one run
- Export PageSpeed scores to CSV, Excel or Google Sheets
- Get LCP, INP, CLS, TTFB field data from the Chrome UX Report
- List the top Lighthouse opportunities with estimated savings per page
- Schedule weekly PageSpeed monitoring for client websites
- Use your own Google PageSpeed API key for a dedicated quota

### What can you do with Best Damn PageSpeed Insights Audit?

- **Monitor client sites weekly**: schedule your clients' key landing pages and build a score history you can chart or alert on.
- **Before/after deploy checks**: run the same URL list before and after a release and diff the results.
- **Prospecting and sales reports**: show a prospect exactly where their pages lose points, with the top opportunities and estimated savings.
- **Portfolio-wide Core Web Vitals checks**: find the pages failing Google's "Good" thresholds in real-user data, the signal Google Search uses.
- **Competitive benchmarking** on mobile and desktop.
- **Feed dashboards and AI agents** through Google Sheets, Airtable, Make, Zapier or the Apify MCP server.

### How it works

For every URL and device strategy the Actor calls the official PageSpeed Insights API v5, exactly as pagespeed.web.dev does. Google runs Lighthouse on the page in its own data centre; nothing is scraped and no browser runs inside the Actor. The Actor reduces the large report to category scores (0 to 100), lab metrics, field data (when Google has enough real-user traffic for the page or its origin) and, optionally, the top failing audits.

Each audit takes Google roughly 10 to 30 seconds, so 100 URLs at the default concurrency finish in about 10 minutes. Two Lighthouse runs of the same page can differ by a few points.

### How to use it

1. Open the Actor and paste your page URLs into **Page URLs**, one per line.
2. Pick the **Device strategy**: mobile (what Google uses for ranking), desktop, or both.
3. Optionally narrow the **Lighthouse categories** and switch on **Include audit details** to get the top opportunities and failing audits.
4. Click **Start**. Results appear in the **Output** tab as they arrive; download them as JSON, CSV or Excel, or connect an integration.

```json
{
    "urls": ["https://example.com", "https://www.wikipedia.org"],
    "strategy": "both",
    "categories": ["performance", "accessibility", "best-practices", "seo"],
    "includeAuditDetails": true
}
```

### Use it from the API, Python, JavaScript or an AI agent

Audit a few URLs and get the results back in one HTTP call:

```bash
curl -X POST "https://api.apify.com/v2/acts/josh99smith~pagespeed-insights-audit/run-sync-get-dataset-items?token=<YOUR_API_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"urls": ["https://example.com"], "strategy": "mobile"}'
```

Python, with the `apify-client` package:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")
run = client.actor("josh99smith/pagespeed-insights-audit").call(
    run_input={"urls": ["https://example.com", "https://www.wikipedia.org"], "strategy": "both", "includeAuditDetails": True}
)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["url"], item["strategy"], item.get("scores"))
```

JavaScript or TypeScript, with the `apify-client` package:

```javascript
import { ApifyClient } from "apify-client";

const client = new ApifyClient({ token: "<YOUR_API_TOKEN>" });
const run = await client.actor("josh99smith/pagespeed-insights-audit").call({
    urls: ["https://example.com", "https://www.wikipedia.org"],
    strategy: "mobile",
    categories: ["performance", "seo"],
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

#### Use it from Claude, Cursor, ChatGPT or any MCP client

The Actor is exposed as a tool by the [Apify MCP server](https://mcp.apify.com), so an AI agent can call it by name. Add this to your MCP client configuration (Claude Desktop, Claude Code, Cursor, VS Code, Windsurf and others):

```json
{
    "mcpServers": {
        "apify": {
            "url": "https://mcp.apify.com?tools=josh99smith/pagespeed-insights-audit",
            "headers": { "Authorization": "Bearer <YOUR_API_TOKEN>" }
        }
    }
}
```

Then ask, for example: *"Audit https://example.com on mobile with josh99smith/pagespeed-insights-audit and list the top opportunities."* The agent fills in the input, runs the Actor and reads the dataset back; you pay the same per-result price as in the Console.

The Actor can also be scheduled, or connected to Zapier, Make, n8n and Google Sheets in the **Integrations** tab.

### Output

One record per URL and strategy. A successful record (trimmed):

```json
{
    "url": "https://example.com",
    "finalUrl": "https://example.com/",
    "strategy": "mobile",
    "success": true,
    "scores": { "performance": 72, "accessibility": 88, "bestPractices": 96, "seo": 100 },
    "labMetrics": { "fcpMs": 2144, "lcpMs": 3413, "cls": 0.042, "tbtMs": 420, "speedIndexMs": 3187, "ttiMs": 4902 },
    "fieldData": {
        "lcpMs": { "percentile": 2371, "category": "FAST" },
        "inpMs": { "percentile": 214, "category": "AVERAGE" },
        "cls": { "percentile": 0.05, "category": "FAST" },
        "fcpMs": { "percentile": 1312, "category": "FAST" },
        "ttfbMs": { "percentile": 612, "category": "FAST" },
        "overallCategory": "FAST",
        "originFallback": false
    },
    "opportunities": [
        {
            "id": "render-blocking-resources",
            "title": "Eliminate render-blocking resources",
            "savingsMs": 780,
            "savingsBytes": null,
            "displayValue": "Est savings of 780 ms"
        },
        {
            "id": "unused-javascript",
            "title": "Reduce unused JavaScript",
            "savingsMs": 450,
            "savingsBytes": 120832,
            "displayValue": "Est savings of 118 KiB"
        }
    ],
    "failedAudits": [
        {
            "id": "color-contrast",
            "title": "Background and foreground colors do not have a sufficient contrast ratio.",
            "category": "accessibility",
            "score": 0,
            "displayValue": "3 failing elements"
        }
    ],
    "lighthouseVersion": "12.8.2",
    "analysisTimestamp": "2026-09-18T20:41:07.512Z",
    "fetchedAt": "2026-09-18T20:41:21.203Z"
}
```

Pages that could not be audited are still recorded, so nothing silently disappears from your list:

```json
{
    "url": "https://this-domain-does-not-exist.example",
    "strategy": "mobile",
    "success": false,
    "errorType": "dns",
    "error": "Lighthouse could not audit the page (DNS_FAILURE): ...",
    "statusCode": 500,
    "fetchedAt": "..."
}
```

### Output fields

| Field                                     | Description                                                                                                                                                                                                                                                                                       |
| ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `url` / `finalUrl`                        | The URL you supplied and the URL Lighthouse ended on after redirects.                                                                                                                                                                                                                             |
| `strategy`                                | `mobile` or `desktop`.                                                                                                                                                                                                                                                                            |
| `success`                                 | `true` when Google returned a usable Lighthouse report. Only these records are billed.                                                                                                                                                                                                            |
| `scores`                                  | Lighthouse category scores as integers from 0 to 100 (`null` for categories you did not request). 90+ is "good", 50 to 89 "needs improvement".                                                                                                                                                    |
| `labMetrics`                              | Lighthouse lab measurements from Google's test device: FCP, LCP, CLS, TBT, Speed Index and TTI. Times in milliseconds.                                                                                                                                                                            |
| `fieldData`                               | Real-user Core Web Vitals from the Chrome UX Report (28-day 75th percentile): LCP, INP, CLS, FCP and TTFB, each with `percentile` and `category` (`FAST`, `AVERAGE`, `SLOW`), plus Google's `overallCategory`. `null` when the page has too little traffic; `originFallback` marks origin-level data. |
| `opportunities[]`                         | With **Include audit details**: failing performance audits with estimated `savingsMs` / `savingsBytes`, largest first, up to 15.                                                                                                                                                                  |
| `failedAudits[]`                          | With **Include audit details**: failing accessibility, best-practices and SEO audits, most heavily weighted first, up to 15.                                                                                                                                                                      |
| `lighthouseVersion` / `analysisTimestamp` | The Lighthouse version Google used and when the analysis ran.                                                                                                                                                                                                                                     |
| `errorType`                               | For failures: `invalid-url`, `rate-limited`, `http-error`, `dns`, `timeout`, `network`, `missing-api-key` or `other`.                                                                                                                                                                             |

### Pricing: how much does it cost to audit a page with PageSpeed Insights?

You pay a **flat price per successfully audited URL and strategy** (see the price next to the Start button). Auditing 100 URLs on mobile is 100 events; on both mobile and desktop it is 200. Invalid URLs, pages Google cannot load and quota errors cost nothing. There is no charge for Actor start-up, and the Actor stops automatically when it reaches the maximum cost you set for a run, so a large list never produces a surprise bill.

**How it compares (September 2026).** Actors that run their own headless Lighthouse charge $0.04 to $0.10 per page and, per Apify's public stats, fail on a quarter of runs; the cheapest alternative relies on an undocumented Google endpoint. This Actor calls the official PageSpeed Insights API at $0.004 per audit, handles many URLs per run on mobile and desktop, and never bills quota errors or pages Google could not load.

### API key and quota

By default the Actor uses a built-in Google API key shared by all its users. The PageSpeed Insights API is free but rate limited (25,000 requests per day and a few hundred per minute per key). For large or scheduled workloads, create your own free key in the [Google Cloud Console](https://developers.google.com/speed/docs/insights/v5/get-started) (enable the "PageSpeed Insights API", then create an API key) and paste it into the **Google API key** field. The key is stored encrypted and never written to the log or dataset. When a quota is exhausted you get free `rate-limited` failure records; retry later or use your own key.

### Tips

- **Mobile first**: Google Search ranks with mobile data; add `desktop` when the audience is mostly desktop.
- **Field data is the ranking signal**: `fieldData.overallCategory` reflects real users, `scores.performance` is a lab estimate. Fix field data first.
- **Variance**: for trend reports, audit on a schedule and look at the moving average rather than single runs.
- **Speed**: raise **Max concurrency** to 6 to 8 for large lists with your own API key. Higher values mostly produce per-minute quota errors.
- **Only what you need**: dropping unused categories makes each audit a little faster.
- **Short run timeouts**: each audit takes 10 to 30 seconds. If the run timeout is about to expire (common when an AI agent or scheduler starts runs with a short timeout), the Actor stops starting new audits, lists the rest as free `timeout` records and finishes normally, so you keep everything already audited.

### FAQ

#### Are the numbers identical to pagespeed.web.dev?

Yes: same API, same Lighthouse run in Google's data centre, subject only to the usual run-to-run variance.

#### Why is fieldData null for my page?

Google only publishes Chrome UX Report data for pages and origins with enough real-user traffic. Low-traffic pages have lab data only.

#### Can it audit pages behind a login, or a staging site?

No. Google's servers must be able to fetch the page publicly; protected or localhost pages fail with `http-error`.

#### Is this legal, and does it scrape Google?

No scraping is involved. The Actor uses Google's official, documented PageSpeed Insights API under its terms of service and audits only the public pages you specify.

#### How many URLs can I audit, and what happens when the quota is exhausted?

There is no hard limit on list size; the shared key allows a few hundred audits per minute and 25,000 per day across all users, and your own key gives you that quota to yourself. When a quota is exhausted, affected URLs are reported as free `rate-limited` failures and the run finishes normally.

#### Will the output fields change between runs?

No. Output fields are stable: existing fields are never renamed or removed without a major version bump announced in the changelog, and new fields are only ever added. You can build integrations on the schema without checking it after every run.

### Integrate Best Damn PageSpeed Insights Audit and automate your workflow

Best Damn PageSpeed Insights Audit plugs into the tools you already use through [Apify integrations](https://docs.apify.com/platform/integrations), so results can flow on without anyone downloading a file. Ready-made connectors include:

- [Make](https://docs.apify.com/platform/integrations/make)
- [Zapier](https://docs.apify.com/platform/integrations/zapier)
- [n8n](https://docs.apify.com/platform/integrations/n8n)
- [Slack](https://docs.apify.com/platform/integrations/slack)
- [Airbyte](https://docs.apify.com/platform/integrations/airbyte)
- [GitHub](https://docs.apify.com/platform/integrations/github)
- [Google Drive](https://docs.apify.com/platform/integrations/drive)
- and [many more](https://docs.apify.com/platform/integrations).

You can also attach [webhooks](https://docs.apify.com/platform/integrations/webhooks) to trigger your own endpoint whenever a run succeeds, fails or times out. For example, alert Slack when a page drops below your performance threshold, or log every audit to a Google Sheet for trend charts.

### Related Actors by the same developer

- [Best Damn Tech Stack Detector](https://apify.com/josh99smith/tech-stack-detector): find out what a website is built with.
- [Best Damn Website Screenshot API](https://apify.com/josh99smith/website-screenshot-api): full-page screenshots and PDFs of any URL.
- [Best Damn Google Autocomplete Scraper](https://apify.com/josh99smith/google-autocomplete-scraper): keyword suggestions from Google search.
- [Best Damn App Reviews Scraper](https://apify.com/josh99smith/app-reviews-scraper): App Store and Google Play reviews as JSON.
- [Best Damn Remote Jobs Aggregator](https://apify.com/josh99smith/remote-jobs-aggregator): remote job listings from five public boards.
- [Best Damn PDF Text Extractor](https://apify.com/josh99smith/pdf-text-extractor): text and metadata from PDF files.
- [Best Damn Sitemap URL Extractor](https://apify.com/josh99smith/sitemap-url-extractor): all URLs from XML sitemaps.
- [Best Damn RSS to JSON Converter](https://apify.com/josh99smith/rss-feed-to-json): RSS and Atom feeds as JSON.
- [Best Damn YouTube Comments Scraper](https://apify.com/josh99smith/youtube-comments-scraper): comments and replies from YouTube videos and channels.
- [Best Damn YouTube Scraper](https://apify.com/josh99smith/youtube-scraper): videos, channels, playlists and search results with statistics.

### Support and feedback

Found a page that fails unexpectedly, or a field you are missing? Open a ticket in the **Issues** tab of this Actor.

This Actor is open source under the MIT licence. PageSpeed Insights and Lighthouse are trademarks of Google LLC; this Actor is not affiliated with Google.

The full source code is on GitHub: [josh99smith/pagespeed-insights-audit](https://github.com/josh99smith/pagespeed-insights-audit). Stars and pull requests are welcome.

# Changelog

This Actor's version history is a separate document: https://apify.com/josh99smith/pagespeed-insights-audit/changelog.md

# Actor input Schema

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

One page per line (or a JSON array of URLs). The scheme is optional: `example.com` and `https://example.com` both work. Duplicates are removed automatically. Each audit takes Google roughly 10 to 30 seconds.

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

Run the audit with mobile emulation (what Google Search uses for ranking), desktop, or both (two results per URL).

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

Which Lighthouse categories to score. Fewer categories make each audit a little faster. Leaving the list empty selects all four.

## `includeAuditDetails` (type: `boolean`):

Add the top failing performance opportunities (with estimated time and byte savings) and the failing accessibility, best-practices and SEO audits to every result. Up to 15 of each.

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

Optional. Your own free PageSpeed Insights API key (Google Cloud Console > APIs & Services > Credentials, with the PageSpeed Insights API enabled). Without it the Actor uses a shared key with a shared daily quota; supplying your own key gives you a dedicated quota of 25,000 audits per day.

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

How many audits to request from Google in parallel. Each audit takes 10 to 30 seconds on Google's side, so 4 to 6 is a good balance; higher values increase the chance of hitting the per-minute quota.

## `timeoutSecs` (type: `integer`):

Give up on a single audit after this many seconds. Google occasionally needs more than a minute for very heavy pages.

## Actor input object example

```json
{
  "urls": [
    "https://example.com",
    "https://www.wikipedia.org"
  ],
  "strategy": "mobile",
  "categories": [
    "performance",
    "accessibility",
    "best-practices",
    "seo"
  ],
  "includeAuditDetails": false,
  "maxConcurrency": 4,
  "timeoutSecs": 120
}
```

# Actor output Schema

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

One record per URL and strategy with Lighthouse scores, lab metrics, Core Web Vitals field data and (optionally) the top failing audits.

## `summary` (type: `string`):

Counts of requested, audited, failed, skipped and billed audits.

# 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://example.com",
        "https://www.wikipedia.org"
    ],
    "categories": [
        "performance",
        "accessibility",
        "best-practices",
        "seo"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("josh99smith/pagespeed-insights-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://example.com",
        "https://www.wikipedia.org",
    ],
    "categories": [
        "performance",
        "accessibility",
        "best-practices",
        "seo",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("josh99smith/pagespeed-insights-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://example.com",
    "https://www.wikipedia.org"
  ],
  "categories": [
    "performance",
    "accessibility",
    "best-practices",
    "seo"
  ]
}' |
apify call josh99smith/pagespeed-insights-audit --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,josh99smith/pagespeed-insights-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/Bqbbwpv7i1cCNnybc/builds/JxpBLn6ILWmpiDf4Y/openapi.json
