Chrome DevTools vs Selenium for Automated Website Screenshots
Both CDP and Selenium can capture browser screenshots. Choose by browser scope, capture controls, and whether screenshots belong to a larger automation suite.
Short answer: Use Chrome DevTools Protocol (CDP) when you target Chrome or Chromium and want direct screenshot controls such as clipping, image format, and capture beyond the viewport. Use Selenium WebDriver when screenshots are one step in a broader browser test suite, especially when you may run against different browsers or remote browser sessions. Both can capture screenshots; the documentation does not establish a universal speed, reliability, or fidelity winner.
If you need browser events over a bidirectional connection, evaluate WebDriver BiDi as well. Selenium describes it as a cross-browser direction for event-driven automation. Pin browser versions and validate your implementation against the pages and environments that matter.
1. How to choose
| Question | Prefer CDP | Prefer Selenium |
|---|---|---|
| Which browser is in scope? | Chrome or Chromium is the explicit target. | You want a WebDriver workflow that can encompass multiple browsers. |
| What does the screenshot need? | Direct protocol options for format, quality, clipping, or beyond-viewport capture. | A current browsing-context screenshot or an element screenshot as part of a test. |
| What automation already exists? | A Chrome-specific tool or protocol workflow. | An existing Selenium suite with navigation, interaction, assertions, or remote execution. |
| Do you need browser events? | CDP exposes Chromium protocol domains, but the live tip-of-tree schema can change. | Consider WebDriver BiDi for a bidirectional, cross-browser event stream. |
CDP instruments Chromium, Chrome, and other Blink-based browsers. Its Page domain exposes Page.captureScreenshot. Selenium WebDriver is a general browser-driving interface, and Selenium documents screenshots of both the current browsing context and individual elements. See the Chrome DevTools Protocol overview and reference, Selenium’s window and tab screenshot documentation, and its WebDriver documentation.
2. CDP: capture a Chrome screenshot directly
This Node.js example launches Chrome through Puppeteer, obtains its DevTools Protocol session, calls Page.captureScreenshot, and writes the returned Base64 image bytes to disk. Puppeteer is used here to manage the Chrome process and protocol session; the capture command itself is CDP.
Install and run
mkdir cdp-shot && cd cdp-shot
npm init -y
npm install puppeteer
node capture.mjs https://example.com shot.png
Save the following as capture.mjs:
import puppeteer from 'puppeteer';
import { writeFile } from 'node:fs/promises';
const target = process.argv[2] ?? 'https://example.com';
const output = process.argv[3] ?? 'shot.png';
const browser = await puppeteer.launch({ headless: true });
try {
const page = await browser.newPage({
viewport: { width: 1440, height: 900 },
deviceScaleFactor: 1,
});
await page.goto(target, { waitUntil: 'networkidle2', timeout: 60_000 });
const cdp = await page.createCDPSession();
await cdp.send('Page.enable');
const { data } = await cdp.send('Page.captureScreenshot', {
format: 'png',
captureBeyondViewport: true,
fromSurface: true,
});
await writeFile(output, Buffer.from(data, 'base64'));
await cdp.detach();
console.log(`Wrote ${output}`);
} finally {
await browser.close();
}
The URL and output path can be supplied as arguments. For example, node capture.mjs https://example.com result.webp still emits PNG unless you change format to webp; the extension should match the selected format. The protocol reference documents PNG, JPEG, and WebP, JPEG quality, an optional clip rectangle, and captureBeyondViewport. It returns Base64-encoded image data. Check the current Page.captureScreenshot schema for exact parameter details.
CDP options to know
format: PNG, JPEG, or WebP. Choose a lossy format where smaller output matters more than lossless pixels.quality: image quality for JPEG (and protocol-supported lossy encoding); it is not meaningful for PNG. Confirm accepted values in the current schema.clip: an x/y/width/height rectangle with a scale factor for capturing a region.captureBeyondViewport: permits capture beyond the visible viewport when supported by the browser and capture setup.fromSurfaceandcaptureBeyondViewport: surface and beyond-viewport behavior can vary with browser version and page conditions; validate the result you need.
For a clipped capture, pass an object like clip: { x: 0, y: 0, width: 800, height: 600, scale: 1 } in the CDP command. To capture the full document, a common approach is to measure document dimensions in the page and use a clip, or use a higher-level full-page facility. A viewport-sized screenshot and a document-sized screenshot are different tasks; do not assume setting a tall viewport reproduces a browser’s full-page capture behavior.
3. Selenium: capture a page or one element
Selenium’s screenshot methods fit naturally into a browser test. The following Python example saves a screenshot of the current page and then a screenshot of a selected element. Selenium’s WebDriver screenshot endpoint returns Base64 data; the Python convenience methods write the image file.
Install and run
python -m venv .venv
. .venv/bin/activate
python -m pip install selenium
python selenium_shot.py https://example.com
Save as selenium_shot.py:
import sys
from pathlib import Path
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
url = sys.argv[1] if len(sys.argv) > 1 else 'https://example.com'
options = webdriver.ChromeOptions()
options.add_argument('--headless')
options.add_argument('--window-size=1440,900')
driver = webdriver.Chrome(options=options)
try:
driver.get(url)
WebDriverWait(driver, 30).until(
lambda d: d.execute_script('return document.readyState') == 'complete'
)
driver.save_screenshot('page.png')
# Replace this selector with an element that exists on the target page.
elements = driver.find_elements(By.CSS_SELECTOR, 'h1')
if elements:
elements[0].screenshot('heading.png')
finally:
driver.quit()
For a remote Selenium Grid or remote WebDriver endpoint, construct a webdriver.Remote with the endpoint and browser options appropriate to that environment. Ensure the remote browser has access to the target URL and that output-file handling matches where the browser runs. A local file written by the browser container may not appear on the test runner’s filesystem.
What Selenium captures
driver.save_screenshot(path)ordriver.get_screenshot_as_file(path)captures the current browsing context.element.screenshot(path)captures the selected element. Locate it after navigation and after the page has rendered the relevant content.- For full-page screenshots, WebDriver’s basic screenshot operation is generally the current viewport. Full-document capture may need browser-specific support or a separate implementation; choose and verify that behavior explicitly.
4. Reproducible screenshots
A screenshot is the result of a browser, page, data, and timing state. For repeatable captures or visual comparisons, control the inputs that can change the rendered pixels:
- Pin browser versions. Chrome for Testing provides versioned browser downloads and matching ChromeDriver releases. Use a known browser build in CI instead of silently accepting whichever version happens to be installed. See Chrome for Testing and Chrome’s ChromeDriver version selection guidance.
- Set the viewport and scale. Fix width, height, and device scale factor. A different viewport can change responsive layout, line wrapping, and lazy loading.
- Wait for the content you need. “Navigation complete” does not always mean client-rendered content or images are ready. Wait for a meaningful selector or application-specific readiness signal, and set a timeout.
- Stabilize the page. Use deterministic test data where possible. Disable or await animations, avoid time-dependent content, and ensure fonts and images have loaded before capture.
- Fix browser environment details. Keep fonts, locale, timezone, color scheme, and relevant browser flags consistent across runs.
- Validate on representative pages. Check pages with long content, sticky headers, lazy images, consent prompts, and dynamic widgets. The documentation does not quantify how much any one factor affects visual differences.
Chrome’s automation guidance calls Chrome for Testing a dedicated flavor for testing and automation, and describes versioned downloads as useful for repeatable environments. Selenium’s driver management can help locate a compatible driver, but a reproducible pipeline should still make its browser and driver versions intentional.
5. Performance, reliability, and cost
The official documentation describes capabilities and architecture, not a controlled head-to-head benchmark. There is no source-backed basis here to claim that CDP is always faster, Selenium is always more reliable, or one produces more accurate pixels. Browser startup, network conditions, page complexity, wait conditions, machine resources, and remote-browser latency can dominate a particular run.
- Performance: reuse a browser session when capturing many pages if isolation requirements allow it; avoid needless browser startups. Measure end-to-end time on representative pages in the same CI or production environment. Record navigation and capture time separately.
- Reliability: use explicit readiness conditions and bounded timeouts. Always close the browser in a
finallyblock. Retry only failures that are plausibly transient, and avoid turning deterministic page errors into repeated expensive runs. - Protocol compatibility: CDP’s live tip-of-tree schema changes frequently and has no backward-compatibility guarantee. Pin Chrome and validate commands when upgrading.
- Operational cost: self-hosted automation consumes compute, browser maintenance, and engineering time. Remote WebDriver adds a remote execution dependency. Compare these costs with the required volume and maintenance level rather than assuming either approach is free to operate.
6. Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Chrome fails to start in CI | Missing browser dependencies, incompatible browser/driver versions, or unsuitable container flags. | Use a supported Chrome environment, pin compatible Chrome and driver releases, and inspect the browser startup error. Add only the runtime flags required by that environment. |
| CDP reports an unknown method or parameter | The command schema differs from the browser version or a parameter is unsupported. | Check the protocol version exposed by the running browser and consult the matching/current Page domain schema. Pin or upgrade deliberately. |
| Screenshot is blank or mostly empty | The capture ran before app rendering, navigation failed, or the page content is in another frame. | Check navigation and console errors, wait for an app-specific selector, and switch into the relevant frame before locating content. |
| Screenshot cuts off long content | The operation captured only the viewport, or beyond-viewport behavior was not enabled/supported for the chosen method. | Choose a full-page strategy explicitly, measure the document, or use a supported beyond-viewport option; inspect the resulting dimensions. |
| Element screenshot fails | The selector matched nothing, the element is stale, hidden, or outside the expected frame. | Wait for the element to exist and be visible, reacquire it after navigation or rerender, and switch to its frame if needed. |
| Images or fonts are missing | Capture occurred before assets loaded, a request failed, or the environment lacks the expected fonts. | Wait for relevant assets or selectors, inspect network failures, and install/pin fonts in the capture environment. |
| Runs differ between machines | Browser build, viewport, scale factor, fonts, locale, animations, or page data differ. | Pin the browser and environment, set viewport and scale explicitly, stabilize dynamic content, and compare in a consistent runner. |
| Remote screenshot file cannot be found | The output path belongs to the remote browser host or container. | Use the remote WebDriver screenshot data API and write the returned bytes on the test runner, or configure artifact transfer for the remote environment. |
7. Or skip the browser setup
ScreenshotNeo provides a website screenshot API: one GET request returns an image or PDF. Its cookie and consent handling accepts banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers report the page verdict and billing status. An MCP server gives AI agents tools to take screenshots, inspect page info, and capture PDFs. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000.
See the ScreenshotNeo API documentation for request options. This Node.js example uses the supplied API call pattern:
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 Bun.write('shot.webp', res);
Equivalent cURL and Python calls:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
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)
ScreenshotNeo is an alternative to try first when you want an API call instead of maintaining browser setup: cookie banners, popups, and chat widgets are removed before the shot; bot checks, blank pages, and failed loads are never billed; an MCP server lets AI agents take screenshots; and 1,000 screenshots a month are free with no card, with paid plans starting at $5 for 3,000. Create a free account and get 1,000 screenshots a month with no card.
8. Frequently asked questions
Is Selenium the same thing as Chrome DevTools?
No. Selenium WebDriver is a browser automation interface. CDP is a browser debugging and instrumentation protocol used by Chrome and Chromium tooling. Selenium can also expose browser-specific functionality, but its general WebDriver interface and direct CDP commands are distinct approaches.
Does WebDriver BiDi replace CDP today?
Selenium describes BiDi as the cross-browser replacement direction for CDP and a bidirectional WebSocket protocol. That does not mean every CDP capability has an equivalent available in every browser; check the feature support you need.
Which should I use for visual regression tests?
Use the browser automation stack that gives you control over the target browser and test state. Fix the rendering environment, then validate the chosen capture method on your actual pages. The supplied official sources do not rank the tools for visual regression accuracy.
Can both capture an individual element?
Selenium documents an element screenshot operation. CDP’s screenshot command supports a clip rectangle; derive that rectangle from the element’s position and dimensions when you need protocol-level region capture.
Can these tools capture a page that requires login?
Yes, if the automation establishes the required authenticated browser state and is permitted to access the page. Use test credentials and keep secrets out of source control and screenshot artifacts.
