Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use Puppeteer to collect browser counters and document-navigation timings, then treat Core Web Vitals as a separate measure of user experience. These are different measurement layers: page.metrics() does not report LCP, CLS, or INP, and a fast load event does not prove that a page was visually stable or responsive.

Collect Puppeteer and navigation metrics

Navigate using an explicit lifecycle condition, then read Puppeteer’s runtime counters and the browser’s Navigation Timing entry. The condition determines when the snapshot is taken; it is part of the test definition, not a universal definition of “page ready.”

const response = await page.goto(url, { waitUntil: 'load' });
const pptrMetrics = await page.metrics();
const browserTimings = await page.evaluate(() => {
  const nav = performance.getEntriesByType('navigation')[0];
  return nav ? {
    startTime: nav.startTime,
    domInteractive: nav.domInteractive,
    domContentLoadedEventEnd: nav.domContentLoadedEventEnd,
    domComplete: nav.domComplete,
    loadEventEnd: nav.loadEventEnd,
  } : null;
});

console.log({ status: response?.status(), pptrMetrics, browserTimings });

This illustrative pattern follows the Puppeteer Page API and page.evaluate() API; it is not a benchmark. page.evaluate() runs in the page context and can return a value (or await a promise). The example records the navigation response status when available, Puppeteer counters, and selected timing fields.

Choose when to take the snapshot

waitUntil: 'load' waits for the document’s load lifecycle event. Puppeteer also offers network-idle waiting conditions, which use a minimum idle interval. Neither condition guarantees that every application is visually complete or that all interactions have finished. Single-page applications may continue rendering after navigation, and content loaded by user action may not exist until the action occurs. If the metric you need concerns a particular element or interaction, define that scenario and wait for its relevant state instead of assuming one lifecycle event answers every question.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#1 Best Overall

Know which measurement layer answers your question

Measurement What it tells you When it is collected What it does not establish
page.metrics() Browser-reported page counters, including document and frame counts, JavaScript event-listener count, and total and used JavaScript heap size. See the Puppeteer Metrics interface. At the point your script calls it. It is not a user-centric loading, responsiveness, or visual-stability score.
Navigation Timing Milestones in a document navigation, exposed through the browser’s Performance API. See MDN’s Navigation timing guide. For a navigation entry associated with the current document. It does not measure every aspect of perceived responsiveness or visual stability.
Core Web Vitals LCP, CLS, and INP address loading, visual stability, and interaction responsiveness. See Google’s Web Vitals guidance. As user experiences are measured across visits and relevant interactions; field data represents real users rather than one controlled run. A single Puppeteer navigation snapshot is not equivalent to representative field data.

Interpret the numbers and milestones

Puppeteer counters and timestamps

Read metric names and units before comparing values. Puppeteer’s Metrics interface includes counts and JavaScript heap sizes in bytes. Its Page API describes timestamps as monotonic seconds from an arbitrary point in the past: they are not wall-clock times, and should not be compared directly with Unix timestamps without a defined conversion. The timestamp statement is from the Puppeteer Page API documentation.

Navigation milestones

  • domInteractive: DOM construction has finished and scripts can interact with the DOM.
  • domContentLoadedEventStart and domContentLoadedEventEnd: the start and end of the DOMContentLoaded event handler.
  • domComplete: the document and its subresources have finished loading.
  • loadEventStart and loadEventEnd: the start and end of the load event handler.

These values help locate a delay in the navigation sequence, but they do not say whether the most important content appeared quickly, whether layout stayed stable, or whether the page responded promptly to an interaction. DOMContentLoaded and load are lifecycle milestones, not substitutes for experience metrics.

Core Web Vitals

Google’s current Web Vitals guidance lists LCP, CLS, and INP as the stable Core Web Vitals. Use appropriate Web Vitals instrumentation when you need those user-centric measures. Google recommends aggregating data and checking its recommended thresholds for at least 75% of page visits; the reviewed guidance does not state a publication year for that recommendation. It also notes that JavaScript API measurements may differ from CrUX, and points to the web-vitals library as a production-ready wrapper designed to match Google tools.

Make Puppeteer runs comparable

A result is meaningful against another result only when the test conditions and page scenario are sufficiently alike. Record the following with each run:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • URL, browser build, and Puppeteer version. API references can change; the version surfaced for the reviewed Puppeteer pages was 25.12.0, so check the current reference for the installed version.
  • Viewport or device emulation, set before navigation where appropriate. Changing viewport settings later can resize or reload the page.
  • Cache and service-worker state, including whether cache is disabled or service workers are bypassed.
  • Network and CPU throttling settings, plus the machine and environment used.
  • The navigation wait condition and the exact time or state at which metrics were read.
  • Whether the run includes an interaction, and what that interaction is.

Puppeteer exposes viewport and device emulation, CPU and network controls, cache control, and service-worker bypass controls. Chrome DevTools also supports CPU and network throttling. Its Performance features reference cautions that CPU throttling is relative to the host computer; it does not truly simulate mobile CPU architecture. Report throttling as a test condition rather than presenting it as a perfect phone simulation.

Use lab and field evidence for different jobs

A controlled Puppeteer run is useful for repeatable investigation: it can help identify which navigation phase or browser resource changed under specified conditions. It is lab evidence, not automatically a picture of what typical users experience. CrUX and real-user monitoring aggregate field experiences; they complement controlled runs and help assess whether an issue is representative. Google notes that public JavaScript API measurements can differ from CrUX, so do not treat a lab value as interchangeable with field data.

Troubleshoot misleading or missing results

  • No navigation entry: performance.getEntriesByType('navigation')[0] may be absent in the document context you queried. Keep the null check shown in the example and confirm that evaluation ran in the intended page after navigation.
  • Timings vary between runs: Check whether the wait condition, cache, service-worker state, viewport, throttling, browser build, or page scenario changed. Record these settings before interpreting a difference as a regression.
  • A low load time but slow-looking page: Load milestones do not establish that key content rendered quickly or that layout remained stable. Instrument the relevant Web Vitals and inspect the page’s actual user-facing behavior.
  • Network idle never arrives or gives an unhelpful snapshot: Persistent requests or ongoing application work can make network-idle an unsuitable readiness condition. Choose a condition tied to the page state being measured; do not equate idle network traffic with finished rendering.
  • Heap values seem incomparable: Confirm that you are comparing the same metric, at the same point in the scenario, with equivalent browser and page conditions. Heap sizes are byte counts, not a page-speed score.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

For a screenshot rather than a custom Puppeteer metrics run, ScreenshotNeo offers a one-call website screenshot API. It does not return Puppeteer’s page.metrics() or replace Web Vitals instrumentation.

See the ScreenshotNeo documentation. Example cURL request:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

ScreenshotNeo removes cookie banners, newsletter popups, and chat widgets before capture; those cleaning steps can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers identify the page verdict and billing status. Its MCP server provides screenshot and PDF tools for AI agents. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots. Sign up for ScreenshotNeo’s free plan.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.