<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: reflexdev</title>
    <description>The latest articles on DEV Community by reflexdev (@reflexdev).</description>
    <link>https://dev.to/reflexdev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4219917%2F8c800df9-5b1f-45b7-ae6d-117bf57d7292.png</url>
      <title>DEV Community: reflexdev</title>
      <link>https://dev.to/reflexdev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/reflexdev"/>
    <language>en</language>
    <item>
      <title>How to run Lighthouse on every page in your sitemap (without a PageSpeed API key)</title>
      <dc:creator>reflexdev</dc:creator>
      <pubDate>Sun, 01 Nov 2026 03:35:15 +0000</pubDate>
      <link>https://dev.to/reflexdev/how-to-run-lighthouse-on-every-page-in-your-sitemap-without-a-pagespeed-api-key-43cn</link>
      <guid>https://dev.to/reflexdev/how-to-run-lighthouse-on-every-page-in-your-sitemap-without-a-pagespeed-api-key-43cn</guid>
      <description>&lt;p&gt;Lighthouse is great for one page at a time. When you're responsible for a whole site, say 50 docs pages, a blog, or a client's product catalogue, the questions change. Which pages are slow? Which ones are missing a meta description? Did last week's release make things worse?&lt;/p&gt;

&lt;p&gt;Doing that by hand in DevTools gets old quickly. This post covers three ways to audit every URL in a sitemap, what each costs in time and money, and what the output looks like from a real run.&lt;/p&gt;

&lt;h2&gt;
  
  
  Option 1: Lighthouse CLI in a loop (free, local)
&lt;/h2&gt;

&lt;p&gt;If you have Node and Chrome installed, you can do it yourself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; lighthouse
curl &lt;span class="nt"&gt;-s&lt;/span&gt; https://www.example.com/sitemap.xml &lt;span class="se"&gt;\&lt;/span&gt;
  | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;loc&amp;gt;[^&amp;lt;]*'&lt;/span&gt; | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'s/&amp;lt;loc&amp;gt;//'&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-20&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  | &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;read &lt;/span&gt;url&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
      &lt;/span&gt;lighthouse &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--quiet&lt;/span&gt; &lt;span class="nt"&gt;--chrome-flags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"--headless=new"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nt"&gt;--only-categories&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;performance,seo &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nt"&gt;--output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;json &lt;span class="nt"&gt;--output-path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"./reports/&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;md5sum&lt;/span&gt; | &lt;span class="nb"&gt;cut&lt;/span&gt; &lt;span class="nt"&gt;-c1-8&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;.json"&lt;/span&gt;
    &lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works and costs nothing. The catches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sitemap indexes (a sitemap of sitemaps) and &lt;code&gt;.gz&lt;/code&gt; sitemaps need extra handling.&lt;/li&gt;
&lt;li&gt;You end up with a folder of 300–500 KB JSON files and still have to pull the scores and metrics out of each one.&lt;/li&gt;
&lt;li&gt;Scores depend on your machine and network. Your laptop on fibre isn't a mid-range phone on 4G.&lt;/li&gt;
&lt;li&gt;Run audits &lt;strong&gt;one at a time&lt;/strong&gt;. Running several in parallel on one machine makes them compete for CPU and drags performance scores down.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a one-off check of a small site, this is honestly the best option.&lt;/p&gt;

&lt;h2&gt;
  
  
  Option 2: PageSpeed Insights API (free, with limits)
&lt;/h2&gt;

&lt;p&gt;Google's PSI API runs Lighthouse for you and also returns Chrome UX Report field data when a page has enough traffic. You need an API key, you're rate-limited, and heavy use runs into quota errors. It's a good choice for a few hundred URLs a day if you're happy to write the sitemap parsing and the retry logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Option 3: a hosted bulk auditor
&lt;/h2&gt;

&lt;p&gt;If you want a table of results without maintaining scripts, you can run Lighthouse in the cloud. Full disclosure: I built a small tool for this on Apify, the &lt;a href="https://apify.com/reflexdev/lighthouse-bulk-auditor" rel="noopener noreferrer"&gt;Lighthouse Bulk Auditor&lt;/a&gt;. It's paid per successful audit (currently US$0.015 per page per device), so weigh that against Options 1 and 2. The rest of this walkthrough uses it because that's where the sample output below comes from.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Point it at a sitemap
&lt;/h3&gt;

&lt;p&gt;Open the Actor, click &lt;strong&gt;Try for free&lt;/strong&gt;, and switch to the JSON input. This is the exact input I used for the sample below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"sitemapUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://docs.apify.com/sitemap.xml"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"maxSitemapUrls"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"strategies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"desktop"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"maxOpportunities"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;sitemapUrl&lt;/code&gt; can be a normal sitemap, a sitemap index or a &lt;code&gt;.gz&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;maxSitemapUrls&lt;/code&gt; caps how many pages are audited. Start small, check the output, then raise it.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;strategies&lt;/code&gt; is &lt;code&gt;mobile&lt;/code&gt;, &lt;code&gt;desktop&lt;/code&gt; or both. Both doubles the number of audits.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;maxOpportunities&lt;/code&gt; is how many "top fixes" to keep per page.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That run audited 3 pages in about 98 seconds in total. A single audit usually takes 10–40 seconds depending on the page.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Read the output
&lt;/h3&gt;

