Viewport and Full-Page Website Screenshots
Learn when to capture the visible viewport, a page element, or the full page, with Firefox, Playwright, and Chrome DevTools examples.

A viewport screenshot captures the part of a webpage currently visible in the browser. A full-page screenshot captures the page’s scrollable content beyond that viewport. Use a viewport capture for what someone sees at a particular moment, a full-page capture to document a long page, and an element capture when you need just one component. For a quick manual capture, use a browser feature; for repeated or automated captures, use Playwright or the Chrome DevTools Protocol.
These methods capture a page as it is rendered at a particular time. They do not guarantee an identical result across browsers or dynamic sites. Content that loads as you scroll, animations, consent dialogs, and changes in page state can affect the result, so inspect the image when accuracy matters.
1. Choose the capture area
Start by deciding what evidence or image you need. The capture area determines which method and settings make sense.

| Need | Capture type | Typical method |
|---|---|---|
| Show exactly what is visible now | Viewport | Browser screenshot or scripted viewport capture |
| Document content above and below the fold | Full page | Browser full-page feature or automation API |
| Save a chart, card, or other component | Element | Browser element capture or locator-based capture |
| Capture many pages repeatedly | Scripted | Playwright, Chrome DevTools Protocol, or a screenshot API |
A full-page image can be very tall and harder to read at normal size. If the purpose is to show a particular state, viewport capture may communicate it better. If readers need a whole-page reference, full-page capture avoids manually stitching separate images.
2. Take a screenshot in Firefox
Firefox documents a screenshot feature for visible portions and full web pages. For a quick, one-off capture, use the browser’s screenshot feature and select the desired area. Firefox Developer Tools also supports entire-page and single-element screenshots.
Enable the Developer Tools full-page control
- Open Firefox Developer Tools for the page.
- Open the toolbox settings.
- Enable the option for the entire-page screenshot button.
- Use the screenshot control when you want the full scrollable page.
The toolbar control is initially disabled, so enable it in toolbox settings before looking for it. Choose a single element when the page component is the subject. For a simple visible-area capture, use the browser’s user-facing screenshot feature. Browser menus can change between versions; consult [Firefox’s current screenshot documentation](https://support.mozilla.org/en-US/kb/take-screenshots-firefox) if the control has moved.
3. Capture viewport, full page, or an element with Playwright
Playwright provides browser automation APIs for screenshots of a page or a selected element. Its page screenshot supports viewport and full-page capture, as well as image type and scale settings. Use this approach when a capture needs to be repeatable or part of a script.
Install Playwright and a browser
npm init -y
npm install playwright
npx playwright install chromium
Runnable Node.js example
Save this as screenshot.cjs. It writes a viewport image, a full-page image, and an image of an element selected by CSS selector.
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch({ headless: true });
const page = await browser.newPage({
viewport: { width: 1440, height: 900 },
deviceScaleFactor: 1
});
try {
await page.goto('https://example.com', {
waitUntil: 'networkidle',
timeout: 30000
});
await page.screenshot({ path: 'viewport.png' });
await page.screenshot({ path: 'full-page.png', fullPage: true });
const heading = page.locator('h1').first();
await heading.screenshot({ path: 'heading.png' });
} finally {
await browser.close();
}
})();
Run it with node screenshot.cjs. Replace the example URL and selector with the page and element you need. The try/finally ensures the browser closes if navigation or capture throws an error.
Python example
Install Playwright for Python and its browser binary:
python -m pip install playwright
python -m playwright install chromium
import asyncio
from playwright.async_api import async_playwright
async def main():
async with async_playwright() as p:
browser = await p.chromium.launch()
page = await browser.new_page(
viewport={"width": 1440, "height": 900},
device_scale_factor=1,
)
try:
await page.goto(
"https://example.com",
wait_until="networkidle",
timeout=30_000,
)
await page.screenshot(path="viewport.png")
await page.screenshot(path="full-page.png", full_page=True)
await page.locator("h1").first.screenshot(path="heading.png")
finally:
await browser.close()
asyncio.run(main())
The examples use Chromium so setup is explicit. Playwright also supports other browser engines; rendering can differ between them. Choose the same engine and viewport each time if you are comparing captures.
Useful Playwright options
| Option | Effect | Use |
|---|---|---|
fullPage: true / full_page=True |
Captures the full scrollable page | Long-page documentation |
type: 'png' or 'jpeg' |
Selects image format | PNG for sharp detail; JPEG for photographic content and smaller output |
quality |
Sets lossy image quality where supported | JPEG output when file size matters |
scale: 'css' or 'device' |
Controls pixel scaling | CSS pixels for compact output; device scale for higher-density output |
clip |
Captures a defined rectangle | A region of the page rather than the viewport or whole page |
animations |
Controls animation handling | Reduce variation when capturing animated content |
Check [Playwright’s screenshot documentation](https://playwright.dev/docs/screenshots) for current option names and behavior. For element capture, target a stable selector and wait until the element is visible. For pages with lazy-loaded images, full-page capture may need additional scrolling or waiting before the final image; inspect the result for missing content.
4. Use Chrome DevTools Protocol for lower-level control
Chrome DevTools Protocol exposes Page.captureScreenshot. It supports PNG, JPEG, and WebP output, JPEG quality, an optional clipped region, and a setting to capture beyond the viewport. This is a lower-level route than Playwright and is most useful when your automation already speaks CDP or needs protocol-level control.
With a CDP session available, the core request is:
const result = await cdpSession.send('Page.captureScreenshot', {
format: 'png',
captureBeyondViewport: true
});
require('node:fs').writeFileSync(
'page.png',
Buffer.from(result.data, 'base64')
);
Here, cdpSession is an established Chrome DevTools Protocol session attached to the target page. The protocol returns base64 image data; decode it before writing the file. For a bounded capture, provide a clip rectangle with page coordinates, dimensions, and scale. Consult the [Chrome DevTools Protocol Page domain reference](https://chromedevtools.github.io/devtools-protocol/tot/Page/#method-captureScreenshot) for the current parameter schema. The protocol’s full-page behavior and coordinate details are version-sensitive, so validate the output against the Chrome version you deploy.
5. Prepare dynamic pages before capture
A screenshot records the page state at capture time. The page may still be loading or may change during a full-page capture. Use these steps for more consistent results:

- Set a fixed viewport. Use the same width and height in each run so responsive layouts break at the same points.
- Wait for the relevant state. Prefer a meaningful selector or application-ready signal if network activity never becomes idle.
- Load lazy content. Some pages load images only after scrolling near them. Scroll through the page or trigger the site’s loading behavior before capture.
- Control variability. Disable or wait for animations when visual comparison matters. Keep locale, authentication, and browser settings consistent.
- Inspect the output. Look for missing sections, repeated sticky headers, clipped content, or an unexpected consent dialog.
Network-idle waiting is not a guarantee that a page is visually complete: analytics, long polling, and other persistent requests can prevent idleness, while application content may appear after requests finish. A selector wait is often more reliable when you know which element signals readiness.
6. Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. One GET request returns a screenshot or PDF. Its API documentation covers the parameters; this minimal cURL request saves a WebP capture:
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://example.com \
-o shot.webp
The equivalent Python request is:
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://example.com"},
timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
And in Node.js:
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}`);
await require('node:fs/promises').writeFile(
'shot.webp',
Buffer.from(await res.arrayBuffer())
);
ScreenshotNeo accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing. Responses indicate the page verdict and billing status in X-Page-Verdict and X-Billed headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.
It supports full-page and element capture, viewport and device presets, retina scale, dark mode, PDF options, custom CSS and JavaScript, selector waits, delay and network-idle waits, request blocking, custom headers and cookies, geolocation and timezone, caching, async jobs, bulk capture, signed links, and a usage API. Free includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. [Create a free ScreenshotNeo account](https://screenshotneo.com/account/sign-up/) and make up to 1,000 screenshots a month without a card.
7. Troubleshooting and reliability
| Symptom | Likely cause | What to try |
|---|---|---|
| Full-page image stops at the viewport | The call used the default viewport mode | Enable fullPage in Playwright or the beyond-viewport option in CDP; verify the browser control is enabled in Firefox. |
| Element screenshot is empty or fails | Selector matched nothing, or the element is hidden | Check the selector, wait for visibility, and confirm the right frame or page is targeted. |
| Images are missing lower on the page | Lazy loading has not been triggered | Scroll through the document, wait for image loading, then capture and inspect again. |
| Navigation times out | The site never reaches the chosen load condition | Increase the timeout if appropriate or wait for a page-specific selector instead of global network idle. |
| Screenshot changes between runs | Dynamic content, animation, viewport differences, or changing data | Fix viewport and browser settings, wait for stable content, and disable animations where suitable. |
| Output is unexpectedly large | Full-page dimensions or high device scale produce many pixels | Use viewport or element capture, CSS scale, or JPEG/WebP where supported and acceptable. |
| CDP image cannot be opened | Base64 data was written as text | Decode the returned data into bytes before saving. |
Performance, reliability, and cost
Local browser automation has setup and runtime costs: install browser binaries, keep the process healthy, and account for the time and memory needed to render a page. Full-page captures can use substantially more memory than viewport captures because the image is taller. Run captures with bounded concurrency and close pages and browsers reliably. Reuse a browser process across a batch when practical, while isolating page contexts if sessions or cookies must differ.
For repeatable visual records, pin browser versions and capture settings. A successful navigation does not prove the screenshot contains the intended content; validate readiness and, where needed, inspect or compare the output. If the site changes while scrolling, a full-page capture may combine content from different moments. Capture during a stable state and review the image.
Local software avoids a per-shot API fee but consumes your infrastructure and maintenance time. For a hosted API, compare the plan allowance and feature set with your volume, and account for retries and failed page loads. ScreenshotNeo says only clean shots are billed and that cache hits and the listed failure states cost nothing; check the response headers to distinguish outcomes. Its published tiers are Free (1,000/month), Starter ($5 for 3,000), Growth ($15 for 15,000), Pro ($39 for 60,000), Scale ($99 for 250,000), and Business ($249 for 1,000,000); yearly billing gives two months free, and every feature is on every plan.
8. Frequently asked questions
Does a full-page screenshot include content that appears only after scrolling?
It is intended to capture the full scrollable page, but lazy-loaded content may need to be triggered first. Check the image for missing sections.
Is a viewport screenshot the same as a browser window screenshot?
Viewport refers to the page area visible in the browser, excluding browser chrome such as tabs and toolbars.
Can I capture just one HTML element?
Yes. Firefox Developer Tools documents single-element capture, and Playwright can take a screenshot of a locator.
Which format should I choose?
PNG is suitable for crisp interface detail; JPEG or WebP can reduce file size depending on the content and supported workflow. Verify format support in the API or tool you use.
Should I use a full-page image for a visual regression test?
Use it when the whole document is relevant, but control viewport, browser version, page state, and dynamic content. A smaller component capture can produce a more focused comparison.
Choose the method that matches the job
Use a browser screenshot feature for a quick manual capture, a viewport image for the current visible state, a full-page capture for a long document, and an element capture for a specific component. Use Playwright or CDP when the process must run repeatedly. Whatever the method, make page readiness explicit and inspect captures of dynamic pages before relying on them.


