Bulk PageSpeed Insights: Lighthouse & Sitemap Audits avatar

Bulk PageSpeed Insights: Lighthouse & Sitemap Audits

Pricing

from $5.00 / 1,000 url analyzeds

Go to Apify Store
Bulk PageSpeed Insights: Lighthouse & Sitemap Audits

Bulk PageSpeed Insights: Lighthouse & Sitemap Audits

Audit URL lists or sitemaps with Google PageSpeed Insights. Export mobile/desktop Lighthouse scores and opportunities. $0.005 per successful URL × device, plus start.

Pricing

from $5.00 / 1,000 url analyzeds

Rating

0.0

(0)

Developer

rovnaki

rovnaki

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

9 days ago

Last modified

Share

Audit a list of public URLs or expand a sitemap. Get Lighthouse category scores, lab metrics and optimization opportunities as JSON or CSV. Mobile and desktop each count as one analysis; failed analyses have no result fee. Supply your encrypted psiApiKey for larger runs, or use the creator-key fallback capped at 25 URL × strategy analyses per run.

Use bulk PageSpeed Insights as a Lighthouse API for a sitemap performance audit or mobile desktop speed test. Export LCP, CLS and TBT lab measurements through PageSpeed CSV export or JSON. Core Web Vitals field data is optional, when PSI supplies it; lab results are not a real-user Core Web Vitals assessment.

$0.005 per successful delivered URL × strategy, plus a start event of $0.00005 per GB (one-GB minimum). No browser or proxy runs inside this Actor.

Quick start

{
"urls": [
"https://example.com/"
],
"strategy": "mobile",
"categories": [
"performance",
"seo"
],
"maxUrls": 1,
"maxChargedResults": 1,
"concurrency": 1
}

One successful result costs $0.0052 with a 4 GB start, or $0.00505 at ≤1 GB, before any separately applicable platform usage. Inspect OUTPUT in the default key-value store for per-analysis errors, counts, stop reasons and sitemap diagnostics.

Illustrative compact row (full results also include opportunities and optional field data):

{"url":"https://example.com/","strategy":"mobile","scores":{"performance":83,"seo":92},"lab":{"lcp_ms":2400,"cls":0.05,"tbt_ms":120},"field":{"url":null,"origin":null}}

Key setup

Optionally enable the PageSpeed Insights API in your Google Cloud project, create a key and enter it in the PageSpeed Insights API key (psiApiKey) secret input field. Apify encrypts this field when saving input; the Actor reads and decrypts it through Actor.getInput(). Your supplied key takes priority over the creator's environment secret. Use the secret input editor; do not save a real key in example JSON, source files or datasets.

If psiApiKey is omitted or blank, the Actor uses the creator's PSI_API_KEY environment secret and logs a clear fallback message. This mode starts at most 25 URL × strategy analyses per run, including failed analyses. both counts twice per URL; the last URL may receive only one strategy when the cap is reached. Supply your own encrypted key for larger runs. User-key runs still obey URL, result and platform budget limits. The fallback is shared quota, not a guarantee of availability; it can return quota errors.

The cap counts analyses rather than retries: each analysis can make up to four HTTP attempts with retry/backoff. It applies across direct URLs and sitemap results and cannot be raised by increasing input limits. Remaining work is reported as OUTPUT.status: limited and stopped_reason: creator-key-analysis-limit. Failed analyses have no result fee but still consume the fallback allowance. The cap resets each run; it is not a per-user or daily quota.

If neither key is available, startup fails before sitemap expansion or upstream requests. Keys are never logged or included in results; PSI request URLs are not logged and generated errors redact the key. For local development, use a private local input or export PSI_API_KEY. Google quota and any project charges apply to the key's project; no fixed daily quota is promised.

Sitemap example

The owner-controlled public sitemap below is capped at five URLs and two strategies: up to 10 results ($0.05 plus start), or $0.0502 at 4 GB / $0.05005 at ≤1 GB.

{
"sitemapUrl": "https://gearchecks.com/sitemap-index.xml",
"strategy": "both",
"categories": ["performance", "seo"],
"maxUrls": 5,
"maxSitemaps": 10,
"maxChargedResults": 10,
"concurrency": 1
}

