Recommended Free Tools
Use Puppeteer when you need an image of the rendered PageSpeed Insights (PSI) report. The current PSI API (v5) returns JSON analysis data, not a documented top-level screenshot. A reliable JavaScript workflow is therefore: request metrics with the API when you need data, open the resulting report or your own HTML in a browser, and call Puppeteer’s page.screenshot(). The two outputs are different, and choosing the right one first prevents most implementation mistakes.
This guide shows both approaches, explains how to capture a real PSI report, and demonstrates how to turn API results into a controlled, screenshot-ready report.
Decide what “screenshot” means
There are two valid interpretations of this task:
- An image of the PSI website or report: a browser must render the page, including its layout and any report controls, before an image can be taken.
- A visual report built from PSI data: JavaScript calls the API, receives JSON, places selected scores and audits into your own HTML, and a browser captures that HTML.
The distinction matters because the API’s documented v5 response does not expose a top-level screenshot field. Google describes the endpoint as running an analysis and returning scores, suggestions and other information, while Puppeteer documents screenshot capture as a browser operation. See the PageSpeed Insights API documentation, the v5 runPagespeed reference, and Puppeteer’s screenshots guide.
Prerequisites
- Node.js with ES-module support (set
"type": "module"inpackage.json, or use a compatible module setup). - A project directory in which to install dependencies.
- For API requests, a network connection and a target URL that PSI can analyze. The API reference requires the
urlparameter. - For a report screenshot, Chromium downloaded by Puppeteer and enough time for the report to render.
Create a project and install Puppeteer:
mkdir psi-screenshot
cd psi-screenshot
npm init -y
npm install puppeteer
Puppeteer downloads a compatible browser during installation. If your environment manages Chromium separately, follow that environment’s launch configuration and provide an executable path when necessary.
#1 Best Overall
- Read Before You Buy — No Video Output: These adapters support charging and USB 2.0 data transfer, but cannot transmit video signals. Except for standard USB webcams (which use USB data only), they are not compatible with HDMI/DisplayPort cables, video-capable USB-C hubs, or docking stations with video output.
- Convert USB-A Ports to USB-C: Designed to connect USB-C earphones, cables, flash drives, card readers, and other USB-C accessories to standard USB-A ports. Plug-and-play with no drivers or software required.
- Aluminum Alloy Housing: Built with a sturdy aluminum alloy shell that aids in heat dissipation and protects against daily wear and scratches. Designed to maintain a stable and secure connection.
- Compact & Travel-Friendly: The ultra-compact design allows the adapter to stay plugged into your device without blocking adjacent ports or adding bulk, reducing wear and tear on your original USB ports.
- 12-Month Warranty: Backed by a 12-month manufacturer warranty for peace of mind. Designed to meet strict quality control standards for reliable everyday performance.
Capture the rendered PageSpeed Insights page
The following script opens PSI, waits for network activity to settle, and saves a full-page PNG. It is an implementation outline rather than a promise that a report has already been submitted: PSI’s interface, consent prompts and navigation can change. For a production workflow, navigate directly to the report URL you intend to archive and wait for a report-specific element or text that your process controls.
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
await page.goto('https://pagespeed.web.dev/', {
waitUntil: 'networkidle2'
});
await page.screenshot({
path: 'pagespeed-report.png',
fullPage: true
});
} finally {
await browser.close();
}
Run it with:
node capture-psi-page.js
fullPage: true tells Puppeteer to capture the complete scrollable document instead of only the visible viewport. You can omit it for a viewport-only image, or add other documented screenshot options such as an image type and quality setting. The ScreenshotOptions API lists the supported options.
Capture a specific report URL
For repeatable archives, use the report URL produced by your workflow rather than relying on the PSI home page. Then wait for content that proves the report is ready. A text-based wait is less dependent on generated CSS class names:
import puppeteer from 'puppeteer';
const reportUrl = process.env.PSI_REPORT_URL;
if (!reportUrl) throw new Error('Set PSI_REPORT_URL to a report URL');
const browser = await puppeteer.launch();
try {
const page = await browser.newPage({
viewport: { width: 1440, height: 1000 },
deviceScaleFactor: 1
});
await page.goto(reportUrl, { waitUntil: 'networkidle2' });
await page.waitForFunction(() => {
const text = document.body?.innerText || '';
return /Performance|Accessibility|Best Practices|SEO/i.test(text);
}, { timeout: 60000 });
await page.screenshot({ path: 'psi-report.png', fullPage: true });
} finally {
await browser.close();
}
This check only establishes that recognizable report text exists. If your application has a stronger readiness signal, such as a stable heading or a completion marker, wait for that instead. Handle consent dialogs or login flows explicitly when they occur in your environment; do not assume the public UI will always behave identically.
Fetch PSI analysis data with the current v5 API
When the required artifact is metrics and audits rather than a picture of Google’s interface, call runPagespeed. The current endpoint is:
https://pagespeedonline.googleapis.com/pagespeedonline/v5/runPagespeed
Rank #2
- 5-in-1 USB-C Hub: Experience comprehensive connectivity featuring a Power Delivery input, two USB-A 2.0 ports, a USB-A 3.0 port, and an HDMI port. (Note: The USB-C power delivery input port is only for connecting an external wall charger to power your laptop and cannot power peripheral devices.)
- 90W Pass-Through Charging: Achieve optimal charging with 90W pass-through power to your laptop, supported by a total input of 100W, with the hub reserving 10W for operational efficiency. (Note: Wall charger not included.)
- Quick Data Transfers: Accelerate your productivity with rapid data transfers using a high-speed 5Gbps USB 3.0 port and two 480Mbps USB 2.0 ports.
- 4K HDMI Display: Enhance your visual experience with a hub capable of delivering 4K resolution at 30Hz in both mirror and extend modes. Please note that this hub is compatible with MacBook (macOS 12 and newer), Windows 10 and 11, ChromeOS, and laptops equipped with DP Alt Mode and Power Delivery. Note: This device is not compatible with Linux.
- What You Get: Anker USB-C Hub (5-in-1, 4K HDMI), welcome guide, 18-month warranty, and our friendly customer service.
url is required. strategy accepts mobile or desktop; desktop is the default. This JavaScript example follows Google’s current pattern: build a URL, check response.ok, parse JSON, and read lighthouseResult.
const endpoint = new URL(
'https://pagespeedonline.googleapis.com/pagespeedonline/v5/runPagespeed'
);
endpoint.searchParams.set('url', 'https://example.com');
endpoint.searchParams.set('strategy', 'mobile');
const response = await fetch(endpoint);
if (!response.ok) {
throw new Error(`PSI request failed: ${response.status}`);
}
const result = await response.json();
console.log(result.analysisUTCTimestamp);
console.log(result.lighthouseResult);
Google’s getting-started example demonstrates this fetch-and-parse flow. The returned Lighthouse object contains audits and category information, but the documented v5 schema does not provide a top-level screenshot image for you to save.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Extract a small, stable data model
Rather than pass the entire response into a template, select the fields your report needs and tolerate missing audits:
const categories = result.lighthouseResult?.categories ?? {};
const audits = result.lighthouseResult?.audits ?? {};
const report = {
analyzedAt: result.analysisUTCTimestamp ?? null,
requestedUrl: result.id ?? null,
performance: categories.performance?.score ?? null,
accessibility: categories.accessibility?.score ?? null,
bestPractices: categories['best-practices']?.score ?? null,
seo: categories.seo?.score ?? null,
largestContentfulPaint: audits['largest-contentful-paint']?.displayValue ?? null,
cumulativeLayoutShift: audits['cumulative-layout-shift']?.displayValue ?? null
};
console.log(JSON.stringify(report, null, 2));
Scores are commonly represented as fractions between zero and one; preserve the value you receive and format it for display in your own template. An audit can be absent, renamed or structurally changed, so use optional chaining and display “not available” rather than crashing.
Build a custom HTML report, then screenshot it
A custom report is the best option when you need a stable layout, branding, selected audits or a repeatable image format. Fetch data first, write escaped values into HTML, then let Puppeteer capture the generated page.
import fs from 'node:fs/promises';
import puppeteer from 'puppeteer';
const endpoint = new URL(
'https://pagespeedonline.googleapis.com/pagespeedonline/v5/runPagespeed'
);
endpoint.searchParams.set('url', 'https://example.com');
endpoint.searchParams.set('strategy', 'mobile');
const response = await fetch(endpoint);
if (!response.ok) throw new Error(`PSI request failed: ${response.status}`);
const result = await response.json();
const lighthouse = result.lighthouseResult ?? {};
const categories = lighthouse.categories ?? {};
const score = (key) => {
const value = categories[key]?.score;
return value == null ? 'Not available' : Math.round(value * 100);
};
const auditValue = (key) =>
lighthouse.audits?.[key]?.displayValue ?? 'Not available';
const html = `<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>PageSpeed report</title>
<style>
body { font: 16px system-ui, sans-serif; margin: 40px; color: #172033; }
.grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; }
.card { border: 1px solid #d8deea; border-radius: 8px; padding: 18px; }
.score { font-size: 2rem; font-weight: 700; }
</style>
</head>
<body>
<h1>PageSpeed Insights summary</h1>
<p>Analyzed: ${result.analysisUTCTimestamp ?? 'Not available'}</p>
<section class="grid">
<div class="card">Performance <span class="score">${score('performance')}</span></div>
<div class="card">Accessibility <span class="score">${score('accessibility')}</span></div>
<div class="card">Best Practices <span class="score">${score('best-practices')}</span></div>
<div class="card">SEO <span class="score">${score('seo')}</span></div>
</section>
<h2>Selected audits</h2>
<ul>
<li>Largest Contentful Paint: ${auditValue('largest-contentful-paint')}</li>
<li>Cumulative Layout Shift: ${auditValue('cumulative-layout-shift')}</li>
</ul>
</body>
</html>`;
await fs.writeFile('report.html', html, 'utf8');
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
await page.goto(`file://${process.cwd()}/report.html`, {
waitUntil: 'networkidle0'
});
await page.screenshot({ path: 'custom-psi-report.png', fullPage: true });
} finally {
await browser.close();
}
The template above is intentionally small. A production template should HTML-escape any API-derived text before interpolation, define what happens when an audit is missing, and include the requested URL and analysis timestamp so an image remains identifiable later. If you need charts, render them in the HTML before taking the screenshot and wait for fonts or asynchronous chart drawing to finish.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →Rank #3
- Sleek 7-in-1 USB-C Hub: Features an HDMI port, two USB-A 3.0 ports, and a USB-C data port, each providing 5Gbps transfer speeds. It also includes a USB-C PD input port for charging up to 100W and dual SD and TF card slots, all in a compact design.
- Flawless 4K@60Hz Video with HDMI: Delivers exceptional clarity and smoothness with its 4K@60Hz HDMI port, making it ideal for high-definition presentations and entertainment. (Note: Only the HDMI port supports video projection; the USB-C port is for data transfer only.)
- Double Up on Efficiency: The two USB-A 3.0 ports and a USB-C port support a fast 5Gbps data rate, significantly boosting your transfer speeds and improving productivity.
- Fast and Reliable 85W Charging: Offers high-capacity, speedy charging for laptops up to 85W, so you spend less time tethered to an outlet and more time being productive.
- What You Get: Anker USB-C Hub (7-in-1), welcome guide, 18-month warranty, and our friendly customer service.
Choose between the approaches
| Need | Use | What you receive |
|---|---|---|
| Scores, audits and suggestions for another program | PSI v5 runPagespeed |
JSON analysis data |
| A picture of Google’s rendered report | Puppeteer against a report URL | PNG or another browser screenshot format |
| A branded, stable visual summary | PSI API plus your HTML and Puppeteer | An image of your own report |
Combining the API and browser is not redundant: the API supplies authoritative analysis data, while the browser determines the final pixels.
Reliability, performance and maintenance
Wait for the right condition
networkidle2 is useful for pages that continue loading a few assets, but it is not proof that a report is complete. Prefer a stable readiness marker, and set a finite timeout so a failed navigation cannot leave a worker running forever.
Control the capture environment
Set a fixed viewport and device scale factor when comparing images. Keep the same browser version, fonts and color-scheme settings where visual diffs matter. Capture at a consistent URL and strategy; mobile and desktop are separate PSI analyses.
Close every browser
Use try/finally as shown so Chromium closes on API, navigation or screenshot errors. In a server process, limit concurrent browser pages because each page consumes memory and CPU.
Expect evolving schemas
PSI’s API version is v5, but Lighthouse updates independently. Google’s release notes document response history, including changes to screenshot-related locations in older responses. Validate the fields you consume and review release notes when upgrading. Do not copy a v4 screenshot field path into a v5 integration.
Troubleshooting
The API returns 400
Check that url is present, fully qualified and URL-encoded by URLSearchParams or URL.searchParams. Confirm that the requested strategy is exactly mobile or desktop.
Rank #4
- Dual Converters, Infinite Potential:Includes 2× USB C male to USB A female adapters and 2× USB A male to USB C female adapters. Perfect for a wide range of uses—tablets with Bluetooth keyboards, expand USB ports on macbook, and more. Two different converters for all your daily needs
- Next-Level 10Gbps & 3A Charging: No more slow 480Mbps, this usb to usb c adapter has a transfer speed of up to 10Gbps, allowing you to do more transferring in less time. This usb adapter fits both USB A and USB C charger, supporting up to 3A fast charging
- Upgraded Exquisite Craftsmanship: With an aluminum alloy housing and metal connector, the usbc to usb adapter is extremely durable and sturdy. Rigorously tested to withstand more than 10,000 times of plugging and unplugging, ensuring long-lasting performance
- Broad Compatible: The usb c to usb adapter widely supports all USB C/ USB A devices like laptops, tablets, cellphones, car chargers, and phone chargers. Such as compatible with MacBook Pro/Air 2023/2022, Thunderbolt 4/3 Devices,Apple MagSafe Watch 9/8/7/SE/Ultra, iPad Pro 2022/2021, Samsung Galaxy S23/S20/S10, and iPhone 17/16/15 Pro. Plug and play
- Please Note: To reach 10Gbps speed, keep the cable under 3.3 ft. For USB A Male to USB C adapters, try flipping the USB C connector. USB C Male to USB A adapters support bidirectional 10Gbps transfer within 3.3 ft
The API returns a non-2xx response
Log the status and response body, then inspect quota, rate limits, authentication requirements and the target URL. Keep the status check before calling response.json(); an error page may not be JSON.
The PNG is blank or incomplete
The page may still be rendering, may require interaction, or may have navigated to a consent or error screen. Save an intermediate HTML dump, inspect the final URL and title, increase the navigation timeout where justified, and wait for a report-specific element before capturing.
Puppeteer cannot launch Chromium
Verify that installation completed and that the runtime can execute the downloaded browser. In managed containers, install the required system libraries or pass the path to an approved Chromium executable through Puppeteer’s launch options.
An audit field is undefined
Do not assume every audit exists in every response. Use optional chaining, provide a visible fallback, and test against the Lighthouse version and categories your workflow requests.
The screenshot differs between runs
Use a fixed viewport, browser version, fonts and timing. Avoid capturing while animations or charts are still changing, and prefer your own static report when pixel-level repeatability is essential.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Or skip the browser setup
ScreenshotNeo is a screenshot API and MCP server for developers. It accepts a URL and returns a PNG, JPEG, WebP or PDF. Before capture it accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups and chat widgets; each step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP tools—take_screenshot, get_page_info and capture_pdf—let Claude, Cursor and other MCP clients request captures.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
For a direct capture, see the ScreenshotNeo documentation and run:
Best Value
- 5-in-1 Connectivity: Equipped with a 4K HDMI port, a 5 Gbps USB-C data port, two 5 Gbps USB-A ports, and a USB C 100W PD-IN port. Note: The USB C 100W PD-IN port supports only charging and does not support data transfer devices such as headphones or speakers.
- Powerful Pass-Through Charging: Supports up to 85W pass-through charging so you can power up your laptop while you use the hub. Note: Pass-through charging requires a charger (not included). Note: To achieve full power for iPad, we recommend using a 45W wall charger.
- Transfer Files in Seconds: Move files to and from your laptop at speeds of up to 5 Gbps via the USB-C and USB-A data ports. Note: The USB C 5Gbps Data port does not support video output.
- HD Display: Connect to the HDMI port to stream or mirror content to an external monitor in resolutions of up to 4K@30Hz. Note: The USB-C ports do not support video output.
- What You Get: Anker 332 USB-C Hub (5-in-1), welcome guide, our worry-free 18-month warranty, and friendly customer service.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://pagespeed.web.dev/ -o shot.webp
ScreenshotNeo also supports full-page captures, CSS selectors, custom viewports and device presets, retina scale, dark mode, PDF settings, custom CSS and JavaScript, clicks, waits, blocked resources, headers, cookies, user agents, authorization, timezone and geolocation, transparent backgrounds, resizing, configurable-TTL caching, signed image links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, a usage API and an OpenAPI specification. Parameter names used by other screenshot APIs also work, which can simplify migration.
The Free plan includes 1,000 screenshots each month with no card. Paid plans start at $5 for 3,000 screenshots; every feature is available on every plan. Create a free ScreenshotNeo account to try the capture without setting up a browser.
Frequently Asked Questions
Does PageSpeed Insights API v5 return a PNG screenshot?
Its current documented response is JSON and does not list a top-level screenshot field. Capture a rendered page with browser automation or build your own report from the returned data.
Can I capture only the visible PSI viewport?
Yes. Omit Puppeteer’s fullPage: true option and set the viewport dimensions you want before calling page.screenshot().
Should I use mobile or desktop?
Set the API’s strategy parameter explicitly. Use mobile or desktop according to the analysis you need; desktop is the API default.
Why do old tutorials mention a screenshot field?
They generally describe the deprecated v4 reference. The current API is v5, and response details can change as Lighthouse evolves; consult Google’s current reference and release notes.
Quick Recap
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.

