ScreenshotNeo

BlogComparisons

Best Screenshot API for Full-Page Scrolling Captures

Compare full-page capture strategies, handle lazy-loaded content, and choose an API or Playwright workflow that fits your pages.

By the ScreenshotNeo team4 October 202610 min read

Direct answer: there is no independently tested universal winner for full-page scrolling captures. Choose a managed screenshot API when you want a hosted endpoint and its controls fit your pages. Try stitched or section-based capture when native full-page rendering misses content or mishandles sticky elements; try native capture when speed matters and your pages render correctly. Choose Playwright when you want to run and maintain browser automation yourself.

ScreenshotNeo is the first hosted API to try if you want clean captures and clear billing outcomes: cookie banners, popups, and chat widgets are removed before capture, and bot checks, blank pages, and failed loads are not billed. The sections below explain how full-page capture works, how to evaluate providers, and how to make captures more complete.

1. What makes full-page scrolling captures difficult?

A full-page screenshot combines content beyond the browser’s current viewport. The challenge is that some content does not exist or render until the page is scrolled: lazy-loaded images, animations, and other scroll-triggered elements can be absent from a capture taken too early. Fixed or sticky elements can also appear in awkward places when a long page is assembled.

Providers document different ways to address these issues. A native full-page capture asks the browser to render the full scrollable page. A scrolling, stitched, or section-based method visits portions of the page and combines captures. Scrolling first can trigger lazy loading; stitching can address some layout problems but may take longer. Neither method guarantees a perfect result on every site.

2. Screenshot API options and tradeoffs

Option Documented approach Consider it when
ScreenshotNeo Hosted screenshot API and MCP server. Supports full-page capture with lazy images loaded, plus controls such as wait conditions, viewport, device presets, custom CSS and JavaScript, and request blocking. Cookie banners, newsletter popups, and chat widgets can be removed before capture. You want a managed API, clean shots, response headers that identify page verdict and billing, or screenshot tools for AI agents. See the ScreenshotNeo API documentation.
ScreenshotOne Documents full_page=true, which enables scrolling by default unless overridden, and a by_sections algorithm that captures and combines sections. Its guide says section capture can help with complex pages and animation, with a possible performance cost. You want to compare a documented native-style full-page option with section-based capture and tune scroll distance, scroll delay, or maximum height.
Urlbox Documents a default stitch mode and a native mode. Its documentation describes stitch as more accuracy-oriented and native as faster but potentially less reliable on some sites. It normally scrolls to the bottom and back before capture; skip_scroll disables that step. You want to compare stitched and native modes, or test whether skipping the preliminary scroll helps latency on your pages.
Playwright Self-hosted browser automation. Its Page API supports page.screenshot({ fullPage: true }) to capture the full scrollable page. You want a browser automation building block that your team can run and maintain.

These are documented approaches, not results from a controlled comparison. The documentation does not establish that one service is most reliable or fastest across real sites. Treat the table as a shortlist, then test pages representative of your own workload.

3. Test providers with representative pages

  1. Choose a test set. Include a tall article, lazy-loaded images, sticky navigation, animated content, and an infinite-scroll page if those appear in your workload.
  2. Keep the URL and conditions consistent. Use the same target page and comparable viewport dimensions for each capture. Note any authentication, locale, or page state needed to reproduce it.
  3. Check content completeness. Confirm that content near the bottom and images loaded on scroll appear in the result.
  4. Inspect layout artifacts. Look for repeated or frozen sticky elements, seams between sections, clipped backgrounds, and shifts caused by animation.
  5. Compare operational fit. Record latency, available controls, failure reporting, billing behavior, and how much infrastructure your team would need to run.
  6. Repeat variable pages. Animated, personalized, or frequently changing pages can differ between runs. Compare more than one capture before choosing a workflow.

This is an evaluation checklist, not a published benchmark. No provider has been tested here on a shared page set.

4. Capture a full page with Playwright

Playwright is a practical do-it-yourself option when you can install and operate a browser. The minimal example below opens a URL and saves a full-page PNG. Install Playwright and its Chromium browser first:

