ScreenshotNeo

BlogHow-to

How to Screenshot an Infinite Scroll Page on a Slow Connection

Load the content you need before capturing an infinite-scroll page. Learn browser and Playwright methods, how to handle slow loading, and what to check when content is missing.

By the ScreenshotNeo team4 October 20269 min read

To screenshot an infinite-scroll page on a slow connection, first scroll through the page in manageable increments and wait for each new section and its images to load. Then capture the full page. A full-page screenshot records the document as it exists at capture time; it does not guarantee that a site has fetched and appended every section that could appear later.

This distinction matters because infinite scrolling usually adds content in response to scrolling, while lazy-loaded images are deferred until they approach the viewport. A browser’s load event alone does not mean all lazy images are ready. MDN’s lazy-loading guide and its image element reference describe these behaviors.

1. Decide what “complete” means

Before capturing, choose the intended stopping point. An endless feed may never have a natural end, and trying to load everything can take a long time or produce an enormous image. Decide whether you need a particular article, a date range, a number of entries, or everything currently available.

  • Final page image: load the sections you need, then take a full-page capture.
  • Loading progression: record how the page changes while it loads. A single final screenshot cannot show that timeline.
  • Repeatable capture: use browser automation with explicit scrolling, waits, and a stopping rule.

On a slow connection, there is no universal wait time that guarantees a section is ready. The right delay depends on the page and connection. Look for the section itself and its images rather than treating a fixed pause as proof of completion.

2. Load the page before capturing

  1. Open the page and wait for the first screen to settle. If you are investigating what appears during loading, open Chrome DevTools’ Network panel before reloading; its Screenshots feature can record page appearance alongside network activity.
  2. Scroll down by a portion of the page, not directly to the bottom. Pause while the site requests and renders more content.
  3. Check whether new sections appeared. If they did, continue in increments and wait again.
  4. At the intended stopping point, inspect the last section and its images. If expected content is missing, scroll farther or wait for the relevant content to appear.
  5. Capture the full page only after the content you need is present.
  6. Review the saved image at the top, middle, and bottom. Confirm the last expected section and important images are visible.

Scrolling is necessary for many infinite-scroll implementations because their next request is triggered by reaching a point on the page. It can also bring deferred images close enough to the viewport to load. A full-page capture command by itself does not prove that those site-specific requests have finished.

3. Capture with Firefox or Chrome

Firefox

Firefox DevTools can capture an entire page. If the screenshot button is not visible, enable it in DevTools settings under Available Toolbox Buttons. The Web Console also supports a full-page screenshot command:

screenshot capture.png --fullpage

Firefox saves the screenshot in the browser’s Downloads directory. First scroll and load the content you need; then use the full-page capture. See Mozilla’s Taking screenshots documentation.

Chrome

After loading the intended content, open DevTools’ Command Menu and search for Capture a full size screenshot. Chrome’s Device Mode documentation describes the full-size capture option.

If you need to document what appeared at different points during a slow load, use the Network panel’s Screenshots feature instead of relying on one final image. It records page appearance during loading with the network activity. See Chrome’s network activity guide and Network features reference.

4. Automate scrolling and capture with Playwright

For repeated captures, automate the process: scroll in steps, allow time for requests and rendering, detect whether the document continues growing, and stop when you reach your target or growth has stopped for several checks. The example below is a starting point for a page whose infinite-scroll content increases the document height. Adapt the stopping condition to the page; a stable height does not always mean the desired content loaded successfully.

Install Playwright and its Chromium browser in a Node.js project:

npm install playwright
npx playwright install chromium

Save as capture.mjs. Set TARGET_URL to the page you are authorized to access, then run TARGET_URL="https://example.com/feed" node capture.mjs.

import { chromium } from 'playwright';

const url = process.env.TARGET_URL;
if (!url) throw new Error('Set TARGET_URL to the page to capture.');

const browser = await chromium.launch({ headless: true });
const page = await browser.newPage({ viewport: { width: 1365, height: 900 } });

try {
  await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 60000 });
  // Give the initial page a chance to render. Slow pages may need a longer wait.
  await page.waitForTimeout(2000);

  const maxSteps = 80;
  const stableChecksNeeded = 4;
  let stableChecks = 0;
  let previousHeight = 0;

  for (let step = 0; step < maxSteps; step++) {
    const height = await page.evaluate(() => document.documentElement.scrollHeight);
    await page.evaluate(() => window.scrollBy(0, Math.max(500, window.innerHeight * 0.75)));

    // No fixed delay proves completeness; tune this for the target site's response time.
    await page.waitForTimeout(1800);

    const newHeight = await page.evaluate(() => document.documentElement.scrollHeight);
    if (newHeight > previousHeight || newHeight > height) {
      stableChecks = 0;
    } else {
      stableChecks++;
    }
    previousHeight = newHeight;

    // Stop after several checks without growth, or replace this with a page-specific end condition.
    if (stableChecks >= stableChecksNeeded) break;
  }

  // Return to the top before capturing the complete document.
  await page.evaluate(() => window.scrollTo(0, 0));
  await page.waitForTimeout(500);
  await page.screenshot({ path: 'capture.png', fullPage: true });
} finally {
  await browser.close();
}

