Fix Selenium Python Screenshots That Capture Only the Viewport
Selenium’s standard screenshot captures the current window. Use Firefox’s full-page API or Chrome’s DevTools Protocol to capture the whole document.
Selenium’s standard Python screenshot methods capture the current browser window, which usually means the visible viewport rather than the entire scrollable document. For a full-page image, use Firefox’s dedicated full-document screenshot method or, in Chrome, call the Chrome DevTools Protocol (CDP) Page.captureScreenshot command with captureBeyondViewport enabled. The Firefox API is Selenium-specific; the Chrome method is browser- and protocol-specific.
First decide whether you need the visible viewport, one element, or the full document. Use save_screenshot() for the visible window, a WebElement screenshot for a component, and one of the full-page approaches below for the entire document. Selenium documents these screenshot scopes separately. Selenium screenshot documentation
1. Capture a full-page screenshot in Firefox
Selenium’s Firefox WebDriver provides get_full_page_screenshot_as_file(filename) and save_full_page_screenshot(filename) for full-document screenshots. This is the most direct path when Firefox is an acceptable browser for the job.
from selenium import webdriver
url = "https://example.com"
output_path = "page.png"
with webdriver.Firefox() as driver:
driver.get(url)
saved = driver.get_full_page_screenshot_as_file(output_path)
if not saved:
raise OSError(f"Could not write screenshot to {output_path}")
print(f"Saved {output_path}")
The method returns a boolean. Check it if the output file is part of an automated pipeline; a false result indicates an I/O error. Use an absolute output path when the process working directory is unclear. The Firefox API also exposes full-page PNG and base64 screenshot methods when you need the image in memory instead of writing directly to a file. Firefox WebDriver Python API
2. Capture beyond the viewport in Chrome
For Chrome, Selenium’s Python remote WebDriver exposes execute_cdp_cmd(cmd, cmd_args). Use it to invoke CDP’s Page.captureScreenshot with captureBeyondViewport: true. The response contains base64-encoded image data, which the example decodes and writes as a PNG.
import base64
from selenium import webdriver
url = "https://example.com"
output_path = "page.png"
with webdriver.Chrome() as driver:
driver.get(url)
result = driver.execute_cdp_cmd(
"Page.captureScreenshot",
{
"format": "png",
"captureBeyondViewport": True,
},
)
image_bytes = base64.b64decode(result["data"])
with open(output_path, "wb") as image_file:
image_file.write(image_bytes)
print(f"Saved {output_path}")
captureBeyondViewport defaults to false in the protocol, so setting it explicitly is essential to request content beyond the viewport. CDP also accepts jpeg and webp formats; quality is available for JPEG. The command’s output is still one image: very long pages can create large files and may encounter browser or memory limits.
This is not a cross-browser WebDriver full-page API. The CDP tip-of-tree protocol changes and does not guarantee backwards compatibility. Confirm that the actual Chrome, driver, Selenium version, and execution environment support the command. CDP Page.captureScreenshot · Selenium Remote WebDriver Python API · CDP protocol overview
3. Make sure the page is ready before capturing
Full-page capture controls the requested image region; it does not guarantee that every part of a dynamic page has loaded. A browser can finish navigation while an application is still fetching data, rendering components, or loading images lazily. Wait for a page-specific condition before taking the screenshot.
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
with webdriver.Firefox() as driver:
driver.get("https://example.com")
WebDriverWait(driver, 20).until(
EC.visibility_of_element_located((By.CSS_SELECTOR, "main"))
)
driver.get_full_page_screenshot_as_file("page.png")
Replace main with a selector that represents the content you actually need. If the site loads more content only after scrolling, trigger that site behavior and wait for the content before capture. A full-document screenshot request alone should not be assumed to trigger lazy loading.
4. Choose the capture method for the job
| Requirement | Use | Trade-off |
|---|---|---|
| Visible browser area | driver.save_screenshot("view.png") |
Captures the current window, not necessarily the scrollable document. |
| Full document in Firefox | driver.get_full_page_screenshot_as_file(...) |
Direct Firefox WebDriver API; use Firefox. |
| Full document in Chrome | CDP Page.captureScreenshot with captureBeyondViewport: true |
Chrome-specific protocol behavior; verify against deployed versions and remote setup. |
| One component | element.screenshot(...) |
Captures an element rather than the whole document. |
5. Troubleshooting incomplete or failed screenshots
| Symptom | Likely cause | What to do |
|---|---|---|
| Image ends at the bottom of the viewport | A generic screenshot method was used, or CDP’s beyond-viewport option was omitted. | Use Firefox’s full-page method or set captureBeyondViewport to true in the Chrome CDP command. |
execute_cdp_cmd is unavailable or command fails |
The active driver/browser does not expose that CDP command, or the session is not the expected Chrome session. | Confirm the actual browser and driver. Check protocol support in the deployed versions; use Firefox’s full-page API if compatible with the workflow. |
| Screenshot is blank or content is missing | Capture happened before the application rendered the required content, or a site loads content only after scrolling. | Wait for a meaningful selector or application condition. Trigger the page’s normal loading behavior and verify the content is present before capture. |
| Output file is missing or empty | Invalid or unexpected output path, file permissions, or a failed file write. | Use a known writable absolute path. In Firefox, check the full-page method’s returned boolean; in Chrome, verify decoded bytes were written successfully. |
| Works locally but fails in a remote grid | The remote browser, driver, or Selenium endpoint may differ from the local combination, especially for CDP commands. | Identify the remote browser and version and verify the command against that environment. Prefer a browser’s documented API when possible. |
| Image is huge or capture is slow | The document is unusually long or uses high-resolution assets. | Capture only the needed element or region when a full document is unnecessary. Consider output format and quality where supported, and avoid retaining oversized artifacts unnecessarily. |
6. Reliability, performance, and cost considerations
Firefox’s dedicated method avoids writing a Chrome-specific protocol call, while Chrome CDP gives Chrome users an explicit beyond-viewport option. Neither choice removes the need to wait for the right page state or inspect the resulting image. CDP can change over time, so pin and verify the browser and driver combination used in CI. Remote execution adds another compatibility boundary: the screenshot is produced by the remote browser, and local assumptions about browser version or protocol support may not hold.
Full-document captures can take longer and consume more memory than viewport or element captures, particularly for tall pages and high device pixel ratios. For repeatable work, use the smallest capture scope that answers the task, wait for specific content rather than relying on arbitrary long sleeps, and keep the output format appropriate to the use case. Selenium itself has no per-screenshot charge; operational cost comes from the browser infrastructure and storage or processing your workflow uses.
7. Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. One GET request returns an image or PDF, so you do not need to install or manage a browser driver for a straightforward capture. Its API documentation describes the 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
Python:
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)
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}`);
const image = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', image));
ScreenshotNeo removes cookie and consent banners, newsletter popups, and chat widgets before the shot. Bot checks, blank pages, and failed loads are never billed. An MCP server lets AI agents use screenshot tools, and 1,000 screenshots per month are free with no card; paid plans start at $5 for 3,000. Sign up for the free plan.
FAQ
Does Selenium’s save_screenshot() capture the whole page?
It is documented as a screenshot of the current window. Use a browser-specific full-document method when you need content outside the viewport.
Can I use the Chrome CDP example with Firefox?
No. execute_cdp_cmd and Page.captureScreenshot are part of the Chrome DevTools Protocol. Use Firefox’s full-page WebDriver API for Firefox.
Will full-page capture load lazy images automatically?
Do not assume so. Make the page load the content you need, then capture and inspect the result.
Should I increase the browser window height instead?
Changing the viewport is not the same as requesting a full-document screenshot. Use the documented full-page route for your browser when the whole document is required.


