Playwright has no built-in maximum-scroll option for screenshots. Put a hard limit in your own scrolling loop—by steps, time, or target item count—then capture the page after the desired content has loaded. fullPage: true captures the current full scrollable page, but it does not itself scroll through an infinite feed or guarantee that scroll-triggered content has loaded.
Why fullPage: true is not enough
Playwright defines a full-page screenshot as “a screenshot of a full scrollable page, as if you had a very tall screen and the page could fit it entirely.” That describes the capture area, not a process for traversing an infinite feed. There is no documented maximumScroll screenshot option; a maximum has to come from your script. See the Playwright screenshot documentation.
As an Amazon Associate I earn from qualifying purchases.
Some pages append items only after the viewport reaches a trigger point. Others reveal images lazily or use a virtualized list that keeps only nearby rows in the DOM. A 2026 Playwright issue describes cases where full-page capture does not move the visual viewport and may miss content gated by scrolling; the issue was closed as a duplicate, so treat it as evidence of a limitation, not a guarantee about every Playwright version or browser. Issue discussion
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Clear out junk files and repair common Windows errors3Scan for outdated or missing drivers - takes under a minuteUse a bounded scroll loop, then capture
The example below scrolls a nested feed by about one viewport at a time, stops at 20 steps or after three checks without a change in item count, and takes a full-page screenshot of the resulting DOM. Replace the selectors with ones from your page. The example is illustrative rather than tested against a particular site.
#1 Best Overall
const maxSteps = 20;
const list = page.locator('[data-testid="feed"]');
const items = page.locator('[data-testid="feed-item"]');
let previousCount = 0;
let unchangedChecks = 0;
for (let step = 0; step < maxSteps; step++) {
const count = await items.count();
if (count === previousCount) unchangedChecks++;
else unchangedChecks = 0;
if (unchangedChecks >= 3) break;
previousCount = count;
await list.evaluate(el => {
el.scrollTop += el.clientHeight;
});
// Replace with a site-specific wait when possible.
await page.waitForTimeout(250);
}
await page.screenshot({ path: 'feed.png', fullPage: true });
The hard step cap protects against an endless feed even if the item count keeps growing. The unchanged-count check can stop earlier when the feed appears to have settled, but it is only a heuristic: a slow request could still add items later. A fixed delay is likewise not proof that loading has finished.
Choose the scrolling surface
If the document itself scrolls, use window or mouse-wheel input. If a feed sits inside an overflow container, scroll that container instead; calling window.scrollTo() will not advance it. Playwright documents locator scrolling, mouse.wheel(), and changing a container’s scrollTop. Its guidance recommends scrolling the element you need into view when that is the reliable way to reach the relevant content. See Playwright’s scrolling guide.
Rank #2
For a document-scrolling page, the loop’s advance operation can instead be:
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteawait page.evaluate(() => window.scrollBy(0, window.innerHeight));
For a specific target already in the DOM, a locator can be scrolled into view:
Rank #3
await page.locator('[data-testid="last-loaded-item"]').scrollIntoViewIfNeeded();
Wait for the application, not just the clock
When possible, wait for the page’s actual loading contract: a known response, a new item, or a loading indicator to disappear. For example, if the site reliably exposes a loading marker, wait for it to become hidden after scrolling:
await page.locator('[data-testid="loading"]').waitFor({ state: 'hidden' });
Adapt that condition to the application; some pages do not expose a dependable marker. A fixed timeout can be a fallback, but it can be too short on a slow run or unnecessarily long on a fast one. Playwright’s APIs cannot supply a universal completion signal for arbitrary sites.
Pick a stopping rule and screenshot shape
| Approach | Useful when | Trade-off |
|---|---|---|
| Maximum steps | You need a predictable upper bound on how far the automation will traverse. | The same step count can load different amounts on pages with different viewport sizes or item heights. |
| Deadline | You need to cap total time spent scrolling and waiting. | A time budget does not guarantee a particular number of items will load. |
| Item target | You need at least a known number of results. | The target may never be reached if the page ends early or loading fails; retain a separate hard cap. |
| No-growth checks | You want to stop when the item count or content height appears stable. | Temporary pauses can look like completion, so keep a step or time cap too. |
For a finite expanded DOM, page.screenshot({ fullPage: true }) requests one tall image. A virtualized list may not retain all traversed rows in the DOM at once, so a single full-page image may omit rows that were never simultaneously rendered. If the goal is a visual record of the whole traversal, capture bounded viewport slices as you move, or take an element screenshot when only a particular rendered region matters. Playwright documents both full-page and element screenshots in its screenshot guide.
Troubleshoot missed or incomplete content
- The loop does not move the page: Check whether the feed is a nested scroll container. Inspect its scrollable element and advance its
scrollTop, not the window. - The screenshot is short: Check that the loop reached the intended range and that the page actually appended items. A full-page screenshot cannot include content that has not been loaded into the DOM.
- Items appear inconsistently: Replace the fixed sleep with an application-specific response, item-count change, or loading-state condition. Ensure your wait has a timeout so a missing signal cannot hang the run indefinitely.
- Rows disappear as you scroll: The page may virtualize its list. Capture viewport slices during traversal instead of expecting one tall capture to preserve rows no longer rendered.
- The loop runs to its cap every time: Confirm the item selector matches actual feed rows and the no-growth check is observing the right count. Keep the hard cap regardless; an active feed may never become stable.
- Some images or reveal effects are absent: They may depend on entering the viewport. Scroll the relevant region before capture and wait for the page-specific image or reveal state.
Or skip the browser setup
For a one-request screenshot of a URL, ScreenshotNeo offers a screenshot API. This does not replace a custom Playwright loop for deliberately traversing an infinite feed; use it when a direct page capture fits the job.
Best Value
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo API documentation for request options. ScreenshotNeo removes cookie banners, newsletter popups, and chat widgets before capture; bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots per month with no card, and paid plans start at $5 for 3,000. Learn about ScreenshotNeo or sign up free for 1,000 screenshots a month with no card.
Frequently Asked Questions
Does Playwright have a built-in maximum scroll setting for screenshots?
No documented screenshot option sets a maximum scroll. Put a stopping condition in your own scrolling script.
Will a full-page screenshot include rows from a virtualized feed?
Not necessarily. A virtualized list may remove rows from the DOM as they leave view, so capture slices during traversal if you need a record of every row.
Free tools Windows power users keep installed
One-click scans. No signup required.
Quick Recap
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.




