# Bulk PageSpeed / Lighthouse Audit (BYO Google key) (`steadfeed/bulk-pagespeed-audit`) Actor

Run Google PageSpeed Insights on many URLs at once. Core Web Vitals, Lighthouse scores, sitemap discovery. Bring your own free Google API key. By Steadfeed.

- **URL**: https://apify.com/steadfeed/bulk-pagespeed-audit.md
- **Developed by:** [Steadfeed](https://apify.com/steadfeed) (community)
- **Categories:** SEO tools, Developer tools
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 50.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 url successfully 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

## Bulk PageSpeed / Lighthouse Audit

Run [Google PageSpeed Insights](https://developers.google.com/speed/docs/insights/v5/get-started) (Lighthouse) on many public URLs in one Actor run. Give it a list of pages, a sitemap, or just a start page to crawl (same domain, up to a limit), test mobile and desktop, and get a readable report with aggregated scores. **Bring your own free Google API key** — this Actor does not sell Google quota.

Built by [Steadfeed](https://apify.com/steadfeed).

### What you get

For each URL × device strategy (`mobile` / `desktop`):

- Lighthouse category scores (performance, accessibility, best-practices, seo) as 0–100
- Core Web Vitals-style metrics (FCP, LCP, CLS, TBT, Speed Index, TTI) with display values
- Top performance opportunities (savings estimates)
- One dataset row per audit; a `SUMMARY` record with run totals **and aggregated scores** (average / min / max per category and device, good / needs-work / poor counts, weakest pages, most common opportunities)
- **`REPORT.html` and `REPORT.md`** in the run's key-value store: a summary table per device, a per-page score table, weakest pages and the opportunities that recur across your site. Open `REPORT.html` straight from the Output tab. No extra charge.

### Input

| Field | Required | Notes |
|---|---|---|
| `urls` | one of urls / sitemapUrls | Up to 50 public http(s) pages |
| `sitemapUrls` | one of urls / sitemapUrls | Up to 5 sitemap or sitemap-index URLs |
| `googleApiKey` | **yes** (unless `dryRun`) | Secret. Enable *PageSpeed Insights API* on a Google Cloud project |
| `strategy` | no | Default `["mobile"]`. Each strategy is a separate audit |
| `categories` | no | Default all four Lighthouse categories |
| `crawlStartUrls` | one of urls / sitemapUrls / crawlStartUrls | Up to 5 start pages. The Actor follows **same-domain** links (breadth-first, honouring robots.txt, skipping files such as PDFs and images) to find more pages |
| `maxCrawlPages` | no | Cap on crawled pages including the start pages. Default 20, max 100 |
| `crawlDepth` | no | Link hops from a start page. Default 2, max 4 |
| `crawlExcludePatterns` | no | Skip crawled URLs containing any of these fragments (e.g. `/tag/`, `/cart`) |
| `respectRobotsTxt` | no | Crawl only pages robots.txt allows (default true) |
| `generateReport` | no | Write `REPORT.html` / `REPORT.md` (default true) |
| `maxAudits` | no | Safety cap on URL × device audits per run. Default 200, max 500 |
| `maxUrlsFromSitemap` | no | Default 20 (max 100) |
| `dryRun` | no | Mock scores, no Google calls |

Private / localhost / credentialed URLs are rejected.

### Crawl and report example

```json
{
  "crawlStartUrls": ["https://example.com/"],
  "maxCrawlPages": 25,
  "crawlDepth": 2,
  "crawlExcludePatterns": ["/tag/", "/cart"],
  "strategy": ["mobile", "desktop"],
  "googleApiKey": "YOUR_KEY"
}
```

This audits up to 25 pages on mobile and desktop (up to 50 audits, about $0.20) and writes the report. Crawling only reads page links to find URLs; Google fetches the pages for the actual audit. Crawling is free; it adds no charge beyond the audits.

### Pricing (draft — not live until owner approval)

Pay-per-event proposal:

- **url-audited** — **$0.004** per successful audit (status `ok`)
- **Actor start** — $0.00005 (platform default)
- Failed / error rows are **not** charged
- `apify-default-dataset-item` is **not** used

Your Google PSI quota is billed by Google under their free tier / Cloud billing, not by Steadfeed.

### How to get a free Google API key

1. Open [Google Cloud Console](https://console.cloud.google.com/)
2. Create or pick a project
3. Enable **PageSpeed Insights API**
4. Create an API key; restrict it to that API if you can
5. Paste it into the Actor’s `googleApiKey` secret field

Without a key, Google’s anonymous shared quota is usually exhausted (HTTP 429).

### Limitations (honest)

- Results come from Google’s PSI service; they can differ slightly from a local Chrome Lighthouse run
- Sitemap discovery follows sitemap indexes **one level** deep and caps total URLs
- The crawler reads server-rendered HTML links only (no JavaScript rendering), stays on the start page's domain (`www.` is treated as the same domain), and does not log in
- This Actor does not log in, bypass paywalls, or render pages itself — Google fetches the URL
- Very large sites: pass a focused URL list or a section sitemap rather than the whole index

### Example

```json
{
  "urls": ["https://example.com/", "https://www.w3.org/"],
  "strategy": ["mobile"],
  "categories": ["performance", "seo"],
  "googleApiKey": "YOUR_KEY"
}
```

### Support

Store issues on the Actor page. No personal names in public assets.

# Changelog

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

# Actor input Schema

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

1–50 public http(s) page URLs. Combine with sitemapUrls if you want. Duplicate URLs are ignored.

## `sitemapUrls` (type: `array`):

Up to 5 public sitemap.xml or sitemap-index URLs. Discovered page URLs are merged with urls (capped by maxUrlsFromSitemap).

## `crawlStartUrls` (type: `array`):

Up to 5 start pages. The Actor follows same-domain links (breadth-first, honouring robots.txt) to discover more pages to audit, up to Max pages to crawl. Combine with URLs and sitemaps if you like.

## `maxCrawlPages` (type: `integer`):

Cap on pages discovered by crawling, including the start pages (1–100). Default 20.

## `crawlDepth` (type: `integer`):

How many link hops from a start page to follow (0–4). Default 2.

## `crawlExcludePatterns` (type: `array`):

Text fragments (case-insensitive). Crawled URLs containing any of them are skipped, for example /tag/, /cart, ?replytocom.

## `googleApiKey` (type: `string`):

Required for reliable runs. Create a free key in Google Cloud Console with the PageSpeed Insights API enabled. The key is a secret input and is never written to the dataset or logs by this Actor.

## `strategy` (type: `array`):

Lighthouse strategies to run. Default: mobile only. Each URL × strategy counts as one url-audited event when pricing is enabled.

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

Categories to request from PSI. Default: all four.

## `generateReport` (type: `boolean`):

Save REPORT.md and REPORT.html (score tables, averages, weakest pages, most common opportunities) in the run's key-value store. Default true. No extra charge.

## `maxUrlsFromSitemap` (type: `integer`):

Cap on page URLs discovered from sitemaps (1–100). Default 20.

## `maxAudits` (type: `integer`):

Safety cap on URL × device audits in one run (1–500). Default 200. Each successful audit is one url-audited event.

## `respectRobotsTxt` (type: `boolean`):

Crawling skips pages that robots.txt disallows for this Actor. Default true. (Google fetches the audited pages itself.)

## `requestIntervalMs` (type: `integer`):

Polite spacing. 200–30000; default 1000.

## `maxRetries` (type: `integer`):

Retries for network errors and 429/5xx. 0–5; default 2.

## `dryRun` (type: `boolean`):

When true, no Google API calls are made; deterministic mock scores are returned. Useful for wiring tests. Default false.

## Actor input object example

```json
{
  "urls": [
    "https://example.com/",
    "https://www.w3.org/"
  ],
  "maxCrawlPages": 20,
  "crawlDepth": 2,
  "strategy": [
    "mobile"
  ],
  "categories": [
    "performance",
    "accessibility",
    "best-practices",
    "seo"
  ],
  "generateReport": true,
  "maxUrlsFromSitemap": 20,
  "maxAudits": 200,
  "respectRobotsTxt": true,
  "requestIntervalMs": 1000,
  "maxRetries": 2,
  "dryRun": false
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

## `scores` (type: `string`):

No description

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

No description

## `reportHtml` (type: `string`):

No description

## `reportMarkdown` (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": [
        "https://example.com/",
        "https://www.w3.org/"
    ],
    "strategy": [
        "mobile"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("steadfeed/bulk-pagespeed-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.w3.org/",
    ],
    "strategy": ["mobile"],
}

# Run the Actor and wait for it to finish
run = client.actor("steadfeed/bulk-pagespeed-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.w3.org/"
  ],
  "strategy": [
    "mobile"
  ]
}' |
apify call steadfeed/bulk-pagespeed-audit --silent --output-dataset

```

## MCP server setup

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