npm init -y
npm install playwright
npx playwright install chromium

Save this as screenshot.mjs, then run it with a URL:

import { chromium } from 'playwright';

const url = process.argv[2];
if (!url) throw new Error('Usage: node screenshot.mjs https://example.com');

const browser = await chromium.launch({ headless: true });
try {
  const page = await browser.newPage({ viewport: { width: 1440, height: 900 } });
  await page.goto(url, { waitUntil: 'networkidle', timeout: 60_000 });
  await page.screenshot({ path: 'full-page.png', fullPage: true });
} finally {
  await browser.close();
}

networkidle is a useful starting point, but it can be unsuitable for pages with long-lived network requests, and it does not guarantee that scroll-triggered content has loaded. For such pages, use a deliberate scroll pass and wait for the content you need before taking the screenshot:

await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 60_000 });
await page.evaluate(async () => {
  const step = Math.max(200, Math.floor(window.innerHeight * 0.75));
  for (let y = 0; y < document.documentElement.scrollHeight; y += step) {
    window.scrollTo(0, y);
    await new Promise(resolve => setTimeout(resolve, 250));
  }
  window.scrollTo(0, 0);
});
await page.waitForTimeout(500);
await page.screenshot({ path: 'full-page.png', fullPage: true });

The scroll loop is a starting point, not a universal setting. A page may extend its height as more content loads, so a single initial height can be insufficient for infinite scroll. For those pages, define a stopping rule based on the expected content, a maximum scroll depth, or a stable page condition. Avoid unbounded scrolling.

Playwright’s documented option is fullPage: true. The code above adds a viewport and waits as implementation choices; the Playwright API documentation does not promise that a particular wait strategy or scrolling loop will work for every page. See the Playwright Page API.

5. Tune scrolling and waits when content is missing

  • Scroll before capture. This can trigger lazy-loaded images and scroll-dependent content. Some hosted APIs perform this automatically for full-page captures.
  • Adjust scroll distance. Smaller steps can help trigger lazy loading on some pages. ScreenshotOne suggests trying 100–500 pixel distances in its documentation; treat that as a troubleshooting range, not a universal rule.
  • Add a scroll delay. Give the page time to fetch and render content after each movement. Tune this against the slowest pages you need to support.
  • Wait for a useful condition. If the page has a reliable selector for the content or a known completion signal, wait for it instead of relying only on a fixed delay.
  • Limit capture height where appropriate. A maximum height can bound unusually tall pages and help prevent infinite-scroll captures from growing without limit.
  • Test reduced motion. Reducing motion may make some captures more consistent. It is best-effort: custom JavaScript animation, canvas content, and animated images can still vary.

On ScreenshotOne, full_page=true enables full_page_scroll=true by default unless overridden. Its by_sections algorithm scrolls automatically regardless of that option. Urlbox documents scrolling to the bottom and back before capture by default; its skip_scroll option can disable that behavior. Consult each provider’s current documentation for exact parameters and defaults.

6. How to choose a capture strategy

  • Start with native full-page capture when the page has ordinary document flow and a fast, simple capture matters. Check the result for missing lazy content and layout defects.
  • Try stitch or section-based capture when a native capture has layout problems, the page has sticky elements, or content depends on scrolling. Budget for potentially longer capture time.
  • Use preliminary scrolling when lazy-loaded content is missing. Tune distance and delay against the page rather than copying one setting to every site.
  • Use a height cap and explicit stopping rule for infinite-scroll or continuously growing pages.
  • Choose hosted or self-hosted based on operations. A hosted API provides a managed endpoint. Playwright gives you a browser automation building block, while your team operates the browser workflow.

7. Or skip the browser setup

ScreenshotNeo captures a URL with one GET request. The result is an image or PDF. This example saves the returned image as WebP:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

For Python, install requests with python -m pip install requests and run:

import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)

For Node.js with a runtime that supports fetch:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer())));

