Take screenshots of a locally running web app using Puppeteer. Use when you need to visually inspect a page, verify UI changes, or debug layout issues.
Takes screenshots of a running local web app and displays them for visual inspection.
localhost:3000). Check with curl -s -o /dev/null -w '%{http_code}' <url> first.cd <project-dir> && npm install --save-dev puppeteer
npx puppeteer browsers install chrome
Determine parameters from the user's request:
url — the page to screenshot (default: http://localhost:3000)viewport — width x height (default: 1440x900)fullPage — whether to capture the full scrollable page (default: false)sections — how many viewport-height chunks to capture when fullPage is false (default: auto-calculate based on page height)Write a temporary script inside the project directory (so it can resolve the puppeteer dependency):
// <project-dir>/_pi-screenshot.mjs
import puppeteer from 'puppeteer';
const url = '<url>';
const width = <width>;
const height = <height>;
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
await page.setViewport({ width, height });
await page.goto(url, { waitUntil: 'networkidle2', timeout: 15000 });
// Get full page height
const fullHeight = await page.evaluate(() => document.body.scrollHeight);
const sections = Math.ceil(fullHeight / height);
for (let i = 0; i < sections; i++) {
await page.screenshot({
path: `/tmp/pi-screenshot-${i}.png`,
clip: { x: 0, y: i * height, width, height: Math.min(height, fullHeight - i * height) }
});
}
await browser.close();
console.log(JSON.stringify({ sections, fullHeight }));
Run the script from the project directory:
cd <project-dir> && node _pi-screenshot.mjs
Read each screenshot using the read tool to display them:
/tmp/pi-screenshot-0.png
/tmp/pi-screenshot-1.png
...
Clean up the temporary files:
rm <project-dir>/_pi-screenshot.mjs /tmp/pi-screenshot-*.png
import puppeteer resolves correctly.page.goto.clip parameter instead of full-page sectioning.waitUntil: 'networkidle2' ensures async content has loaded. For SPAs with lazy loading, consider adding await page.waitForSelector('<selector>') before capturing.await page.evaluate(() => document.querySelector('<selector>').scrollIntoView()).