ScreenshotNeo

BlogHow-to

How to Take a Full-Page Screenshot in Chrome with Selenium

Use Chrome DevTools Protocol through Selenium to capture beyond the viewport, decode the PNG, and handle pages that load content while scrolling.

By the ScreenshotNeo team4 October 20268 min read

To take a full-page screenshot in Chrome with Selenium, use Chrome DevTools Protocol (CDP) and set captureBeyondViewport to true. Selenium’s regular screenshot methods capture the current browsing context; they do not guarantee a full-document image. CDP returns Base64-encoded image data, which you decode and save to a file.

The example below uses Selenium’s Python Chrome driver command facility, execute_cdp_cmd. It captures a PNG after navigating to a page. For pages that load content as you scroll, scroll through the page first and give that content time to load.

1. Install Selenium and prepare Chrome

Use Python 3 and an installed Chrome browser. Install Selenium in your project environment:

python -m pip install selenium

Recent Selenium versions can manage the browser driver for you when one is available through Selenium Manager. If your environment manages ChromeDriver separately, make sure it is compatible with the Chrome version you run.

2. Capture the full page with Chrome DevTools Protocol

Save this as full_page_screenshot.py. Pass the page URL as the first argument, or use the default URL. The script waits for the document’s load event, then asks CDP to capture beyond the viewport and writes the decoded bytes to a PNG.

import base64
import sys
from pathlib import Path

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait

url = sys.argv[1] if len(sys.argv) > 1 else "https://example.com"
output_path = Path("full-page.png")

options = webdriver.ChromeOptions()
# For a server or container without a visible desktop, uncomment:
# options.add_argument("--headless=new")

with webdriver.Chrome(options=options) as driver:
    driver.set_page_load_timeout(60)
    driver.get(url)

    # Wait for the document load event. This does not guarantee that every
    # application-rendered or lazy-loaded element is ready.
    WebDriverWait(driver, 30).until(
        lambda browser: browser.execute_script(
            "return document.readyState"
        ) == "complete"
    )

    result = driver.execute_cdp_cmd(
        "Page.captureScreenshot",
        {
            "format": "png",
            "captureBeyondViewport": True,
        },
    )

    image_bytes = base64.b64decode(result["data"])
    output_path.write_bytes(image_bytes)

print(f"Saved {output_path.resolve()}")

Run it with:

python full_page_screenshot.py https://example.com

Open the resulting image and check that it contains the intended page. If the target site renders content only after scrolling, use the scrolling guidance below before calling Page.captureScreenshot.

3. Understand the CDP screenshot options

Chrome’s Page.captureScreenshot command supports these relevant parameters. Check the protocol and Selenium binding versions used by your project because the available command surface can vary with the browser and driver setup. See the Chrome DevTools Protocol Page documentation.

Parameter What it controls When to use it
format Image format: png, jpeg, or webp. PNG is the documented default. Choose PNG for lossless output; choose a compressed format when file size matters.
captureBeyondViewport Whether the capture can include content outside the current viewport. Set to true for the full-page capture described here.
quality Quality setting for lossy formats such as JPEG or WebP. Set when using a lossy format; it does not apply to PNG.
clip A page region to capture, expressed as a viewport rectangle with scale. Use when you need a specific region rather than the whole page. Confirm coordinates and dimensions on the target page.
fromSurface Whether to capture from the page surface. Usually leave unspecified unless your Chrome-specific workflow requires a different capture source.
omitBackground Whether to omit the default background in supported capture cases. Use only when a transparent result is needed and verify the output format and page behavior.

The protocol response contains image data as Base64. Decode the data field before writing it as an image file; writing the Base64 text directly would not produce a valid PNG.

4. Load content that appears during scrolling

A page can report document.readyState === "complete" while an application is still fetching data or while images and sections are waiting for a scroll. For a page that uses lazy loading, scroll through it before capturing. This example scrolls in viewport-sized steps and waits briefly after each step:

import time

height = driver.execute_script(
    "return Math.max(document.body.scrollHeight, "
    "document.documentElement.scrollHeight)"
)
step = driver.execute_script("return window.innerHeight")

for position in range(0, height, max(step, 1)):
    driver.execute_script("window.scrollTo(0, arguments[0])", position)
    time.sleep(0.25)

driver.execute_script("window.scrollTo(0, 0)")
time.sleep(0.5)

result = driver.execute_cdp_cmd(
    "Page.captureScreenshot",
    {"format": "png", "captureBeyondViewport": True},
)

Scrolling can change page state, trigger infinite loading, or affect sticky elements. For dynamic pages, prefer a site-specific readiness condition, such as waiting for a known content selector or for a loading indicator to disappear. Avoid relying on a fixed delay alone when the page’s completion can be detected directly.

