How to Scroll Down in Playwright
Scrolling is essential for interacting with content that’s off-screen — such as lazy-loaded elements, infinite scroll feeds, or sticky buttons. In this guide, you’ll learn how to scroll down using Playwright, with different strategies, real-world examples, and best practices.
✅ Quick Answer
To scroll down the page:
await page.mouse.wheel(0, 1000); // Scroll down by 1000 pixels
Or scroll to a specific element:
await page.locator('#footer').scrollIntoViewIfNeeded();
🧭 Common Use Cases
- Trigger lazy loading
- Load more content (e.g., infinite scroll)
- Reveal off-screen buttons/inputs
- Capture full-page screenshots
🧪 Method 1: Scroll Using Mouse Wheel
await page.mouse.wheel(0, 1000); // (dx = 0, dy = 1000)
- ✅ Works like a real user scroll
- 🔁 You can repeat for longer pages
Looped Scroll Example:
for (let i = 0; i < 5; i++) {
await page.mouse.wheel(0, 1000);
await page.waitForTimeout(500); // Allow time for loading
}
🧪 Method 2: Scroll Into View of Element
await page.locator('#target-element').scrollIntoViewIfNeeded();
- ✅ Scrolls only if off-screen
- 💡 Ideal for interacting with hidden buttons
🧪 Method 3: Evaluate JavaScript Scroll
await page.evaluate(() => window.scrollBy(0, 1000));
- ✅ Fine-grained control
- 🔁 You can implement infinite scroll logic
Scroll to Bottom Example:
await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));
🧪 Method 4: Scroll an Inner Container
await page.locator('.scrollable-div').evaluate(el => {
el.scrollTop = el.scrollHeight;
});
- ✅ Scrolls specific container
- 💡 Use for modals, sidebars, or chat boxes
🧪 Method 5: Scroll and Wait for Content
If you're triggering lazy-load or infinite scroll:
const scrollStep = 1000;
const maxScrolls = 10;
for (let i = 0; i < maxScrolls; i++) {
await page.mouse.wheel(0, scrollStep);
await page.waitForTimeout(500); // Adjust if needed
}
🧰 Comparison Table
Method | Best Use Case | Works Like User | Custom Scroll Target | Notes |
---|---|---|---|---|
page.mouse.wheel() | Generic scroll | ✅ Yes | ❌ No | Simulates physical scroll |
locator.scrollIntoViewIfNeeded() | Scroll to element | ✅ Yes | ✅ Yes | Only if off-screen |
page.evaluate(window.scrollTo) | Scroll page programmatically | ❌ No | ✅ Yes | Full control via JS |
locator.evaluate(el => el.scrollTop) | Scroll containers/divs | ❌ No | ✅ Yes | Great for nested elements |
🧠 Pro Tips
- Use
scrollIntoViewIfNeeded()
before clicking off-screen buttons - Always
waitForTimeout()
orwaitForResponse()
if scroll triggers network loads - Prefer
mouse.wheel()
for realistic user-like behavior - For infinite scroll, monitor content or DOM size changes
🧩 Example: Scroll Until Element Appears
const target = page.locator('#load-more');
while (!(await target.isVisible())) {
await page.mouse.wheel(0, 1000);
await page.waitForTimeout(500);
}
await target.click();
🏁 Conclusion
Playwright gives you multiple ways to scroll, depending on your app’s structure:
- Use
mouse.wheel()
for user-like scrolling - Use
scrollIntoViewIfNeeded()
for specific targets - Use
evaluate()
for full control, including infinite scroll
Pick the one that fits your use case, and always handle lazy-loading and network delays properly.