&lt;p&gt;You get one row per page per device. This is a real row from that run, trimmed slightly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://docs.apify.com/api"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"strategy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"desktop"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ok"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scores"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"performance"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;71&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"accessibility"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"bestPractices"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;69&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"seo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;85&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"firstContentfulPaintMs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;570&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"largestContentfulPaintMs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1366&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"totalBlockingTimeMs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;455&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"cumulativeLayoutShift"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.005&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"speedIndexMs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2355&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"serverResponseTimeMs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"topOpportunities"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mainthread-work-breakdown"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Minimize main-thread work"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"estimatedSavingsMs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;450&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bootup-time"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Reduce JavaScript execution time"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"estimatedSavingsMs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;450&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"render-blocking-insight"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Render-blocking requests"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"estimatedSavingsMs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;350&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"failedSeoOrA11yAudits"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Document does not have a meta description"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Image elements do not have `[alt]` attributes"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Background and foreground colors do not have a sufficient contrast ratio."&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"lighthouseVersion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"13.6.0"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The fields I find most useful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;largestContentfulPaintMs&lt;/code&gt;, &lt;code&gt;cumulativeLayoutShift&lt;/code&gt;, &lt;code&gt;totalBlockingTimeMs&lt;/code&gt;&lt;/strong&gt;: the lab versions of the Core Web Vitals. TBT stands in for INP in lab testing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;topOpportunities&lt;/code&gt;&lt;/strong&gt;: Lighthouse's own estimate of what each fix would save, sorted by time saved. It's a decent to-do list, but treat the numbers as estimates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;failedSeoOrA11yAudits&lt;/code&gt;&lt;/strong&gt;: the plain-English names of failing binary checks. This is often the quickest win, because a missing meta description takes a minute to fix.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;status&lt;/code&gt; / &lt;code&gt;errorMessage&lt;/code&gt;&lt;/strong&gt;: pages that couldn't be loaded show up as &lt;code&gt;error&lt;/code&gt; rows with the reason, so they don't silently drop out.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Export to CSV or Excel and sort by &lt;code&gt;largestContentfulPaintMs&lt;/code&gt; or &lt;code&gt;scores.performance&lt;/code&gt; to find your worst pages.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Narrow it down when you only care about one thing
&lt;/h3&gt;

&lt;p&gt;A full audit isn't always what you need. Limiting &lt;code&gt;categories&lt;/code&gt; makes runs faster and the output easier to scan.&lt;/p&gt;

&lt;p&gt;Performance only, with a pass/fail budget:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"startUrls"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://apify.com"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://docs.apify.com"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"strategies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"mobile"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"categories"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"performance"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"minPerformanceScore"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each row gets &lt;code&gt;passedPerformanceBudget: true/false&lt;/code&gt;. In my test, one page scored 64 and passed. The other scored 35 with a 23-second LCP on emulated slow 4G and failed. That's exactly the kind of page this is meant to surface.&lt;/p&gt;

&lt;p&gt;SEO only (&lt;code&gt;"categories": ["seo"]&lt;/code&gt;) or accessibility only (&lt;code&gt;"categories": ["accessibility"]&lt;/code&gt;) took about 10–12 seconds per page in my runs. Columns for categories you didn't ask for come back as &lt;code&gt;null&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Automate it
&lt;/h3&gt;

&lt;p&gt;The useful version of this is a scheduled run:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Save your input as a task.&lt;/li&gt;
&lt;li&gt;Add a schedule, for example weekly.&lt;/li&gt;
&lt;li&gt;Set &lt;code&gt;minPerformanceScore&lt;/code&gt; and add a webhook or Slack integration so you hear about pages that fail the budget.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can also call it from a script or CI with Apify's &lt;code&gt;run-sync-get-dataset-items&lt;/code&gt; endpoint, which starts a run and returns the rows in one request. Synchronous calls time out after 5 minutes, so use the normal asynchronous run endpoint for large sitemaps.&lt;/p&gt;

&lt;h2&gt;
  
  
  Caveats worth knowing (whichever option you pick)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scores vary between runs&lt;/strong&gt; by a few points, because of network jitter, ads and third-party scripts. Compare trends over several runs, not single numbers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lab data isn't field data.&lt;/strong&gt; The CrUX numbers at the top of PageSpeed Insights come from real Chrome users. Lighthouse lab data is reproducible and works for pages with no traffic, but the two will differ.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Location matters.&lt;/strong&gt; Cloud audits run from wherever the servers are (US data centres in this case), so &lt;code&gt;serverResponseTimeMs&lt;/code&gt; for a site hosted in Australia or Europe will look worse than from a local machine.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Only audit sites you own or have permission to test&lt;/strong&gt;, and keep volumes reasonable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lighthouse isn't a full accessibility audit.&lt;/strong&gt; It catches common, automatable issues such as contrast, alt text and labels, but not everything WCAG covers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;For a handful of pages, run the Lighthouse CLI locally. For a few hundred URLs a day when you're happy to write some glue code, the PSI API is free. When you want a whole sitemap turned into a spreadsheet, or a scheduled check that alerts you, a hosted runner saves the plumbing.&lt;/p&gt;

&lt;p&gt;If you try the Actor and something doesn't work, or there's a field you wish it had, open an issue on its Issues tab. I'd genuinely like to know.&lt;/p&gt;

</description>
      <category>lighthouse</category>
      <category>webperf</category>
      <category>seo</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
