ScreenshotNeo

BlogHow-to

How to Capture Pages That Load Content on Scroll with Screenshot.Rocks

Load scroll-triggered content before capturing a full page, then bring the image into Screenshot.Rocks to frame and export it.

By the ScreenshotNeo team4 October 202610 min read

To capture a page whose images or sections appear only as you scroll, first scroll through the part you need and wait for deferred content to load. Then make a full-page screenshot with your browser or a capture tool that scrolls through the page. Screenshot.Rocks’ extension captures only the visible part of the current tab; import the completed full-page image into its editor to choose a frame and background, then export it. Screenshot.Rocks documents this workflow.

The important detail is that “full page” and “scrolls the page” are different behaviors. A tool can produce a tall image without triggering content that loads only when it enters the viewport. For those pages, the capture process needs to visit the relevant sections before it records them. ScreenshotOne’s full-page guide describes section-by-section scrolling and notes that scroll timing can affect whether lazy-loaded content appears.

1. Identify what kind of page you are capturing

Before choosing a method, decide which content should appear in the result:

  • Finite page: A normal article or product page has a bottom. Scroll through the whole page, let its deferred content settle, and capture the full page.
  • Infinite feed: More content appears as you approach the bottom. Choose a stopping point or item count first. There is no natural final page height to capture.
  • Nested scroll area: A feed, table, or panel may scroll inside the page rather than moving the main document. Scrolling the window alone may not load its contents.
  • Authenticated page: A page behind a login may be available in your current browser tab, but a separate browser automation or URL-based service will need its own authenticated session or credentials.

Also decide whether you need one tall image or a paginated document, and whether sticky navigation, consent prompts, or chat controls belong in the final image.

2. Use Screenshot.Rocks for the finishing step

  1. Open the target page and allow the initial load to finish.
  2. Scroll down in stages through every section you need. Pause while images, cards, or loading indicators are still changing.
  3. Use your browser’s full-page screenshot feature, or a capture method that scrolls and stitches page sections.
  4. Inspect the saved image for missing sections, blank image areas, duplicated sticky headers, overlays, and cut-off content.
  5. Drop the screenshot into the Screenshot.Rocks editor, choose a frame or background, and export.

Screenshot.Rocks says its extension works on the visible part of the current tab, including pages behind a login. The full-page capture happens separately through the browser or another capture tool. Its extension page says there is no Safari extension; Safari users can use a separate full-page capture route and then import the resulting image.

Browser commands vary, and the available sources do not establish a universal shortcut for each browser. Use the full-page or web capture command provided by your browser, and verify that it actually scrolls through the page when the content is lazy-loaded. A one-shot page-height capture may miss content that was never brought into view.

3. Automate the scroll and capture with Playwright

For repeatable captures, Playwright can scroll the page in increments, wait between increments, return to the top, and save a full-page screenshot. The examples below are runnable starting points for finite pages. They cap the number of scroll steps so an expanding feed cannot run forever.

Node.js

npm install playwright
npx playwright install chromium
// capture.mjs
import { chromium } from 'playwright';

const url = process.argv[2] ?? 'https://example.com';
const output = process.argv[3] ?? 'page.png';
const maxSteps = 80;
const stepRatio = 0.8;
const waitMs = 700;

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

try {
  await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 60_000 });
  await page.waitForLoadState('load', { timeout: 15_000 }).catch(() => {});

  let previousHeight = 0;
  let stableAtBottom = 0;
  for (let step = 0; step < maxSteps; step++) {
    const height = await page.evaluate(() => document.documentElement.scrollHeight);
    const viewport = await page.evaluate(() => window.innerHeight);
    const y = await page.evaluate(() => window.scrollY);
    if (y + viewport >= height - 2 && height === previousHeight) {
      stableAtBottom++;
    } else {
      stableAtBottom = 0;
    }
    if (stableAtBottom >= 2) break;

    await page.evaluate((distance) => window.scrollBy(0, distance), Math.floor(viewport * stepRatio));
    await page.waitForTimeout(waitMs);
    previousHeight = height;
  }

  // Return to the top so the final full-page render starts from a predictable position.
  await page.evaluate(() => window.scrollTo(0, 0));
  await page.waitForTimeout(waitMs);
  await page.screenshot({ path: output, fullPage: true, animations: 'disabled' });
  console.log(`Saved ${output}`);
} finally {
  await browser.close();
}
node capture.mjs https://example.com article.png

