Tutorial··8 min read

How to Take Full Page Screenshots with an API

A viewport screenshot captures 800 pixels of content. A full page screenshot captures everything — the entire scrollable page from header to footer. Here's how to do it with a simple API call, and how it compares to self-hosted browser approaches.

Viewport vs full page: the difference

Every screenshot tool defaults to viewport mode — it captures only what fits in the browser window. For most websites, that's the header, hero section, and maybe the first content block. Everything below the fold is cut off.

Viewport screenshot

  • Captures visible area only (e.g., 1280x800)
  • Small file size
  • Fast capture
  • Good for: thumbnails, previews, OG images

Full page screenshot

  • Captures entire scrollable content
  • Can be 5,000-20,000+ pixels tall
  • Slightly slower (full render needed)
  • Good for: archival, QA, design review, documentation

1

SnapRender API (easiest)

Add full_page: true to your request body. That's it. The API scrolls the page, triggers lazy loading, waits for content to render, and captures the full scrollable height.

Viewport only (default)

viewport screenshot
// Viewport-only screenshot (default behavior)
const response = await fetch('https://api.snaprender.dev/v1/screenshot', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    url: 'https://example.com',
    viewport: { width: 1280, height: 800 }
  })
});
// Result: 1280x800 image — only what's visible in the "window"

Full page

full page screenshotfull_page: true
// Full page screenshot — captures entire scrollable content
const response = await fetch('https://api.snaprender.dev/v1/screenshot', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    url: 'https://example.com',
    full_page: true,
    viewport: { width: 1280, height: 800 }
  })
});
// Result: 1280x(full height) image — entire page captured

2

Puppeteer

Puppeteer supports fullPage: true natively. It works well for static pages, but lazy-loaded content requires manual scrolling before capture.

puppeteer
const puppeteer = require('puppeteer');

(async () => {
  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' });

  // Full page screenshot
  await page.screenshot({
    path: 'full-page.png',
    fullPage: true  // <-- this is the key parameter
  });

  await browser.close();
})();

3

Playwright

Same parameter as Puppeteer. Playwright's auto-waiting helps with dynamic content, but lazy-loaded images still need a scroll-to-bottom pass for complete capture.

playwright
const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch();
  const page = await browser.newPage({
    viewport: { width: 1280, height: 800 }
  });
  await page.goto('https://example.com');

  // Full page screenshot
  await page.screenshot({
    path: 'full-page.png',
    fullPage: true  // <-- same parameter name
  });

  await browser.close();
})();

The lazy loading problem

Most modern websites lazy-load images and content. Images below the fold don't load until the user scrolls to them. With fullPage: true, Puppeteer and Playwright expand the viewport but don't trigger scroll events — so lazy-loaded images show as blank placeholders.

The fix is to scroll to the bottom of the page before capturing. SnapRender does this automatically. With Puppeteer, you need a manual scroll function:

lazy load workaround (puppeteer)
// SnapRender handles lazy-loaded content automatically.
// With Puppeteer, you need manual scrolling:

async function scrollToBottom(page) {
  await page.evaluate(async () => {
    await new Promise((resolve) => {
      let totalHeight = 0;
      const distance = 500;
      const timer = setInterval(() => {
        window.scrollBy(0, distance);
        totalHeight += distance;
        if (totalHeight >= document.body.scrollHeight) {
          clearInterval(timer);
          resolve();
        }
      }, 100);
    });
  });
}

// Scroll first to trigger lazy loading, then capture
await scrollToBottom(page);
await page.screenshot({ path: 'full-page.png', fullPage: true });

SnapRender handles this automatically. The API scrolls the page, waits for lazy-loaded content to render, then captures. No extra code needed — just set full_page: true.


Full page screenshots in any language

Since SnapRender is a REST API, full page screenshots work from any language or tool. Here are Python and cURL examples:

Python

python
import requests

# Full page screenshot with SnapRender API
response = requests.post(
    "https://api.snaprender.dev/v1/screenshot",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    json={
        "url": "https://example.com",
        "full_page": True,
        "viewport": {"width": 1440, "height": 900},
        "format": "png"
    }
)

with open("full-page.png", "wb") as f:
    f.write(response.content)

cURL

curl
curl -X POST https://api.snaprender.dev/v1/screenshot \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "full_page": true,
    "viewport": {"width": 1280, "height": 800},
    "format": "png"
  }' \
  --output full-page.png

Method comparison

FeaturePuppeteerPlaywrightSnapRender
Full page supportYes (fullPage: true)Yes (fullPage: true)Yes (full_page: true)
Lazy load handlingManual scroll neededManual scroll neededAutomatic
Sticky element handlingManual CSS injectionManual CSS injectionAutomatic
Cloudflare sitesBlockedBlockedBypass included
Max page heightBrowser memory limitBrowser memory limit20,000px
Setup requiredChromium installBrowser installNone (API call)

Full page screenshots, zero setup

100 free screenshots per month. Full page, lazy loading handled, Cloudflare bypass included. No browser to install. No credit card.

Get your API key

Frequently asked questions

A full page screenshot captures the entire scrollable length of a web page — not just the visible viewport. The resulting image can be thousands of pixels tall, capturing everything from the header to the footer including content that requires scrolling to see.

The browser calculates the total height of the page content, resizes its internal viewport to match, and captures the entire area in one render pass. This is more reliable than scrolling and stitching multiple viewport captures, which can miss sticky elements or cause layout shifts.

A viewport screenshot captures only what's visible in the browser window (typically 1280x800 pixels). A full page screenshot captures the entire scrollable content, which can be 5,000-20,000+ pixels tall depending on the page.

It depends. Puppeteer and Playwright need custom scrolling logic to trigger lazy-loaded images before capture. SnapRender's API handles this automatically — it scrolls the page to trigger lazy loading before capturing the full page.

SnapRender is the easiest — add full_page: true to your API request. No browser setup, handles lazy loading, works with Cloudflare-protected sites. Puppeteer and Playwright also support it but require self-hosted infrastructure.