Perform automated auditing using lighthouse/headless chrome.

Install lighthouse

$ npm install lighthouse

Inspect npm binary folder.

$ npm bin
/home/milosz/node_modules/.bin

Update PATH to include npm binary folder.

$ export PATH="$PATH:$(npm bin)"

Display usage information.

$ lighthouse --help
lighthouse <url> <options>

Logging:
      --verbose  Displays verbose logging                                                                     [boolean] [default: false]
      --quiet    Displays no progress, debug logs, or errors                                                  [boolean] [default: false]

Configuration:
      --save-assets                  Save the trace contents & devtools logs to disk                          [boolean] [default: false]
      --list-all-audits              Prints a list of all available audits and exits                          [boolean] [default: false]
      --list-locales                 Prints a list of all supported locales and exits                         [boolean] [default: false]
      --list-trace-categories        Prints a list of all required trace categories and exits                 [boolean] [default: false]
      --print-config                 Print the normalized config for the given config and options, then exit. [boolean] [default: false]
      --additional-trace-categories  Additional categories to capture with the trace (comma-delimited).                         [string]
      --config-path                  The path to the config JSON.
                                                 An example config file: lighthouse-core/config/lr-desktop-
                                     config.js                                                                                  [string]
      --preset                       Use a built-in configuration.
                                               WARNING: If the --config-path flag is provided, this preset
                                      will be ignored.                             [string] [choices: "perf", "experimental", "desktop"]
      --chrome-flags                 Custom flags to pass to Chrome (space-delimited). For a full list of flags, see https://bit.ly/chro
                                     me-flags
                                                 Additionally, use the CHROME_PATH environment variable to use a specific Chrom
                                     e binary. Requires Chromium version 66.0 or later. If omitted, any detected Chrome Canary or Chrome
                                      stable will be used.                                                        [string] [default: ""]
      --port                         The port to use for the debugging protocol. Use 0 for a random port           [number] [default: 0]
      --hostname                     The hostname to use for the debugging protocol.                     [string] [default: "127.0.0.1"]
      --form-factor                  Determines how performance metrics are scored and if mobile-only audits are skipped. For desktop, -
                                     -preset=desktop instead.                                    [string] [choices: "mobile", "desktop"]
      --screenEmulation              Sets screen emulation parameters. See also --preset. Use --screenEmulation.disabled to disable. Oth
                                     erwise set these 4 parameters individually: --screenEmulation.mobile --screenEmulation.width=360 --
                                     screenEmulation.height=640 --screenEmulation.deviceScaleFactor=2
      --emulatedUserAgent            Sets useragent emulation                                                                   [string]
      --max-wait-for-load            The timeout (in milliseconds) to wait before the page is considered done loading and the run should
                                      continue. WARNING: Very high values can lead to large traces and instability              [number]
      --enable-error-reporting       Enables error reporting, overriding any saved preference. --no-enable-error-reporting will do the o
                                     pposite. More: https://git.io/vFFTO                                                       [boolean]
  -G, --gather-mode                  Collect artifacts from a connected browser and save to disk. (Artifacts folder path may optionally
                                     be provided). If audit-mode is not also enabled, the run will quit early.
  -A, --audit-mode                   Process saved artifacts from disk. (Artifacts folder path may be provided, otherwise defaults to ./
                                     latest-run/)
      --only-audits                  Only run the specified audits                                                               [array]
      --only-categories              Only run the specified categories. Available categories: accessibility, best-practices, performance
                                     , pwa, seo                                                                                  [array]
      --skip-audits                  Run everything except these audits                                                          [array]
      --budget-path                  The path to the budget.json file for LightWallet.                                          [string]

Output:
      --output       Reporter for the results, supports multiple values. choices: "json", "html", "csv"      [array] [default: ["html"]]
      --output-path  The file path to output the results. Use 'stdout' to write to stdout.
                       If using JSON output, default is stdout.

                     If using HTML or CSV output, default is a file in the working directory with a name based on the test URL and date.

                       If using multiple outputs, --output-path is appended with the standard extension for each output type. "reports/
                     my-run" -> "reports/my-run.report.html", "reports/my-run.report.json", etc.
                       Example: --output-path=./lighthouse-r
                     esults.html                                                                                                [string]
      --view         Open HTML report in your browser                                                         [boolean] [default: false]

