Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use Selenium’s screenshot method after the page loads, and save the returned image bytes to a file. When Chrome runs in a separate Docker container, create a Remote WebDriver session at the Selenium container’s reachable URL, set a deterministic viewport, navigate, capture, and then quit the session. The same approach works for PNG, JPEG, or other formats supported by your Selenium binding.

How do I take a screenshot with Selenium in Docker?

The essential Python operation is driver.save_screenshot("screenshot.png"). Selenium sends a WebDriver screenshot command for the active browsing context; the server returns Base64-encoded image data and the language binding writes it to a file. The Selenium documentation demonstrates this pattern at selenium.dev/documentation/webdriver/browser/windows/.

  1. Start Chrome locally or in a Selenium Docker container.
  2. Create a local or remote WebDriver session.
  3. Set the window or display size before navigation.
  4. Call save_screenshot() after the page is ready.
  5. Write the file where your test process can access it, then call quit() in a finally block.

Complete Python example for a remote Chrome container

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

options = Options()
options.add_argument("--headless=new")
options.add_argument("--no-sandbox")

# Use the Selenium service name on a Docker network.
driver = webdriver.Remote(
    command_executor="http://selenium:4444/wd/hub",
    options=options,
)
try:
    driver.set_window_size(1365, 900)
    driver.get("https://example.com")
    driver.save_screenshot("screenshot.png")
finally:
    driver.quit()

If your Selenium image exposes the newer Grid endpoint, http://selenium:4444 is commonly used; use the URL documented by the exact image tag you run. From a process outside Docker, replace selenium with the published host address and port. The test process must be able to resolve and reach that address.

Run Selenium Chrome with Docker

Start a standalone Chrome container

The SeleniumHQ docker-selenium project documents standalone browser images, port 4444 for WebDriver traffic, and optional port 7900 for visual inspection. Pin a complete image tag when browser and Grid versions must be reproducible instead of relying on an unqualified latest tag. See the current instructions at github.com/SeleniumHQ/docker-selenium.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
docker run -d --name selenium 
  --shm-size=2g 
  -p 4444:4444 
  -p 7900:7900 
  selenium/standalone-chrome:<pin-a-full-tag>

--shm-size=2g is a known workaround for Chrome crashes in the project’s guidance, not a universal performance requirement. Tune shared memory for your workload. The optional 7900 mapping is useful when the image supports a browser-viewing interface and you need to inspect a visible session.

Connect from another container

Put the test container and the Selenium container on the same Docker network. Use the Selenium service name, not localhost, because localhost inside the test container refers to that test container itself.

docker network create browser-net
docker network connect browser-net selenium
# Run your test container on browser-net, then connect to:
# http://selenium:4444/wd/hub

When the browser runs in one container and Python runs in another, a screenshot path such as /tmp/screenshot.png belongs to the Python process’s filesystem. A path written inside the browser container is not automatically a host path. Use a shared volume or transfer the returned bytes through your test process if you need the file on the host.

Set the Docker display and browser viewport

Container screen variables

For a display-backed Selenium container, set the screen before starting it. docker-selenium documents SE_SCREEN_WIDTH, SE_SCREEN_HEIGHT, and related depth and DPI variables. For example:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
docker run -d --name selenium 
  --shm-size=2g 
  -e SE_SCREEN_WIDTH=1365 
  -e SE_SCREEN_HEIGHT=900 
  -e SE_SCREEN_DEPTH=24 
  -e SE_SCREEN_DPI=96 
  -p 4444:4444 
  selenium/standalone-chrome:<pin-a-full-tag>

These variables establish the container display. The browser window size, device scale factor, page layout, and the binding’s screenshot behavior can still affect the resulting image. Verify the actual pixel dimensions in your test rather than assuming that display dimensions guarantee a full-page capture.

Window size versus full-page output

driver.set_window_size(width, height) controls the browser viewport used for the current session. The standard screenshot endpoint captures the current browsing context, normally the visible viewport. It does not establish one universal full-page behavior across every browser and binding. If you need a full document, use a binding-supported full-page method or a page-specific scrolling strategy and verify it with the versions you deploy.

Headless and Xvfb settings

Chrome supports headless mode with --headless; current Selenium examples commonly use --headless=new. Chrome’s headless implementation is unified with headful Chrome, while Chrome 132.0.6793.0 and later also provide the separate chrome-headless-shell binary for the old headless implementation. Details are in the Chrome guide at developer.chrome.google.cn/docs/automation-and-testing/headless?hl=en.

Do not blindly disable Xvfb. docker-selenium’s SE_START_XVFB behavior is image- and version-sensitive. Match the display configuration to the pinned Selenium image and Chrome version. A headless session may not need a virtual display, while a display-backed or visually inspected session may depend on it.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Wait for the page before capturing

A screenshot taken immediately after get() can contain a loading state, blank region, or unrendered lazy content. Use explicit waits for the content that defines “ready” for your page.

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

# ...create driver...
driver.get("https://example.com/dashboard")
wait = WebDriverWait(driver, 30)
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "main.dashboard")))
driver.save_screenshot("dashboard.png")

For a page whose content is driven by network requests, wait for a stable application element rather than using a fixed sleep alone. A short delay can be useful for animations, but a selector-based wait is usually more deterministic.

Capture one element instead of the viewport

Selenium’s interaction documentation includes element screenshot guidance. Locate the target element and use the element screenshot method supported by your binding and version:

card = driver.find_element(By.CSS_SELECTOR, "article.product-card")
card.screenshot("product-card.png")

