Hardware FixRecommendedDevice not working? Your driver may be the problemCheck updates for common hardware issues.Fix DriversHalloween DealsAmazon USHalloween week deals: useful picks before month-endAmazon US: current deals, useful picks and tech finds.Check DealsWindows FixRecommendedWindows errors stealing your time? Find the fix fastScan stability, cleanup and performance issues.Fix Now×
Skip to content
World desk7 min

Puppeteer Screenshot of an Infinite-Scroll Page Without Duplicate Sections

Puppeteer’s fullPage option captures rendered page extent, not an infinite feed automatically. Scroll the correct container, verify unique items and a real stopping condition, then capture.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

To capture an infinite-scroll page without repeated sections, first make the page load the content you want, then verify that its rendered items are unique, and only then call page.screenshot({ fullPage: true }). Puppeteer’s full-page option captures the page’s current rendered extent; it does not scroll through an infinite feed or guarantee that the feed has finished loading.

How to capture an infinite-scroll page with Puppeteer

The right sequence is: navigate, wait for a page-specific starting signal, scroll the actual feed container in bounded steps, check whether new unique items arrived, and take one screenshot after the content and layout settle. Puppeteer provides the browser-control primitives; the selectors, scroll logic, and stopping condition must match the target site.

As an Amazon Associate I earn from qualifying purchases.

Puppeteer’s screenshot guide recommends Page.screenshot() for screenshots. The ScreenshotOptions API defines fullPage: true as capturing the full page; the default is false. Neither setting means “scroll until the infinite feed ends.”

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Runnable control-flow example

Install Puppeteer in your project with npm install puppeteer. Save this as an ES module, such as screenshot.mjs, then run node screenshot.mjs https://example.com/feed. Replace the example selectors and ID attribute with those used by the page. The bounded loop is a defensive pattern, not a universal or officially prescribed infinite-scroll algorithm.

import puppeteer from 'puppeteer';

const url = process.argv[2];
if (!url) throw new Error('Usage: node screenshot.mjs <url>');

const ITEM = '[data-feed-item]';
const MAX_SCROLLS = 30;
const STABLE_ROUNDS_REQUIRED = 3;
const SETTLE_MS = 800;

const browser = await puppeteer.launch({ headless: true });
try {
  const page = await browser.newPage();
  await page.goto(url, { waitUntil: 'networkidle2' });
  await page.waitForSelector(ITEM);

  let previousUniqueCount = 0;
  let stableRounds = 0;

  for (let i = 0; i < MAX_SCROLLS && stableRounds < STABLE_ROUNDS_REQUIRED; i++) {
    await page.evaluate(() => {
      window.scrollTo(0, document.documentElement.scrollHeight);
    });

    // Replace this with a page-specific wait if the feed exposes one.
    await new Promise(resolve => setTimeout(resolve, SETTLE_MS));

    const uniqueCount = await page.$$eval(ITEM, items => {
      const keys = items.map(item =>
        item.getAttribute('data-id') || item.textContent.trim()
      );
      return new Set(keys).size;
    });

    stableRounds = uniqueCount === previousUniqueCount ? stableRounds + 1 : 0;
    previousUniqueCount = uniqueCount;
  }

  const counts = await page.$$eval(ITEM, items => {
    const keys = items.map(item =>
      item.getAttribute('data-id') || item.textContent.trim()
    );
    return { rendered: keys.length, unique: new Set(keys).size };
  });
  console.log('Feed items:', counts);

  await page.screenshot({ path: 'page.png', fullPage: true });
} finally {
  await browser.close();
}

This example scrolls the document, waits a fixed settling interval, and stops after three rounds without an increase in unique items or after 30 scrolls. Those values are adjustable safeguards, not proof of completion. Prefer a site’s explicit end marker or a specific content-change condition when available. Puppeteer documents evaluate(), waitForFunction(), and network-idle waiting as page APIs, but does not prescribe this loop or guarantee that it detects a finished feed (Page API).

Adapt the scroll and completion checks to the page

Find the real scroll container

Some feeds scroll the document; others load content inside a nested element with its own scrollbar. If the feed is nested, scrolling window may never trigger its loading handler. Identify the element whose scrollTop changes as you scroll, then update that element in page.evaluate() and measure its scrollHeight or feed-item count. The page’s own intersection observers or event handlers need an opportunity to run.

