DEV Community

Innovative Cookie
Innovative Cookie

Posted on

Bulk Core Web Vitals with the free PageSpeed Insights API (and a small hosted option)

Core Web Vitals are easiest to fix when you look at many URLs at once. Google’s PageSpeed Insights (PSI) API v5 is free with your own API key and returns lab Lighthouse scores plus real-user CrUX field data in one call.

1. Get a free Google API key

In Google Cloud, enable “PageSpeed Insights API”, create an API key, and check the Quotas page for your daily limit.

2. One URL, one call

curl "https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url=https://example.com&strategy=mobile&category=performance&key=YOUR_KEY"
Enter fullscreen mode Exit fullscreen mode

Useful JSON paths:

  • Lab: lighthouseResult.audits (largest-contentful-paint, cumulative-layout-shift, total-blocking-time)
  • Field (when enough traffic): loadingExperience.metrics; else originLoadingExperience

3. Bulk loop (keep it polite)

import csv, json, time, urllib.parse, urllib.request

KEY = "YOUR_KEY"
URLS = ["https://example.com/", "https://example.com/pricing"]

def psi(url, strategy="mobile"):
    q = urllib.parse.urlencode({
        "url": url, "strategy": strategy,
        "category": "performance", "key": KEY,
    })
    with urllib.request.urlopen(
        "https://www.googleapis.com/pagespeedonline/v5/runPagespeed?" + q,
        timeout=90,
    ) as r:
        return json.load(r)

rows = []
for u in URLS:
    data = psi(u)
    audits = data["lighthouseResult"]["audits"]
    rows.append({
        "url": u,
        "perf": data["lighthouseResult"]["categories"]["performance"]["score"],
        "lcp_ms": audits["largest-contentful-paint"]["numericValue"],
        "cls": audits["cumulative-layout-shift"]["numericValue"],
        "tbt_ms": audits["total-blocking-time"]["numericValue"],
        "fetched_at": data.get("analysisUTCTimestamp"),
    })
    time.sleep(0.5)  # stay under quota; back off on HTTP 429

with open("cwv.csv", "w", newline="") as f:
    w = csv.DictWriter(f, fieldnames=rows[0].keys())
    w.writeheader(); w.writerows(rows)
print(len(rows), "rows → cwv.csv")
Enter fullscreen mode Exit fullscreen mode

Start from failing field metrics, then use lab audits to find the cause. Re-run after fixes; lab scores move between runs.

Hosted option (optional)

I built a small Apify Actor that runs the same PSI calls in bulk from a URL list, a sitemap or a domain, and exports CSV/JSON. You still bring your own free Google key. Disclosure: I am the creator.

https://apify.com/innovative_cookie/pagespeed-bulk

No Actor fee for now — only Apify platform usage (Free plan includes monthly credit).


Written with AI assistance.

Top comments (0)