Back to Blog
Guide February 23, 2026 · 4 min read

How to Take a Screenshot with Node.js (and Record Narrated Videos)

Take website screenshots in Node.js with a single fetch call — no Puppeteer, no binary dependencies. Then step up to narrated video recording when you need more.

The Puppeteer approach to screenshots in Node.js looks like this: install the package, wait for Chromium to download, launch a browser, open a page, wait for it to load, take the screenshot, close the browser, handle the cleanup. Eight steps, one dependency that's 300MB, and a process that leaks memory in production.

Here's the short version.

Quick start: screenshot in Node.js

import fs from 'fs';

const response = await fetch('https://api.pagebolt.dev/v1/screenshot', {
  method: 'POST',
  headers: {
    'x-api-key': process.env.PAGEBOLT_API_KEY,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    url: 'https://example.com',
    fullPage: true,
    blockBanners: true
  })
});

fs.writeFileSync('screenshot.png', Buffer.from(await response.arrayBuffer()));

No npm install. No binary. Works in any Node.js environment — Lambda, Cloud Run, a cron job, a CI pipeline.

blockBanners removes cookie consent popups automatically. fullPage captures the entire scrollable page, not just the viewport.

Lazy-loaded content

If the page uses lazy loading, images below the fold will appear blank without an explicit scroll. Add fullPageScroll:

body: JSON.stringify({
  url: 'https://example.com',
  fullPage: true,
  fullPageScroll: true  // scrolls page before capture, forces lazy images to load
})

Mobile viewport

body: JSON.stringify({
  url: 'https://example.com',
  viewportDevice: 'iphone_14_pro'
})

25+ device presets. Useful for checking responsive layouts or generating mobile-specific thumbnails.

Pages behind a login

body: JSON.stringify({
  url: 'https://app.example.com/dashboard',
  cookies: ['session=abc123; Domain=example.com'],
  fullPage: true
})

Step up: record a narrated video

Screenshots show state. Videos show flow. If you're building demo tooling, automated QA, or PR review artifacts, a narrated recording is worth the extra two lines.

const response = await fetch('https://api.pagebolt.dev/v1/video', {
  method: 'POST',
  headers: {
    'x-api-key': process.env.PAGEBOLT_API_KEY,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    steps: [
      { action: 'navigate', url: 'https://yourapp.com' },
      { action: 'click', selector: '#get-started', note: 'Opening the signup form' },
      { action: 'fill', selector: '#email', value: 'demo@example.com' },
      { action: 'click', selector: '#submit', note: 'Submitting' },
      { action: 'wait', ms: 1500 },
      { action: 'screenshot', name: 'result' }
    ],
    audioGuide: {
      enabled: true,
      voice: 'nova',
      script: 'Welcome. {{2}} Click Get Started. {{4}} Submit the form. {{5}} Done.'
    },
    pace: 'slow',
    frame: { enabled: true, style: 'macos' }
  })
});

fs.writeFileSync('demo.mp4', Buffer.from(await response.arrayBuffer()));

The audioGuide.script syncs an AI voice to specific steps using {{N}} markers. The output is an MP4 with browser chrome, natural pacing, and narration — ready to embed in a PR comment, a Loom, or a product changelog.

Voices: nova, alloy, echo, fable (OpenAI) or emma, ava, brian, aria (Azure).

Both patterns, zero browser management

The same API key, the same fetch call structure. No Chromium binary, no browser pool, no memory leak debugging. Screenshots for snapshots, video for everything that needs to show motion or tell a story.

Free tier — 100 requests/month

No credit card required. Full API access including screenshots, video recording, PDF generation, and page inspection.

Get your free API key