The height-based loop is a heuristic, not a guarantee. For a more reliable job, replace it with a page-specific condition such as the appearance of a known final item, an expected item count, or a “no more results” marker. If the site does not increase document height when it loads more content, monitor a selector or item count instead. Playwright documents fullPage: true as capturing the full scrollable page in its Screenshots guide.

Useful adjustments

  • Slow responses: increase the per-step delay or wait for a specific content selector. Avoid using networkidle as a universal completion signal: analytics, polling, or persistent connections can keep a page active, and network quiet does not prove that the desired feed items appeared.
  • Known end marker: use await page.locator('.end-of-results').waitFor({ timeout: 30000 }) when the site has a reliable marker. Replace the selector with one from the page.
  • Lazy images: scroll each relevant region into view and wait for image loading. You can inspect images with document.images and their complete and naturalWidth properties, but some sites replace image elements or use CSS backgrounds.
  • Bound the job: set a maximum number of scroll steps, elapsed time, or items. This prevents a feed that never ends from running indefinitely.
  • Large pages: capture only the required range or split the output into sections if the browser runs out of memory or the resulting image is unwieldy.

5. Choose the right capture method

Method Best for What to account for
Firefox full-page screenshot A one-off capture after manual scrolling Content must already be loaded; enable the screenshot button if needed.
Chrome full-size screenshot A one-off full-page image after manual scrolling It captures the current page state, not future feed requests.
Chrome Network screenshots Seeing how the page looks at points during loading This is a loading record, not a substitute for a final complete-page capture.
Playwright Repeatable or scripted capture Implement and tune site-specific scrolling, waiting, and stopping logic.

6. Troubleshoot missing or incomplete content

Symptom Likely cause What to try
The screenshot ends after the first screen or a few sections The page had not appended later content before capture. Scroll in increments, wait for new items, and verify the target section is present before taking the full-page shot.
Some images are blank or missing Images may be lazy-loaded, still downloading, or dependent on scrolling into view. Scroll the image region into view, wait for it to render, and inspect the saved image. A completed page load event is not proof that lazy images are ready.
The script stops too soon A short delay or a few unchanged height checks were mistaken for completion. Increase the wait and stability threshold, or use a page-specific item count or end marker. Confirm the last expected item in the DOM.
The script never stops The page has ads, rotating content, polling, or an endless feed that keeps changing. Use a maximum step count, time limit, item count, or explicit target boundary instead of waiting for the page to become globally idle.
The page height stops growing but content is still absent The site may load inside a fixed-height container, replace existing items, or have hit an error. Watch the relevant container’s item count or a known item selector. Check DevTools Network and Console for failed requests.
Capture is very tall, slow, or fails Too much content is loaded for a single image or the browser’s available memory. Limit the capture to the needed range, use a narrower viewport only if appropriate, or save separate section captures.
Chrome shows no screenshot button in the toolbar The control may not be enabled in the current DevTools layout. Use the Command Menu and search for the full-size screenshot command.

7. Performance, reliability, and cost considerations

Each scroll step gives the browser time to request and render more content, so a slow connection naturally makes capture take longer. Short waits make the script finish sooner but increase the chance of missing items; excessively long waits add time without proving completeness. Tune waits against observable page-specific signals where possible.

Reliability depends on the stopping condition. A fixed number of scrolls is predictable but may end before the target; waiting for document height to stop changing can fail on feeds that update in place or continue changing for unrelated reasons. A known item, count, or end marker is usually more meaningful when the site provides one. Review the output rather than assuming a successful screenshot call means the capture is complete.

For very long pages, full-page images can require substantial memory and may be difficult to inspect or share. Capture a defined segment when that meets the goal. The browser approaches described here do not have a per-screenshot service charge, though they use your computer’s time and resources. ScreenshotNeo’s service pricing is listed below.

8. Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. A single request can return a screenshot or PDF. For this infinite-scroll use case, the important limitation remains: the content must exist on the page for it to be captured. A full-page option can load lazy images, but do not assume one API call will trigger every site’s custom infinite-scroll fetch. If later feed items are essential, use the scrolling workflow above or a page-specific automation step first.

For an ordinary page capture, call the API with a URL:

curl -G "https://api.screenshotneo.com/v1/shot" \
  -d access_key=YOUR_API_KEY \
  --data-urlencode url=https://stripe.com \
  -o shot.webp
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)
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 Bun.write('shot.webp', res);

See the ScreenshotNeo API documentation for request options. Cookie and consent banners are accepted and removed before capture, along with supported newsletter popups and chat widgets; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers indicate the page verdict and billing status. ScreenshotNeo also offers an MCP server so AI agents can use screenshot, page-info, and PDF tools.

The free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 screenshots; every feature is on every plan. For a slow infinite-scroll page, use the API when the desired content is already loaded or your workflow can load it first.

Sign up for 1,000 free screenshots a month, with no card.

Frequently asked questions

Can I capture content that has not loaded yet?

No. A screenshot records the rendered page state available to the capture process. Load the needed feed items first.

Does full-page capture automatically scroll an infinite feed?

Do not rely on that. Full-page capture covers the current scrollable document; custom feed requests commonly need scrolling or site-specific interaction to run.

How long should I wait between scrolls?

There is no universal delay. Start with a reasonable pause, then tune it to the target site’s response and use a visible item, count, or end marker when available.

Should I save one giant image?

Only if that is useful for your purpose. For exceptionally long pages, a bounded range or multiple section captures can be easier to render and review.