Adjust the viewport, waitMs, stepRatio, and maxSteps for the site. Smaller scroll increments and longer pauses give scroll-triggered code more opportunities to run, at the cost of time. This loop scrolls the main document; for a nested panel, locate that element and scroll it explicitly. For pages requiring sign-in, use a persistent browser context or a saved authenticated state according to Playwright’s guidance, and protect that state as a credential.

Python

python -m pip install playwright
python -m playwright install chromium
# capture.py
import asyncio
import sys
from playwright.async_api import async_playwright

async def main():
    url = sys.argv[1] if len(sys.argv) > 1 else "https://example.com"
    output = sys.argv[2] if len(sys.argv) > 2 else "page.png"
    max_steps = 80
    step_ratio = 0.8
    wait_ms = 700

    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=True)
        page = await browser.new_page(viewport={"width": 1440, "height": 900})
        try:
            await page.goto(url, wait_until="domcontentloaded", timeout=60_000)
            try:
                await page.wait_for_load_state("load", timeout=15_000)
            except Exception:
                pass

            previous_height = 0
            stable_at_bottom = 0
            for _ in range(max_steps):
                height = await page.evaluate("document.documentElement.scrollHeight")
                viewport = await page.evaluate("window.innerHeight")
                y = await page.evaluate("window.scrollY")
                if y + viewport >= height - 2 and height == previous_height:
                    stable_at_bottom += 1
                else:
                    stable_at_bottom = 0
                if stable_at_bottom >= 2:
                    break

                await page.evaluate("distance => window.scrollBy(0, distance)", int(viewport * step_ratio))
                await page.wait_for_timeout(wait_ms)
                previous_height = height

            await page.evaluate("window.scrollTo(0, 0)")
            await page.wait_for_timeout(wait_ms)
            await page.screenshot(path=output, full_page=True, animations="disabled")
            print(f"Saved {output}")
        finally:
            await browser.close()

asyncio.run(main())
python capture.py https://example.com article.png

The scripts intentionally treat scrolling and capture as separate steps. The pre-scroll triggers many viewport-based loading patterns, but it cannot guarantee that every site-specific script will finish or that every nested scroller will be visited. Inspect the output and tune the wait or scroll behavior when needed.

4. Choose the right capture route

Route Good fit Watch for
Browser full-page capture One-off capture in the browser, especially when the current tab already has access to the page. Confirm it triggers scrolling for deferred content; browser behavior and controls vary.
Playwright or another browser automation tool Repeatable captures, custom scroll loops, explicit viewport and wait controls. Requires browser setup; handle login state carefully and account for nested scrollers, changing layouts, and endless feeds.
Screenshot.Rocks extension Capturing the visible current tab and styling/exporting an image in its editor. The extension itself does not make a full-page screenshot; first use a separate full-page capture route.
Screenshot API Automated capture from a URL without maintaining a local browser workflow. Check how it handles scrolling, authentication, page failures, and billing before building it into a job.
PDF output Long documents intended for pages or printing. Pagination can change layout; verify page breaks and content after export.

5. Handle common edge cases

Lazy-loaded images still show as blank

The page may have been captured before the image entered the viewport, before its request finished, or before it decoded. Scroll in smaller steps, pause longer, and inspect whether the image appears in the live page before capturing. If it does not appear in the browser, the capture cannot include it.

The page keeps getting taller

This is typical of infinite feeds. Pick a limit such as a target item, maximum scroll depth, or maximum number of steps. The scripts above stop after a configured maximum even if the page continues adding content. Verify the last included item; do not interpret the result as a complete archive of an unbounded feed.

The page contains a nested scroll panel

Find the element whose own scrollbar moves and scroll that element rather than window. Some pages also need the main document scrolled to reveal the panel before its contents load. A capture tool that only scrolls the window may miss the panel’s lower content.

Sticky headers or floating controls repeat