You can supply both explicit URLs and a sitemap; explicit URLs take priority. URLs must be HTTP(S), without embedded credentials. Fragments are removed and duplicates are skipped before the URL cap and strategy expansion. Distinct query strings and paths are retained. Redirected canonical pages may still have distinct input rows.

What you get

  • Performance, accessibility, SEO and best-practices scores on a 0–100 scale.
  • Lab LCP, CLS, TBT, FCP, Speed Index and TTI, if present in the selected Lighthouse version and categories.
  • URL and origin CrUX p75 metrics, categories and distributions from PSI's loadingExperience and originLoadingExperience responses. LCP/INP use milliseconds; CLS is unitless. A Core Web Vitals assessment is included for each field-data scope.
  • Top opportunities sorted by estimated time savings, then byte savings. Supports legacy Lighthouse opportunities and newer metricSavings audits. Savings are estimates and should not be added together.
  • Sitemap indexes, nested sitemaps, namespaces, gzip, URL deduplication, configurable caps, retry/backoff and per-analysis error isolation.

Field data is optional and can disappear from PSI. Google plans to remove CrUX data from this API; no CrUX or INP availability is promised. The source is the official PSI v5 API, including its available CrUX data. The Actor does not make separate CrUX API calls.

Inputs

InputDefaultDescription
psiApiKeyUnsetOptional encrypted personal PSI key; blank/omitted uses creator PSI_API_KEY with a 25-analysis cap, including failures
urls[]Up to 100,000 explicit URLs; supply this or sitemapUrl
sitemapUrlUnsetXML sitemap or sitemap index
strategymobilemobile, desktop or both
strategiesUnsetAPI alternative: array of mobile/desktop; omit strategy when using it
categoriesAll fourOne or more of performance, accessibility, seo, best-practices
maxUrls1001–100,000 unique URLs before multiplying by strategy
maxSitemaps251–1,000 sitemap documents; bounds the queue too
concurrency41–20 simultaneous PSI requests, including their retries
timeoutSecs12010–300 seconds per fetch attempt
maxChargedResults200000Run-wide emitted URL × strategy cap; 0 avoids upstream work
topOpportunities100–100 opportunities per result

Keep concurrency low enough for your key's quota. HTTP 429/5xx and transient network failures get up to three retries. Exponential backoff starts at 500 ms, honors Retry-After seconds/dates, and caps waits at 60 seconds. Permanent failures such as HTTP 400/403 are not retried. Persistent quota failures are recorded without charging a result.

Sitemap expansion is breadth-first, skips duplicate/cyclic index URLs and stops at the configured caps. Each fetched document and decompressed XML is limited to 10 MB. External entities/DTDs are rejected. A bad child sitemap is reported while other queued documents continue. It does not crawl page links or discover sitemaps from robots.txt.

Output

One dataset item per successful unique URL × strategy. For example, 100 URLs with both produces up to 200 items. This abbreviated example shows the score/metric layout; full results also contain timestamps, field data, opportunities and warnings:

{
"url": "https://example.com/",
"final_url": "https://example.com/",
"strategy": "mobile",
"scores": {
"performance": 83,
"accessibility": 100,
"seo": 92,
"best-practices": 96
},
"lab": {
"lcp_ms": 2400,
"cls": 0.05,
"tbt_ms": 120,
"fcp_ms": 800,
"si_ms": 1800,
"tti_ms": null
},
"field": {"url": null, "origin": null},
"opportunities": [],
"warnings": []
}

Each available field-data object includes id, overall_category, core_web_vitals and a metrics map keyed by Google's names, such as LARGEST_CONTENTFUL_PAINT_MS, INTERACTION_TO_NEXT_PAINT and CUMULATIVE_LAYOUT_SHIFT_SCORE. Each metric contains p75, category, unit and distributions. PSI represents CLS percentiles and bucket bounds as hundredths; these are converted to unitless values. The returned id preserves the source scope, including any origin fallback chosen by Google.

Core Web Vitals passes when all three p75 values are present and LCP ≤ 2,500 ms, INP ≤ 200 ms and CLS ≤ 0.1. It fails if any known metric exceeds its threshold; otherwise missing values yield unknown. Lab metrics do not substitute for field data.