Options:
      --help                               Show help                                                                           [boolean]
      --version                            Show version number                                                                 [boolean]
      --cli-flags-path                     The path to a JSON file that contains the desired CLI flags to apply. Flags specified at the
                                           command line will still override the file-based ones.
      --debug-navigation                   Pause after page load to wait for permission to continue the run, evaluate `continueLighthous
                                           eRun` in the console to continue.                                                   [boolean]
      --fraggle-rock                       [EXPERIMENTAL] Use the new Fraggle Rock navigation runner to gather results.
                                                                                                              [boolean] [default: false]
      --locale                             The locale/language the report should be formatted in
      --blocked-url-patterns               Block any network requests to the specified URL patterns                              [array]
      --disable-storage-reset              Disable clearing the browser cache and other storage APIs before a run              [boolean]
      --throttling-method                  Controls throttling method             [string] [choices: "devtools", "provided", "simulate"]
      --throttling
      --throttling.rttMs                   Controls simulated network RTT (TCP layer)
      --throttling.throughputKbps          Controls simulated network download throughput
      --throttling.requestLatencyMs        Controls emulated network RTT (HTTP layer)
      --throttling.downloadThroughputKbps  Controls emulated network download throughput
      --throttling.uploadThroughputKbps    Controls emulated network upload throughput
      --throttling.cpuSlowdownMultiplier   Controls simulated + emulated CPU throttling
      --extra-headers                      Set extra HTTP Headers to pass with request
      --precomputed-lantern-data-path      Path to the file where lantern simulation data should be read from, overwriting the lantern o
                                           bserved estimates for RTT and server latency.                                        [string]
      --lantern-data-output-path           Path to the file where lantern simulation data should be written to, can be used in a future
                                           run with the `precomputed-lantern-data-path` flag.                                   [string]
      --plugins                            Run the specified plugins                                                             [array]
      --channel                                                                                                [string] [default: "cli"]
      --chrome-ignore-default-flags                                                                           [boolean] [default: false]

Examples:
  lighthouse <url> --view                                               Opens the HTML report in a browser after the run completes
  lighthouse <url> --config-path=./myconfig.js                          Runs Lighthouse with your own configuration: custom audits, repo
                                                                        rt generation, etc.
  lighthouse <url> --output=json --output-path=./report.json --save-as  Save trace, screenshots, and named JSON report.
  sets
  lighthouse <url> --screenEmulation.disabled --throttling-method=prov  Disable emulation and all throttling
  ided --no-emulated-user-agent
  lighthouse <url> --chrome-flags="--window-size=412,660"               Launch Chrome with a specific window size
  lighthouse <url> --quiet --chrome-flags="--headless"                  Launch Headless Chrome, turn off logging
  lighthouse <url> --extra-headers "{\"Cookie\":\"monster=blue\", \"x-  Stringify'd JSON HTTP Header key/value pairs to send in requests
  men\":\"wolverine\"}"
  lighthouse <url> --extra-headers=./path/to/file.json                  Path to JSON file of HTTP Header key/value pairs to send in requ
                                                                        ests
  lighthouse <url> --only-categories=performance,pwa                    Only run the specified categories. Available categories: accessi
                                                                        bility, best-practices, performance, pwa, seo

For more information on Lighthouse, see https://developers.google.com/web/tools/lighthouse/.

Generate sample report.