Section stitching may capture fixed UI in multiple positions. Inspect the completed image. If repetition makes it unusable, try a capture option that handles fixed elements or hide the relevant selector where the tool permits it. Screenshot.Rocks is an image finishing step here, so the capture itself needs to be corrected before import.

Animations, carousels, and content that changes over time

Capture can land on different animation or carousel frames between sections. Prefer a reduced-motion option when available, pause the content where possible, or add a consistent wait before recording. A capture tool’s motion controls are tool-specific; do not assume a static result without checking.

Logged-in pages

The Screenshot.Rocks extension works on the current browser tab, including a page behind a login, but its full-page route is separate. A script or remote API does not automatically inherit the browser’s cookies. Use an authenticated browser context or supported cookie/header configuration, and never put session secrets into a shared script or public URL.

Very tall screenshots are hard to read

One image can become unwieldy when the page is long. Use a narrower capture boundary, split the capture into sections, or choose PDF when a paginated document is more useful than a single image. Check readability at the intended display size.

6. Troubleshoot capture failures

Symptom Likely cause Fix
Lower sections are missing The method did not scroll far enough, the step cap was reached, or the site uses a nested scroller. Raise the step limit for a finite page, scroll the correct element, and confirm the page height stops changing.
Images are placeholders or blank Viewport entry, network loading, or image decoding did not finish before capture. Use smaller scroll steps, increase the pause, and confirm images render in the live page.
Capture hangs on an endless page New items keep extending the document, so there is no stable bottom. Set a deliberate depth or item limit and stop after the needed portion.
Headers appear more than once Fixed or sticky elements were included in multiple stitched sections. Try a fixed-element handling option or hide the selector if supported; check the resulting image.
Script reports a navigation timeout The page did not reach the selected lifecycle event within the timeout. Use a less strict initial event such as domcontentloaded, then wait for the specific content you need. A long network-idle wait can be unsuitable for pages with continuous requests.
Screenshot is clipped or unexpectedly narrow Viewport dimensions or full-page behavior differ from what the page requires. Set the desired viewport explicitly and verify the capture tool’s full-page setting.
Script cannot access a private page The automated browser has no authenticated session or the site rejects automation. Supply a properly authenticated browser context or use the current browser workflow; do not expose credentials in source control.
Screenshot.Rocks shows only the top viewport The extension captured its supported visible-tab region rather than a separate full-page image. Make the full-page capture first, then import that file into the editor.

7. Performance, reliability, and cost

Pre-scrolling adds time because the browser must visit sections and allow content to load. Smaller steps and longer pauses can improve the chance that viewport-triggered content appears, but they increase capture time. Start with moderate values and tune against the specific page. If you control the site, a dedicated readiness selector is more reliable than guessing a long fixed delay.

Reliability depends on the page: network speed, deferred scripts, consent overlays, sticky elements, viewport width, and feed behavior can all affect the result. Treat a successful browser navigation as distinct from a complete capture. Check the bottom, image areas, and repeated UI before sharing or storing the output.

Local browser automation has setup and runtime costs, but no Screenshot.Rocks full-page automation price is established in the available product information. For an API, compare the price and billing rules alongside capture quality and failure handling. ScreenshotNeo says bot checks/CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing; each response includes X-Page-Verdict and X-Billed headers so the outcome is visible.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. One GET request can return an image or PDF. For scroll-loaded content, its API supports full-page capture with lazy images loaded. See the ScreenshotNeo documentation for request options.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://example.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));

Cookie banners, popups, and chat widgets are removed before the shot. Bot checks, blank pages, and failed loads are never billed. An MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Sign up for free and capture 1,000 screenshots a month without a card.

FAQ

Can Screenshot.Rocks take a scrolling screenshot by itself?

Its extension captures the visible part of the current tab. Make a full-page screenshot separately, then import it into the editor.

Why are images missing in my full-page screenshot?

They may load only when scrolled into view. Pre-scroll through the relevant sections and wait for the images to appear before recording.

Can I capture an entire infinite-scroll feed?

There is no fixed end to capture. Decide which portion you need and set a practical stopping boundary.

Can I style the result in Screenshot.Rocks?

Yes. Import the completed screenshot into its editor to choose a style or background and export.

Sources