Use the ScreenshotNeo documentation for API options and configuration. Full-page capture can load lazy images. Other relevant controls include CSS selector capture, viewport and device presets, retina scale, custom CSS or JavaScript, selector or network-idle waits, delay, request blocking, headers, cookies, user agent, caching with a chosen TTL, and image resizing. For page-specific behavior, check the docs for supported parameter names and values.

ScreenshotNeo removes cookie banners, popups, and chat widgets before the shot. Bot checks, blank pages, and failed loads are never billed; response headers report the page verdict and billing outcome. An MCP server lets AI agents use take_screenshot, get_page_info, and capture_pdf. The Free plan includes 1,000 shots a month with no card; paid plans start at $5 for 3,000 shots. Sign up free for 1,000 screenshots a month, with no card.

8. Performance, reliability, and cost

Performance

Preliminary scrolling and section stitching add browser work and can increase capture time. A native capture may be faster on a page that renders correctly, while smaller scroll increments and longer delays can increase total time. Measure on your own pages and set request timeouts to match the capture workflow.

Reliability

Full-page capture depends on the page’s behavior as well as the screenshot method. Lazy content, sticky layout, animation, infinite scrolling, authentication, and variable page height can all affect the result. Keep representative regression URLs and inspect outputs after changing capture settings. Animation reduction is not a guarantee that every dynamic element will become static.

Cost

For hosted APIs, check current plan limits and prices directly before choosing; provider pricing can change, and the research sources do not establish a shared price comparison. For self-hosted Playwright, consider the browser runtime and the engineering work needed to operate, monitor, and maintain it. ScreenshotNeo’s listed plans are Free: 1,000 shots per month with no card; Starter: $5 for 3,000; Growth: $15 for 15,000; Pro: $39 for 60,000; Scale: $99 for 250,000; and Business: $249 for 1,000,000. Yearly billing gives two months free, and every feature is on every plan.

9. Troubleshooting full-page captures

Symptom Likely cause What to try
Images or sections are missing near the bottom They load only after scrolling, or the capture begins before rendering finishes. Scroll before capture, add a per-step delay, reduce scroll distance, or wait for a content selector.
Sticky header repeats or appears in the wrong place The chosen capture algorithm handles fixed positioning poorly for this layout. Compare native and stitched or section-based modes on the same URL; inspect the output for artifacts.
Capture is unexpectedly slow Long scroll delays, section stitching, a very tall page, or a wait condition that never resolves can extend the job. Measure each stage, use a suitable timeout, cap height when appropriate, and test whether a shorter scroll delay or native mode still captures complete content.
Infinite-scroll capture keeps growing Every scroll triggers more content and the page never reaches a natural bottom. Set a maximum height or a bounded scroll count, and define which amount of content is useful.
Animated areas differ between runs Animation or dynamic content changes while the browser captures. Try reduced motion or a wait for a stable condition; expect custom JavaScript, canvas, and animated images to remain variable.
Waiting for network idle times out The page may keep network connections open or continue making background requests. Use a less restrictive navigation condition, then wait for a specific selector or a bounded delay that matches the page.
Capture clips content or background The page has unusual dimensions, full-height backgrounds, or layout changes during scrolling. Compare capture modes, adjust viewport dimensions, and test the exact page at the intended output size.

10. Frequently asked questions

How do I take a full-page screenshot of a scrolling website?

Use a screenshot API’s full-page option or, with Playwright, call page.screenshot({ fullPage: true }). If the page loads content on scroll, scroll through it and wait for that content before capturing.

Does full-page capture always include lazy-loaded images?

No. Scrolling before the capture can trigger lazy loading, but page behavior and timing vary. Inspect the output and tune the scroll steps and waits when needed.

Is native capture better than stitching?

Neither is best for every page. Native capture may be faster; stitching or section capture may help with some complex layouts. Test both on the pages that matter to your application.

Can I use full-page capture for an infinite-scroll feed?

Yes, but define a maximum height, scroll count, or other stopping condition. An infinite feed may keep adding content indefinitely.

Sources