Element screenshots are appropriate for a component, chart, or test fixture. Confirm the method in the documentation for your language binding, especially when using a remote Grid or an older browser.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Local Chrome versus a remote Selenium container

Choice Where Chrome runs WebDriver setup File consideration
Local driver Same environment as the test process webdriver.Chrome() with Chrome installed there The screenshot path is directly visible to the test process
Remote driver Selenium standalone or Grid container webdriver.Remote(command_executor=..., options=...) Save through the test process or configure a shared volume; browser-container paths are not host paths automatically

Use local Chrome when your build image already contains a compatible browser and driver and you want the simplest filesystem behavior. Use a remote container when browser isolation, a standard Selenium image, or a separately managed Grid is more important. In either case, record the browser version, Selenium image tag, binding version, viewport, and local/remote mode for reproducibility.

Make captures reliable in CI

  • Pin versions: record the complete Selenium image tag and the Selenium language binding version.
  • Control dimensions: set SE_SCREEN_WIDTH and SE_SCREEN_HEIGHT for the container, then call set_window_size() in the test when the viewport itself matters.
  • Use stable waits: wait for a meaningful selector and, where necessary, for an application state indicating that data finished loading.
  • Keep output accessible: write screenshots to a CI artifact directory or a mounted volume.
  • Clean up: always call quit(), including when navigation or capture raises an exception.
  • Inspect failures: preserve the screenshot, driver logs, container logs, URL, and session configuration together.

Troubleshooting Selenium screenshots in Docker

“Connection refused” or a session that never starts

Confirm that the Selenium container is running, port 4444 is published or reachable on the Docker network, and the hostname is correct. Container-to-container traffic should use the service name; outside traffic should use the published host address. Check the image’s expected Grid endpoint and inspect docker logs selenium.

Chrome crashes, exits, or reports a session-not-created error

Check shared memory first. Start with the project’s documented --shm-size=2g guidance and tune it for concurrent sessions and page complexity. Then verify that the pinned Chrome, driver, Selenium image, and language binding are compatible.

Driver service timeouts or Chrome startup failures

Compare headless arguments and Xvfb settings with the documentation for your exact image and Chrome version. Incorrect SE_START_XVFB choices, unsupported flags, or a mismatch between a modern headless setup and an older image can prevent startup. Container stdout and docker logs usually provide the first useful clue.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The image is blank or captures a loading spinner

Move the screenshot after a selector-based wait, check that the URL is reachable from inside the container, and verify that authentication, cookies, and JavaScript requests are available in the session. Capture a diagnostic screenshot after navigation and inspect browser console or application logs if your test framework exposes them.

The screenshot has the wrong dimensions

Check all four layers: container screen variables, WebDriver window size, device scale factor, and page responsive breakpoints. Ensure the environment is not applying a different DPI or mobile emulation profile. Read the image dimensions in your test and compare them with the requested viewport.

The file is missing on the host

Determine which process wrote the file. With Remote WebDriver, the screenshot binding normally receives image data in the test process, but an explicit path used by another operation may refer to a container filesystem. Save to a mounted host directory or copy the bytes from the test process into your CI artifact directory.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

ScreenshotNeo provides a website screenshot API and MCP server when you need a capture without maintaining Chrome containers. One GET request returns a PNG, JPEG, WebP, or PDF. Before capture it accepts cookie and consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Install your API key, then use the documented request examples at screenshotneo.com/docs/.

Best Value
Docker Container Linux Devops Programming Coding T-Shirt
  • Docker, Docker Swarm, Docker Compose, Programmer, Developer, Coding, Programming, Software Engineer, Code, DevOps, Deploy, Deployment, Kubernetes, Salt, Puppet, Chef, Terraform, Container, AWS, Azure, Cloud, Geek, Funny, Computer, Software, Tech, IT
  • Integration, Scrum, Compile, Compilation, Science, Bug, Debug, Python, Linux, Java, Javascript, Scala, Dotnet, Kotlin
  • Lightweight, Classic fit, Double-needle sleeve and bottom hem

cURL

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

Python

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)

Node.js

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

ScreenshotNeo also supports full-page captures with lazy images loaded, CSS-selector element shots, dark mode, device presets and custom viewports, retina scale, PDF paper and page-range settings, custom CSS and JavaScript, clicks, selector or network-idle waits, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, TTL caching, signed image links, asynchronous jobs with signed webhooks, bulk capture for up to 100 URLs per call, a usage API, and an OpenAPI specification. Existing parameter names used by other screenshot APIs also work for easier migration.

Plan Allowance Price
Free 1,000 shots/month $0, no card
Starter 3,000 shots $5
Growth 15,000 shots $15
Pro 60,000 shots $39
Scale 250,000 shots $99
Business 1,000,000 shots $249

Yearly billing gives two months free, and every feature is available on every plan. Create a free ScreenshotNeo account to get 1,000 screenshots each month with no card.

Frequently Asked Questions

Can Selenium save a screenshot as bytes instead of a file?

Yes. Use your binding’s screenshot-as-bytes or screenshot-as-Base64 method, then write the decoded data to the destination managed by your test process.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Does Selenium automatically capture the entire page?

The standard endpoint captures the active browsing context, usually the visible viewport. Full-page behavior is binding- and browser-dependent, so verify the method supported by your deployed versions.

Why should I use a pinned Selenium Docker image?

A full tag lets you reproduce the same browser and Grid combination. An unqualified latest tag can change independently of your test code.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.