5. When Selenium’s ordinary screenshot is enough

If you only need what is currently visible in the browser context, Selenium’s standard screenshot API is simpler:

driver.save_screenshot("viewport.png")

That is a viewport/current-context capture, not a promise to include the entire document. Selenium documents screenshots in the context of the current browsing context; its Python Chromium API includes convenience methods for saving a current-window screenshot as PNG. See Selenium’s windows and tabs documentation and the Selenium Python Chromium WebDriver API.

6. cURL, Python, and Node.js alternatives

CDP is the Chrome-specific approach when you need Selenium browser automation and a beyond-viewport capture. The Selenium examples above are the do-it-yourself browser method. If you need an HTTP screenshot instead of managing a Chrome session, ScreenshotNeo provides a screenshot API. Its API documentation describes the request options.

cURL

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 bytes = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', bytes));

Or skip the browser setup

One GET request returns a screenshot. Cookie banners, newsletter popups, and chat widgets are removed before the shot; each cleanup step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers say which page verdict and billing status apply. An MCP server gives AI agents tools to take screenshots, inspect page information, and capture PDFs. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp

Create a free ScreenshotNeo account to get 1,000 screenshots per month with no card.

7. Troubleshooting

Symptom Likely cause What to do
execute_cdp_cmd is unavailable The code is not running with Selenium’s Chromium-based driver, or the binding is old. Use ChromeDriver through webdriver.Chrome and update Selenium. Check the Selenium Python Chromium API for the command facility available in your installed version.
Unknown CDP command or parameter The Chrome/driver protocol version does not expose the command or parameter as expected. Check the Chrome DevTools Protocol documentation and align the installed Chrome and driver setup. Try a current Selenium and Chrome combination.
The image shows only part of the page The standard WebDriver screenshot method was used, the beyond-viewport option was omitted, or the page’s content had not rendered. Use Page.captureScreenshot with captureBeyondViewport: true; wait for required page content and inspect the resulting image.
Lazy images or sections are missing The site loads them only after scrolling or after application-specific requests finish. Scroll through the document, wait for the relevant content, and return to the top before capture. Prefer a selector-based readiness condition when available.
PNG cannot be opened The Base64 data was saved as text, or the wrong response field was decoded. Decode the response’s data value with Base64 and write the resulting bytes to the file.
Navigation times out The page load event did not complete before the configured timeout, often because of slow or long-running page resources. Check the URL and network access, set an appropriate page-load timeout, and decide whether your workflow can capture after a specific required element is ready rather than waiting for every resource.
Capture is unexpectedly huge or memory use rises A very tall page produces a large image, especially at high device pixel ratios. Capture only the needed page, reduce the page’s rendered size when acceptable, or save to a compressed format if loss is acceptable. Verify the output dimensions and fidelity.

8. Reliability, performance, and cost considerations

  • Wait for the content you need. A completed navigation is not proof that client-rendered data, lazy images, or delayed widgets are ready. Use meaningful page-specific conditions.
  • Expect large outputs for tall pages. Full-page images consume more memory and storage than viewport shots. PNG is lossless and may be large; JPEG or WebP can reduce size at a quality tradeoff.
  • Validate representative pages. Test the actual site and Chrome setup. The protocol documentation describes the command but does not guarantee identical output for every very tall page, lazy-loading behavior, or fixed-position element.
  • Keep browser and protocol versions aligned. CDP is Chrome-specific. Pin or regularly validate your Chrome, driver, and Selenium versions in automated environments.
  • Account for automation infrastructure. Selenium requires a browser and driver process, which need resources and maintenance in local, CI, or server environments. CDP itself does not add a screenshot API charge, but the browser infrastructure and compute still have costs.

FAQ

Does driver.save_screenshot() take a full-page screenshot?

Do not assume so. Selenium describes WebDriver screenshots as captures of the current browsing context. Use Chrome CDP’s beyond-viewport option when the image must extend past the viewport.

Can I save the capture as JPEG or WebP?

Yes. CDP documents PNG, JPEG, and WebP formats. Set the format parameter and use the matching file extension; quality is relevant to lossy formats.

Will scrolling before capture change the screenshot?

It can change page state or trigger more content to load. Scroll only as needed for the target site, return to the desired position, and inspect the output.

Is this method specific to Chrome?

Yes. Page.captureScreenshot is a Chrome DevTools Protocol command. For other browsers, use that browser’s supported automation and screenshot capabilities.

For product details and supported screenshot options, visit ScreenshotNeo or read the documentation.