Selenium can take three kinds of screenshots: what is visible in the window, a single element, and — depending on the browser — the whole page. The first two are one line each; the third is where most people get stuck, because Chrome's Selenium driver has no full-page method at all. This page shows working Python code for each, with what came out when we ran it.
How we measured. On 2026-11-08, Selenium 4.52.0 for Python with Chromium and ChromeDriver 156.0.8078.79 (Debian packages, headless) and Firefox ESR 153.6 with geckodriver 0.37.1, against a local test page 3,516 px tall in Chrome. For Firefox, Selenium Manager — which ships with Selenium — downloaded geckodriver by itself; for Chromium we used the distribution's ChromeDriver.
The viewport screenshot
from selenium import webdriver
options = webdriver.ChromeOptions()
options.add_argument("--headless=new")
options.add_argument("--window-size=1280,800")
driver = webdriver.Chrome(options=options)
driver.get("https://example.com/")
driver.save_screenshot("page.png")
driver.quit()
Selenium's documentation describes it as a screenshot of the "current browsing context" — the visible window. Our result was 1280×657, not 1280×800: --window-size sets the outer window, and Chrome's own interface takes part of it even in headless mode. window.innerWidth and innerHeight reported 1280×657 too. If you need an exact viewport, check driver.execute_script("return [innerWidth, innerHeight]") and adjust, or use the full-page method below with a clip.
Two settings that help, both tested:
- An exact viewport: add the interface height to the window. In our setup
--window-size=1280,943gave a viewport, and a screenshot, of exactly 1280×800. - A sharp (retina) image:
--force-device-scale-factor=2doubled the pixels — 2560×1314 for the 1280×657 viewport — withdevicePixelRatio2 inside the page.
Screenshots in WebDriver are always PNG; convert with Pillow if you need JPEG or WebP. In Java, the same command is ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE), as in Selenium's documentation.
An element
from selenium.webdriver.common.by import By
element = driver.find_element(By.CSS_SELECTOR, "ul.products")
element.screenshot("products.png")
The image is exactly the element's box: in our test 1249×270, the same as element.rect. Java: element.getScreenshotAs(OutputType.FILE).
The full page in Chrome: use the DevTools command
Selenium's Chrome driver can send Chrome DevTools Protocol commands, and the protocol can capture beyond the viewport — the same call Chrome DevTools makes for Capture full size screenshot (how that works):
import base64
height = driver.execute_script("return document.documentElement.scrollHeight")
width = driver.execute_script("return document.documentElement.scrollWidth")
data = driver.execute_cdp_cmd("Page.captureScreenshot", {
"format": "png",
"captureBeyondViewport": True,
"clip": {"x": 0, "y": 0, "width": width, "height": height, "scale": 1},
})
with open("full.png", "wb") as f:
f.write(base64.b64decode(data["data"]))
Ours came out 1280×3516, the whole page. execute_cdp_cmd exists on the Chrome and Edge drivers only.
The window-resize trick, and why it cuts the bottom off
The old workaround is to make the window as tall as the page and take a normal screenshot:
driver.set_window_size(1280, height)
driver.save_screenshot("full.png")
We got 1280×3373 for a 3,516 px page: 143 px short — the same 143 px of browser interface that shrank the viewport above. It can also change the page itself, since 100vh elements grow with the window. Prefer the CDP command.
The full page in Firefox: built in
options = webdriver.FirefoxOptions()
options.add_argument("-headless")
driver = webdriver.Firefox(options=options)
driver.get("https://example.com/")
driver.get_full_page_screenshot_as_file("full.png")
The Firefox driver has its own full-page methods, and ours captured the whole page: 1268×3519 (Firefox laid the page out 3 px taller, and the width excluded the scroll bar). On the Chrome driver, get_full_page_screenshot_as_png does not exist — we got AttributeError: 'WebDriver' object has no attribute 'get_full_page_screenshot_as_png'.
Wait before you capture
driver.get() returns when the page's load event fires; content added later by scripts is not there yet. On our test page an element inserted half a second after load was missing right after get() and appeared after an explicit wait of 535 ms:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.ID, "late")))
driver.save_screenshot("page.png")
Selenium's waiting strategies page explains explicit and implicit waits; for screenshots, an explicit wait for the element that shows the content is loaded is the reliable choice. A fixed time.sleep() is either too short or wastes time on every page.
The same in Java
We ran the Python versions; these are the same calls in Selenium's Java bindings:
// viewport and element
File page = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
File el = driver.findElement(By.cssSelector("ul")).getScreenshotAs(OutputType.FILE);
// full page in Chrome, through the DevTools protocol
Map<String, Object> result = ((ChromeDriver) driver).executeCdpCommand("Page.captureScreenshot",
Map.of("format", "png", "captureBeyondViewport", true));
byte[] png = Base64.getDecoder().decode((String) result.get("data"));
// full page in Firefox
File full = ((FirefoxDriver) driver).getFullPageScreenshotAs(OutputType.FILE);
What full-page captures still miss
Both methods paint the page without scrolling it, so anything that appears only on scroll is missing: lazy-loaded images stay blank, and pages that scroll inside an element come out one screen tall. Scroll through the page with execute_script("window.scrollTo(0, document.body.scrollHeight)") in steps before capturing, or set lazy images to eager — our full-page guides measured both problems.
Selenium also prints pages: driver.print_page(PrintOptions()) returns a PDF as base64 (W3C WebDriver's print command) — ours was a valid 22.6 KB PDF.
A screenshot without a browser to run
Selenium is the right tool when screenshots are part of a test suite. If all you need is the image of a public page — for a report, a link preview, monitoring — our screenshot API returns a viewport or full-page capture in one HTTP request from Python, with lazy images loaded and cookie banners removed:
import requests
r = requests.post("https://shareglint.com/v1/screenshots?wait=true",
headers={"Authorization": "Bearer sk_live_..."},
json={"url": "https://example.com/", "full_page": True, "lazy_load": True}, timeout=60)
print(r.json()["url"])
A full-page screenshot uses 2 renders of the monthly quota; see the Python screenshot API guide for the options.