Basic screenshot
npm install puppeteer
import puppeteer from "puppeteer";
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setViewport({ width: 1280, height: 800 });
await page.goto("https://example.com", { waitUntil: "networkidle2" });
await page.screenshot({ path: "example.png" });
await browser.close();
Full page, retina and formats
await page.setViewport({ width: 1280, height: 800, deviceScaleFactor: 2 }); // retina
await page.screenshot({ path: "full.jpg", fullPage: true, type: "jpeg", quality: 80 });
Mobile devices
import { KnownDevices } from "puppeteer";
await page.emulate(KnownDevices["iPhone 13"]);
await page.goto("https://example.com");
await page.screenshot({ path: "iphone.png" });
Viewport sizes of all common devices are on the viewport sizes pages.
One element
const element = await page.waitForSelector("#pricing");
await element.screenshot({ path: "pricing.png" });
Hide cookie banners and chat widgets
await page.addStyleTag({ content: "#onetrust-banner-sdk, .intercom-launcher { display: none !important; }" });
Problems in production
- Memory and crashes: each Chrome instance needs a few hundred MB; leaked pages bring servers down.
- Fonts and emoji: Linux servers lack fonts, so pages render with fallback fonts and empty boxes.
- Bot detection: many sites block headless Chrome.
- Cookie banners and ads differ per site and country.
- Timeouts and retries for slow pages.
A screenshot API handles these for you; with screenshotbase the same screenshot is one request:
curl -G "https://api.screenshotbase.com/v1/take" --data-urlencode "url=https://example.com" \
-d full_page=true -d block_cookie_banners=true -H "apikey: YOUR-API-KEY" -o example.png
Try it without code: website screenshot tool.