How to Capture a Full-Page Website Screenshot Beyond the Viewport
Capture an entire webpage beyond the visible viewport with Firefox, Chrome DevTools, Playwright, or ScreenshotNeo.
A full-page screenshot captures the complete scrollable document, including content below the visible viewport. Use Firefox’s Save full page, Chrome DevTools’ Capture a full size screenshot, or Playwright’s fullPage: true. A normal viewport screenshot captures only what is currently visible.
Choose the right method
| Situation | Best option | Why |
|---|---|---|
| One-off capture in Firefox | Firefox screenshot UI | No code required |
| One-off capture in Chrome | Chrome DevTools Device Mode | Captures the full document from the browser |
| Repeatable screenshots or visual tests | Playwright | Scriptable and suitable for CI |
| Server-side capture, many URLs, or clean output | ScreenshotNeo | One API request, full-page capture, and browser setup handled for you |
Firefox: save a full page without code
- Open the page in Firefox.
- Right-click an empty area, or press Ctrl+Shift+S on Windows/Linux (Command+Shift+S on macOS).
- Select Take Screenshot.
- Choose Save full page in the upper-right corner.
- Download the image or copy it to the clipboard.
Firefox also offers visible-area, selected-region, and automatically highlighted page-part captures. See Mozilla’s screenshot instructions for the current interface.
Firefox DevTools controls
For more control, open DevTools settings, find Available Toolbox Buttons, and enable Take a screenshot of the entire page. The resulting toolbar button saves the full page to your Downloads folder.
Firefox Web Console helper
Open the Web Console and run:
:screenshot --fullpage
The helper can also accept a filename, delay, device-pixel ratio, selector, clipboard option, and force-file option. Choose a new filename for repeated captures because an existing file can be overwritten. Mozilla documents these options in the Web Console command reference.
Chrome: capture the full document with DevTools
- Open the webpage in Chrome.
- Open DevTools with F12, Ctrl+Shift+I, or Command+Option+I.
- Turn on Device Mode with the phone/tablet icon.
- Open the Device Mode More options menu.
- Choose Capture a full size screenshot.
This captures content outside the current viewport. Chrome’s current Device Mode documentation is the best reference if menu labels move. Chrome announced the full-page DevTools feature in Chrome 59; that historical release note confirms the feature’s origin, while the current documentation describes the workflow.
Playwright: automate a full-page screenshot
Playwright defines a full-page screenshot as a capture of the full scrollable page, as if it were displayed on a very tall screen. The fullPage option defaults to false, so set it explicitly.
Install Playwright
npm init -y
npm install -D playwright
npx playwright install chromium
Complete Node.js example
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch();
const page = await browser.newPage({
viewport: { width: 1440, height: 900 },
deviceScaleFactor: 1
});
await page.goto('https://example.com', {
waitUntil: 'networkidle',
timeout: 90000
});
await page.screenshot({
path: 'full-page.png',
fullPage: true,
scale: 'css'
});
await browser.close();
})();
Save this as capture.js and run node capture.js. A relative output path is resolved from the current working directory. Use scale: 'css' for smaller output based on CSS pixels, or scale: 'device' for larger device-pixel output. See the official Playwright screenshot documentation.
Wait for lazy content before capture
Full-page mode does not guarantee that every application has finished rendering. Wait for a page-specific selector, scroll through lazy sections, or add a short delay when necessary:
await page.goto('https://example.com/article', { waitUntil: 'domcontentloaded' });
await page.locator('article').waitFor();
await page.evaluate(async () => {
for (let y = 0; y < document.body.scrollHeight; y += 800) {
window.scrollTo(0, y);
await new Promise(resolve => setTimeout(resolve, 100));
}
window.scrollTo(0, 0);
});
await page.waitForTimeout(500);
await page.screenshot({ path: 'article.png', fullPage: true });
Capture one element instead of the whole page
await page.locator('main article').screenshot({
path: 'article-only.png'
});
Use an element screenshot when navigation, comments, or unrelated page content should not appear. Firefox’s console helper also supports a selector.
Important options and edge cases
- Viewport versus full page:
fullPage: falsecaptures only the viewport;truecaptures the scrollable document. - Sticky headers: fixed elements may appear repeatedly or cover content. Inspect the output and hide or restyle them before capture if your workflow requires a clean document.
- Lazy-loaded images: scroll-triggered images may not exist until their section enters the viewport. Scroll first and wait for image completion.
- Infinite scroll: there may be no final page height. Define a maximum scroll count or capture a bounded element.
- Animations: pause animations or wait for a stable state to avoid inconsistent frames.
- Cookie banners and overlays: dismiss them before capture or hide their selectors. A full-page command does not inherently remove overlays.
- Very tall pages: large output files consume memory and take longer to encode. Consider an element capture, reduced scale, or a PDF when an image is not required.
- Cross-origin frames: content inside an iframe may be controlled by a different document. Wait for the frame explicitly and verify the result.
- Responsive layouts: set a deterministic viewport so screenshots do not change with the machine running the script.
Or skip the browser setup
ScreenshotNeo captures a full page with lazy images loaded through one GET request. The API accepts PNG, JPEG, WebP, or PDF output and supports a viewport, device preset, retina scale, wait conditions, custom CSS and JavaScript, hidden selectors, dark mode, headers, cookies, user agent, timezone, geolocation, request blocking, caching, and more. Full documentation is at screenshotneo.com/docs.
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)
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}`);
Before the shot, ScreenshotNeo accepts cookie and consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. An MCP server lets Claude, Cursor, and other MCP clients call take_screenshot, get_page_info, and capture_pdf. The Free plan includes 1,000 screenshots per month without a card; paid plans start at $5 for 3,000.
Create a free ScreenshotNeo account and start with 1,000 screenshots per month at no charge.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Only the visible area was saved | Viewport capture was selected | Choose Firefox Save full page, Chrome Capture a full size screenshot, or Playwright fullPage: true. |
| Lower images are blank | Lazy loading had not run | Scroll through the page, wait for images, then capture. |
| Capture times out | Slow network, blocked resource, or page script | Increase the timeout, wait for a specific selector, and inspect failed requests. |
| Cookie dialog covers content | Consent UI remained open | Dismiss it, hide its selector, or use ScreenshotNeo’s consent cleanup. |
| Screenshot changes between runs | Responsive viewport, animation, ads, or live data | Fix the viewport, freeze animations, block unstable resources, and capture at a defined time. |
| Huge image or memory error | Extremely tall page or device scale | Use CSS scale, capture an element, split the page, or output PDF. |
| Playwright browser is missing | Browser binaries were not installed | Run npx playwright install chromium (or install the browser used by your project). |
Performance, reliability, and cost
- Performance: Full-page captures require layout and image work for the entire document. Keep the viewport and scale as small as your use case allows, and avoid unnecessary waits.
- Reliability: Wait for an application-specific ready signal instead of assuming network idle means every component is rendered. Save failures with their URL and timing so they can be retried.
- Repeatability: Fix viewport, locale, timezone, color scheme, authentication state, and output format. Disable or mask animations and live widgets when visual diffs matter.
- Cost: Local Playwright uses your own compute and browser maintenance. ScreenshotNeo bills only clean shots; bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing. Its plans include Free 1,000/month, Starter $5/3,000, Growth $15/15,000, Pro $39/60,000, Scale $99/250,000, and Business $249/1,000,000; yearly billing gives two months free.
FAQ
What is the difference between a full-page and viewport screenshot?
A viewport screenshot contains only pixels currently visible in the browser window. A full-page screenshot includes the page’s scrollable content below and above that viewport.
Can I capture a full page without installing code?
Yes. Firefox and Chrome DevTools both provide built-in full-page commands.
Why does full-page capture miss content?
Content may be lazy-loaded, hidden behind a consent dialog, rendered after a delayed request, or generated by infinite scroll. Make the page reach a known ready state before saving.
Should I use PNG, JPEG, WebP, or PDF?
PNG is useful for sharp text and lossless diffs, JPEG for smaller photographic images, WebP for compact web delivery, and PDF when the result must be paginated or printed.
Can I capture only an article or component?
Yes. Use Firefox’s selector support, Playwright’s locator screenshot, or an API option that targets a CSS selector.