Opportunities contain id, title, description, savings_ms, savings_bytes and display_value. Time savings use the largest time-metric estimate, excluding unitless CLS savings. Values without published estimates are null.

The Scores and lab metrics and CrUX and opportunities dataset views support quick inspection and export. Use JSON for nested data. The OUTPUT record in the default key-value store includes task counts, per-URL-strategy errors, budget stop reasons and sitemap expansion diagnostics/cap flags. Failed PSI calls and Lighthouse runtime errors produce no dataset row and no custom event. If every analysis fails, OUTPUT.status is failed; mixed results are partial; a cap that prevents remaining work is limited. Check this record when monitoring runs, since isolated upstream errors do not abort the SDK process.

Pricing and budget behavior

The url-strategy-analyzed event costs $0.005 per successful delivered item. Two strategies cost $0.01 per URL. A missing CrUX section does not invalidate an otherwise successful Lighthouse analysis. Invalid input, failed analyses, sitemap requests and duplicates do not produce custom charges. The default start event is automatic and is not charged again in code.

Dataset writes and Actor.charge() calls are serialized. Each write is guarded by the platform charging manager, strict remaining dollar capacity and result limits. maxChargedResults, ACTOR_MAX_TOTAL_CHARGE_USD, ACTOR_MAX_CHARGED_RESULTS, ACTOR_MAX_PAID_DATASET_ITEMS and APIFY_MAX_PAID_DATASET_ITEMS are all honored, including zero and prior charges. Local runs apply configured caps too. Some in-flight requests may finish after the cap is reached; excess rows are not delivered or charged. Check the Store/Console for any separately applicable platform usage; this source does not establish platform-cost allocation. The local memory default remains 512 MB (maximum 1,024 MB), but remote default run memory must also be checked; a previously observed 4,096 MB default requires a separate metadata update. Existing tasks or explicit run overrides can select different memory.

Dataset storage and charging are not atomic. The Actor charges only after a successful write. If charging is rejected, that last row can remain in the dataset and the run fails immediately after workers settle, preventing further delivery.

Limitations

  • A valid supplied psiApiKey or creator PSI_API_KEY and available project quota are required. Creator-key mode is limited to 25 analyses per run. Concurrency is a ceiling, not a per-minute quota guarantee. Retries consume time and can still exhaust quota.
  • CrUX data needs sufficient real-user samples; many pages or origins have none. Missing data stays null. Field data reflects Google's reporting window, not this run's synthetic measurement.
  • Scores and audits vary by Lighthouse version, region and measurement conditions. Unrequested categories and unavailable lab metrics remain null. Newer Lighthouse versions may omit TTI.
  • Estimated opportunities are not guaranteed savings. Unitless-only CLS opportunities are not included in the time/byte ranking.
  • Sitemaps may omit pages. URL caps count unique input URLs, not successful analyses. Sitemap caps may omit later branches; expansion diagnostics report limits and errors.
  • This version does not implement historical run diffs, authentication into target pages, full Lighthouse report storage, a separate CrUX API fallback or browser rendering in the Actor.

Local development and publishing

source ~/.nvm/nvm.sh
nvm use 22
npm ci
npm run build
npm test
npm run smoke

Run commands inside this Actor directory. Tests use representative synthetic PSI and sitemap fixtures plus injected transports; no API key or live calls are needed. The smoke command builds and invokes the real SDK entrypoint using INPUT.json and isolated .smoke-storage, validates the dataset schema and prints one JSON summary. Without PSI_API_KEY, it emits an explicit skipped: true summary and exits successfully. With a key, failed live checks exit non-zero.

For local runs, put input at storage/key_value_stores/default/INPUT.json, export the key and use npm start after building, or use the Apify CLI. Node 22 and a multi-stage apify/actor-node:22 Dockerfile match the reference Actor's stack. Only production dependencies go into the runtime image.

.actor/actor.json links the input schema, output links, dataset schemas/views and this Store listing. Before publishing a paid Actor, configure the prices in .actor/pay_per_event.json through Apify's pricing configuration; this deployment manifest does not activate pricing on its own. Disable synthetic apify-default-dataset-item charges to prevent double billing. The Actor fails closed for missing custom PPE configuration or an active synthetic dataset-item price. Production budget checks use the charging manager's event prices; local checks use the listed price.