$ lighthouse https://sleeplessbeastie.eu --preset=desktop -quiet --chrome-flags="--headless"
  LH:ChromeLauncher Waiting for browser. +0ms
  LH:ChromeLauncher Waiting for browser... +0ms
  LH:ChromeLauncher Waiting for browser..... +504ms
  LH:ChromeLauncher Waiting for browser.....✓ +1ms
  LH:config:warn IFrameElements gatherer requested, however no audit requires it. +287ms
  LH:config:warn Inputs gatherer requested, however no audit requires it. +0ms
  LH:status Connecting to browser +48ms
  LH:status Resetting state with about:blank +10ms
  LH:status Navigating to about:blank +0ms
  LH:status Benchmarking machine +18ms
  LH:status Initializing… +1s
  LH:status Preparing target for navigation mode +3ms
  LH:status Running defaultPass pass CSSUsage, JsUsage, ViewportDimensions, ConsoleMessages, AnchorElements, ImageElements, LinkElements, MetaElements, ScriptElements, IFrameElements, Inputs, MainDocumentContent, GlobalListeners, Doctype, DOMStats, OptimizedImages, PasswordInputsWithPreventedPaste, ResponseCompression, TagsBlockingFirstPaint, FontSize, EmbeddedContent, RobotsTxt, TapTargets, Accessibility, TraceElements, InspectorIssues, SourceMaps, FullPageScreenshot +10ms
  LH:status Resetting state with about:blank +0ms
  LH:status Navigating to about:blank +0ms
  LH:status Preparing target for navigation +8ms
  LH:status Cleaning origin data +20ms
  LH:status Cleaning browser cache +2ms
  LH:status Preparing network conditions +3ms
  LH:status Beginning devtoolsLog and trace +17ms
  LH:status Loading page & waiting for onload +10ms
  LH:status Navigating to https://sleeplessbeastie.eu/ +0ms
  LH:status Gathering in-page: CSSUsage +2s
  LH:status Gathering in-page: JsUsage +0ms
  LH:status Gathering in-page: ViewportDimensions +0ms
  LH:status Gathering in-page: ConsoleMessages +0ms
  LH:status Gathering in-page: AnchorElements +0ms
  LH:status Gathering in-page: ImageElements +0ms
  LH:status Gathering in-page: LinkElements +0ms
  LH:status Gathering in-page: MetaElements +0ms
  LH:status Gathering in-page: ScriptElements +0ms
  LH:status Gathering in-page: IFrameElements +0ms
  LH:status Gathering in-page: Inputs +0ms
  LH:status Gathering in-page: MainDocumentContent +0ms
  LH:status Gathering in-page: GlobalListeners +0ms
  LH:status Gathering in-page: Doctype +0ms
  LH:status Gathering in-page: DOMStats +0ms
  LH:status Gathering in-page: OptimizedImages +0ms
  LH:status Gathering in-page: PasswordInputsWithPreventedPaste +0ms
  LH:status Gathering in-page: ResponseCompression +0ms
  LH:status Gathering in-page: TagsBlockingFirstPaint +0ms
  LH:status Gathering in-page: FontSize +0ms
  LH:status Gathering in-page: EmbeddedContent +0ms
  LH:status Gathering in-page: RobotsTxt +0ms
  LH:status Gathering in-page: TapTargets +0ms
  LH:status Gathering in-page: Accessibility +1ms
  LH:status Gathering in-page: TraceElements +0ms
  LH:status Gathering in-page: InspectorIssues +0ms
  LH:status Gathering in-page: SourceMaps +0ms
  LH:status Gathering in-page: FullPageScreenshot +0ms
  LH:status Gathering trace +0ms
  LH:status Gathering devtoolsLog & network records +36ms
  LH:status Gathering: CSSUsage +6ms
  LH:status Gathering: JsUsage +14ms
  LH:status Gathering: ViewportDimensions +7ms
  LH:status Gathering: ConsoleMessages +2ms
  LH:status Gathering: AnchorElements +2ms
  LH:status Gathering: ImageElements +31ms
  LH:status Gathering: LinkElements +7ms
  LH:status Gathering: MetaElements +5ms
  LH:status Gathering: ScriptElements +4ms
  LH:status Gathering: IFrameElements +4ms
  LH:status Gathering: Inputs +3ms
  LH:status Gathering: MainDocumentContent +4ms
  LH:status Gathering: GlobalListeners +1ms
  LH:status Gathering: Doctype +2ms
  LH:status Gathering: DOMStats +2ms
  LH:status Gathering: OptimizedImages +4ms
  LH:status Gathering: PasswordInputsWithPreventedPaste +1ms
  LH:status Gathering: ResponseCompression +3ms
  LH:status Gathering: TagsBlockingFirstPaint +1ms
  LH:status Gathering: FontSize +3ms
  LH:status Gathering: EmbeddedContent +9ms
  LH:status Gathering: RobotsTxt +2ms
  LH:status Gathering: TapTargets +31ms
  LH:status Gathering: Accessibility +12ms
  LH:status Gathering: TraceElements +137ms
  LH:status Gathering: InspectorIssues +13ms
  LH:status Gathering: SourceMaps +3ms
  LH:status Gathering: FullPageScreenshot +1ms
  LH:status Populate base artifacts +5s
  LH:status Get webapp manifest +1ms
  LH:status Get webapp installability errors +0ms
  LH:status Collect stacks +1ms
  LH:status Running offlinePass pass ServiceWorker +15ms
  LH:status Resetting state with about:blank +0ms
  LH:status Navigating to about:blank +0ms
  LH:status Preparing target for navigation +9ms
  LH:status Preparing network conditions +0ms
  LH:status Beginning devtoolsLog and trace +2ms
  LH:status Loading page & waiting for onload +0ms
  LH:status Navigating to https://sleeplessbeastie.eu/ +1ms
  LH:status Gathering in-page: ServiceWorker +38ms
  LH:status Gathering devtoolsLog & network records +0ms
  LH:status Gathering: ServiceWorker +3ms
  LH:status Disconnecting from browser... +3ms
  LH:status Cleaning origin data +0ms
  LH:status Analyzing and running audits... +5ms
  LH:status Auditing: Uses HTTPS +1ms
  LH:status Auditing: Registers a service worker that controls page and `start_url` +3ms
  LH:status Auditing: Has a `<meta name="viewport">` tag with `width` or `initial-scale` +3ms
  LH:status Auditing: First Contentful Paint +2ms
  LH:status Auditing: Largest Contentful Paint +9ms
  LH:status Auditing: First Meaningful Paint +7ms
  LH:status Auditing: Speed Index +4ms
  LH:status Auditing: Screenshot Thumbnails +196ms
  LH:status Auditing: Final Screenshot +81ms
  LH:status Auditing: Total Blocking Time +1ms
  LH:status Auditing: Max Potential First Input Delay +6ms
  LH:status Auditing: Cumulative Layout Shift +7ms
  LH:status Auditing: No browser errors logged to the console +3ms
  LH:status Auditing: Initial server response time was short +4ms
  LH:status Auditing: Time to Interactive +4ms
  LH:status Auditing: User Timing marks and measures +3ms
  LH:status Auditing: Avoid chaining critical requests +4ms
  LH:status Auditing: Avoid multiple page redirects +3ms
  LH:status Auditing: Web app manifest and service worker meet the installability requirements +6ms
  LH:status Auditing: Provides a valid `apple-touch-icon` +4ms
  LH:status Auditing: Configured for a custom splash screen +3ms
  LH:status Auditing: Sets a theme color for the address bar. +2ms
  LH:status Auditing: Manifest has a maskable icon +3ms
  LH:status Auditing: Content is sized correctly for the viewport +3ms
  LH:status Auditing: Displays images with correct aspect ratio +3ms
  LH:status Auditing: Serves images with appropriate resolution +2ms
  LH:status Auditing: Fonts with `font-display: optional` are preloaded +2ms
  LH:status Auditing: Avoids deprecated APIs +2ms
  LH:status Auditing: Minimizes main-thread work +2ms
  LH:status Auditing: JavaScript execution time +4ms
  LH:status Auditing: Preload key requests +3ms
  LH:status Auditing: Preconnect to required origins +2ms
  LH:status Auditing: All text remains visible during webfont loads +2ms
  LH:status Auditing: Diagnostics +1ms
  LH:status Auditing: Network Requests +1ms
  LH:status Auditing: Network Round Trip Times +1ms
  LH:status Auditing: Server Backend Latencies +2ms
  LH:status Auditing: Tasks +1ms
  LH:status Auditing: Metrics +0ms
  LH:status Auditing: Performance budget +2ms
  LH:status Auditing: Timing budget +2ms
  LH:status Auditing: Keep request counts low and transfer sizes small +3ms
  LH:status Auditing: Minimize third-party usage +3ms
  LH:status Auditing: Lazy load third-party resources with facades +3ms
  LH:status Auditing: Largest Contentful Paint element +2ms
  LH:status Auditing: Largest Contentful Paint image was not lazily loaded +1ms
  LH:status Auditing: Avoid large layout shifts +2ms
  LH:status Auditing: Avoid long main-thread tasks +2ms
  LH:status Auditing: Avoids `unload` event listeners +2ms
  LH:status Auditing: Avoid non-composited animations +2ms
  LH:status Auditing: Image elements have explicit `width` and `height` +2ms
  LH:status Auditing: Page has valid source maps +2ms
  LH:status Auditing: Preload Largest Contentful Paint image +3ms
  LH:status Auditing: Ensure CSP is effective against XSS attacks +3ms
  LH:status Auditing: Full-page screenshot +2ms
  LH:status Auditing: Script Treemap Data +1ms
  LH:status Auditing: Site works cross-browser +1ms
  LH:status Auditing: Page transitions don't feel like they block on the network +2ms
  LH:status Auditing: Each page has a URL +1ms
  LH:status Auditing: `[accesskey]` values are unique +2ms
  LH:status Auditing: `[aria-*]` attributes match their roles +5ms
  LH:status Auditing: `button`, `link`, and `menuitem` elements have accessible names +6ms
  LH:status Auditing: `[aria-hidden="true"]` is not present on the document `<body>` +2ms
  LH:status Auditing: `[aria-hidden="true"]` elements do not contain focusable descendents +6ms
  LH:status Auditing: ARIA input fields have accessible names +2ms
  LH:status Auditing: ARIA `meter` elements have accessible names +2ms
  LH:status Auditing: ARIA `progressbar` elements have accessible names +3ms
  LH:status Auditing: `[role]`s have all required `[aria-*]` attributes +3ms
  LH:status Auditing: Elements with an ARIA `[role]` that require children to contain a specific `[role]` have all required children. +3ms
  LH:status Auditing: `[role]`s are contained by their required parent element +3ms
  LH:status Auditing: `[role]` values are valid +2ms
  LH:status Auditing: ARIA toggle fields have accessible names +3ms
  LH:status Auditing: ARIA `tooltip` elements have accessible names +3ms
  LH:status Auditing: ARIA `treeitem` elements have accessible names +4ms
  LH:status Auditing: `[aria-*]` attributes have valid values +3ms
  LH:status Auditing: `[aria-*]` attributes are valid and not misspelled +5ms
  LH:status Auditing: Buttons have an accessible name +8ms
  LH:status Auditing: The page contains a heading, skip link, or landmark region +5ms
  LH:status Auditing: Background and foreground colors have a sufficient contrast ratio +6ms
  LH:status Auditing: `<dl>`'s contain only properly-ordered `<dt>` and `<dd>` groups, `<script>`, `<template>` or `<div>` elements. +7ms
  LH:status Auditing: Definition list items are wrapped in `<dl>` elements +4ms
  LH:status Auditing: Document has a `<title>` element +4ms
  LH:status Auditing: `[id]` attributes on active, focusable elements are unique +7ms
  LH:status Auditing: ARIA IDs are unique +5ms
  LH:status Auditing: No form fields have multiple labels +3ms
  LH:status Auditing: `<frame>` or `<iframe>` elements have a title +4ms
  LH:status Auditing: Heading elements appear in a sequentially-descending order +4ms
  LH:status Auditing: `<html>` element has a `[lang]` attribute +6ms
  LH:status Auditing: `<html>` element has a valid value for its `[lang]` attribute +8ms
  LH:status Auditing: Image elements have `[alt]` attributes +6ms
  LH:status Auditing: `<input type="image">` elements have `[alt]` text +4ms
  LH:status Auditing: Form elements have associated labels +4ms
  LH:status Auditing: Links have a discernible name +3ms
  LH:status Auditing: Lists contain only `<li>` elements and script supporting elements (`<script>` and `<template>`). +6ms
  LH:status Auditing: List items (`<li>`) are contained within `<ul>` or `<ol>` parent elements +6ms
  LH:status Auditing: The document does not use `<meta http-equiv="refresh">` +7ms
  LH:status Auditing: `[user-scalable="no"]` is not used in the `<meta name="viewport">` element and the `[maximum-scale]` attribute is not less than 5. +4ms
  LH:status Auditing: `<object>` elements have alternate text +7ms
  LH:status Auditing: No element has a `[tabindex]` value greater than 0 +5ms
  LH:status Auditing: Cells in a `<table>` element that use the `[headers]` attribute refer to table cells within the same table. +5ms
  LH:status Auditing: `<th>` elements and elements with `[role="columnheader"/"rowheader"]` have data cells they describe. +7ms
  LH:status Auditing: `[lang]` attributes have a valid value +7ms
  LH:status Auditing: `<video>` elements contain a `<track>` element with `[kind="captions"]` +5ms
  LH:status Auditing: Custom controls have associated labels +5ms
  LH:status Auditing: Custom controls have ARIA roles +0ms
  LH:status Auditing: User focus is not accidentally trapped in a region +0ms
  LH:status Auditing: Interactive controls are keyboard focusable +0ms
  LH:status Auditing: Interactive elements indicate their purpose and state +0ms
  LH:status Auditing: The page has a logical tab order +0ms
  LH:status Auditing: The user's focus is directed to new content added to the page +0ms
  LH:status Auditing: Offscreen content is hidden from assistive technology +0ms
  LH:status Auditing: HTML5 landmark elements are used to improve navigation +1ms
  LH:status Auditing: Visual order on the page follows DOM order +0ms
  LH:status Auditing: Uses efficient cache policy on static assets +0ms
  LH:status Auditing: Avoids enormous network payloads +2ms
  LH:status Auditing: Defer offscreen images +2ms
  LH:status Auditing: Eliminate render-blocking resources +2ms
  LH:status Auditing: Minify CSS +2ms
  LH:status Auditing: Minify JavaScript +5ms
  LH:status Auditing: Reduce unused CSS +3ms
  LH:status Auditing: Reduce unused JavaScript +3ms
  LH:status Auditing: Serve images in next-gen formats +3ms
  LH:status Auditing: Efficiently encode images +2ms
  LH:status Auditing: Enable text compression +2ms
  LH:status Auditing: Properly size images +2ms
  LH:status Auditing: Use video formats for animated content +1ms
  LH:status Auditing: Remove duplicate modules in JavaScript bundles +2ms
  LH:status Auditing: Avoid serving legacy JavaScript to modern browsers +3ms
  LH:status Auditing: Page has the HTML doctype +12ms
  LH:status Auditing: Properly defines charset +2ms
  LH:status Auditing: Avoids an excessive DOM size +2ms
  LH:status Auditing: Avoids requesting the geolocation permission on page load +3ms
  LH:status Auditing: No issues in the `Issues` panel in Chrome Devtools +2ms
  LH:status Auditing: Avoids `document.write()` +2ms
  LH:status Auditing: Avoids front-end JavaScript libraries with known security vulnerabilities +2ms
  LH:status Auditing: Detected JavaScript libraries +1ms
  LH:status Auditing: Avoids requesting the notification permission on page load +1ms
  LH:status Auditing: Allows users to paste into password fields +2ms
  LH:status Auditing: Use HTTP/2 +1ms
  LH:status Auditing: Uses passive listeners to improve scrolling performance +2ms
  LH:status Auditing: Document has a meta description +2ms
  LH:status Auditing: Page has successful HTTP status code +2ms
  LH:status Auditing: Document uses legible font sizes +1ms
  LH:status Auditing: Links have descriptive text +2ms
  LH:status Auditing: Links are crawlable +2ms
  LH:status Auditing: Page isn’t blocked from indexing +3ms
  LH:status Auditing: robots.txt is valid +2ms
  LH:status Auditing: Tap targets are sized appropriately +2ms
  LH:status Auditing: Document has a valid `hreflang` +1ms
  LH:status Auditing: Document avoids plugins +2ms
  LH:status Auditing: Document has a valid `rel=canonical` +1ms
  LH:status Auditing: Structured data is valid +3ms
  LH:status Generating results... +0ms
  LH:Printer html output written to /home/milosz/lighthouse/sleeplessbeastie.eu_2022-12-12_22-37-01.report.html +37ms
  LH:CLI Protip: Run lighthouse with `--view` to immediately open the HTML report in your browser +0ms
  LH:ChromeLauncher Killing Chrome instance 1737869 +0ms

Open generated report.

lighthouse!

Store results using JSON.

$ lighthouse https://sleeplessbeastie.eu --preset=desktop -quiet --chrome-flags="--headless" --output json --output-path sleeplessbeastie.eu.$(date +%Y%m%d).json

Inspect results.

$ jq '.audits["speed-index"] | "\(.title): \(.numericValue) \(.numericUnit)"' \
     sleeplessbeastie.eu.20221212.json
"Speed Index: 232 millisecond"