Use a meaningful stopping condition

  • End marker: Stop when a page-specific “end of results” element appears, if the site exposes one.
  • Unique-item count: Compare stable item identifiers across rounds. A count of DOM nodes alone can rise because duplicates were appended.
  • No-change threshold: If there is no explicit marker, stop after a chosen number of rounds without new unique items, while retaining a maximum-scroll limit.
  • Network idle: Use it as a possible settling signal, not as proof the feed is complete. Another scroll may be needed to trigger the next request.

For a page-specific predicate, Puppeteer’s waitForFunction() can wait until an observable condition becomes true. Avoid waiting only for “at least one item”: once the first item exists, that condition may already be true before the next batch arrives. The relevant tools are documented in the Page API.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Why a screenshot may repeat sections

Check the rendered page before changing screenshot settings. If the DOM already contains repeated item IDs or content, the site’s feed-rendering behavior is producing duplicates; fullPage does not remove them. If the DOM is correct but the image appears repeated, investigate whether the feed had finished updating, whether you scrolled the right container, and whether sticky or fixed page elements are being mistaken for repeated content.

Puppeteer’s documentation defines screenshot capture and full-page extent, but does not establish a universal cause of repeated sections or a built-in deduplication option (ScreenshotOptions; Page API). Compare the item identifiers in the DOM with the screenshot to isolate whether repetition starts in the page or in the capture/layout outcome.

Virtualized feeds and choosing the output

A virtualized feed may remove off-screen items from the DOM as new ones appear. In that case, reaching the end does not mean earlier items remain available for one full-page capture. A full-page screenshot should not be assumed to contain content the application no longer renders.

  • If the full feed remains in the DOM, scrolling to completion and taking one full-page capture may suit the task.
  • If the feed is virtualized, consider capturing viewport-sized screenshots as you scroll and combining them only if the page layout makes that reliable, or use the site’s underlying paginated data/export path where permitted.
  • If content is loaded by cursor or “load more” controls, use the site’s actual progression mechanism and verify each new batch rather than relying on document height alone.

Capture after content and layout stabilize

Once the feed has reached the stopping condition and the item IDs have been checked, take the screenshot with:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
await page.screenshot({ path: 'page.png', fullPage: true });

That call captures the page as rendered at that point. For screenshot operations generally, Puppeteer documents coordination intended to prevent certain BrowserContext operations from interfering with a screenshot in progress (Page.screenshot() API); it does not define how a site stores or updates its feed records.

Troubleshooting

The script captures only the first batch

Confirm that the correct scroll container is being moved and that the site loads content from scrolling rather than a button or cursor request. Replace generic waits with a page-specific condition that can change after the next batch arrives.

The loop stops while more content exists

A temporary pause may leave the unique-item count unchanged even though a request is still in flight. Increase the settling interval or wait for a known loading indicator to disappear or a known item count to increase. Do not treat network inactivity as a universal end-of-feed signal.

The loop never stops

Keep a hard maximum iteration count. Infinite feeds may continuously append content, mutate identifiers, or show changing elements that make an overly broad condition appear to change forever. Prefer stable item IDs and a real end marker.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The duplicate count is misleading

Text content may not uniquely identify records: two legitimate posts can have identical text, while one record may change its text after rendering. Prefer a stable data ID or link URL. If the site exposes no stable key, treat text-based uniqueness as a diagnostic approximation, not a definitive deduplication test.

The screenshot omits earlier content

Check whether the application virtualizes the feed and removes off-screen items from the DOM. A full-page screenshot cannot capture records that are no longer rendered. Use a viewport-by-viewport capture workflow or another page-supported export strategy where appropriate.

The screenshot looks repeated although the DOM does not

Inspect the actual rendered image and review fixed headers, sticky elements, and capture timing. Puppeteer’s documented fullPage option sets capture extent; the documentation does not promise to normalize sticky elements or diagnose repeated visual bands.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. For a single request, it accepts a URL and returns an image or PDF. Example cURL request:

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com/feed -o shot.webp

See the ScreenshotNeo API documentation for request options. The API can capture full pages and can wait for a selector, a delay, or network idle, but an infinite feed still needs page-specific handling and validation: a full-page request should not be taken as proof that every item has loaded or that the site has no duplicate records.

  • Cookie banners are accepted and more than 60 known consent platforms, newsletter popups, and chat widgets are removed before capture; each step can be turned off.
  • Bot checks/CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing; response headers identify the page verdict and billing status.
  • An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for AI agents and MCP clients.
  • The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000.

Sign up for ScreenshotNeo’s free plan to get 1,000 screenshots a month with no card.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Crashes, No Sound, or Screen Glitches?Free driver scan
PC Slower Than It Used to Be?Free scan - under a minute

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.