Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
To take a screenshot with Selenium Chrome in Docker, navigate with WebDriver, call the binding’s screenshot method, and save the returned image to a path that exists where your test process runs. If Chrome is in a separate Selenium container, create a Remote WebDriver session through the container’s reachable WebDriver URL, set the display size before the session starts, and copy or share the output file deliberately.
The minimal Python operation is driver.save_screenshot("screenshot.png"). The difficult parts in Docker are usually networking, shared memory, headless/display configuration, viewport sizing, and deciding where a remote file is written.
Minimal Python screenshot example
When Selenium and Chrome run in the same container, the normal Chrome driver API is sufficient. This example always closes the browser, including when navigation or capture fails.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →from selenium import webdriver
options = webdriver.ChromeOptions()
options.add_argument("--headless")
options.add_argument("--no-sandbox")
# Set the browser viewport, not the Docker host window.
options.add_argument("--window-size=1440,900")
driver = webdriver.Chrome(options=options)
try:
driver.get("https://example.com")
driver.save_screenshot("screenshot.png")
finally:
driver.quit()
Selenium’s screenshot endpoint returns encoded image data; language bindings expose convenience methods that write it to a file. The documented Python form is driver.save_screenshot('./image.png') (Selenium WebDriver screenshot documentation).
#1 Best Overall
Build a container that can save the image
A local-browser image needs Chrome, a compatible Selenium binding and a Python runtime. The output path is inside the test container unless you mount a host directory.
FROM python:3.12-slim
RUN apt-get update && apt-get install -y --no-install-recommends
chromium chromium-driver
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY capture.py .
CMD ["python", "capture.py"]
# requirements.txt
selenium
Build and run it with a mounted output directory so the file survives container removal:
docker build -t selenium-shot .
mkdir -p shots
docker run --rm -v "$PWD/shots:/app/shots" selenium-shot
Change the Python destination to /app/shots/screenshot.png. A relative path such as screenshot.png is written to the process working directory, not automatically to your host.
Recommended Free Tools
Use a separate Selenium Chrome container
The SeleniumHQ Docker project provides standalone browser images with a WebDriver endpoint. Its quick start publishes port 4444 for WebDriver traffic and optionally port 7900 for visual inspection. A test process outside the Docker network uses the host-published address; a test container on the same network uses the Selenium service name.
docker run -d --name selenium-chrome
--shm-size=2g
-p 4444:4444
-p 7900:7900
selenium/standalone-chrome:4.35.0-20250808
Use a full image tag that matches the browser and Grid version you require rather than relying on an unqualified latest tag. The project describes --shm-size=2g as an arbitrary, known-to-work value that must be tuned for your workload, not as a universal performance guarantee (SeleniumHQ docker-selenium documentation).
Remote Python capture
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_argument("--window-size=1440,900")
driver = webdriver.Remote(
command_executor="http://localhost:4444/wd/hub",
options=options,
)
try:
driver.get("https://example.com")
driver.save_screenshot("screenshot.png")
finally:
driver.quit()
If the Python process itself runs in another container, replace localhost with the Selenium service name, for example http://selenium-chrome:4444/wd/hub, and put both services on the same Docker network. Confirm the exact endpoint supported by the image tag you deploy.
Where does a remote screenshot file go?
save_screenshot() writes from the perspective of the client binding. With a remote session, do not assume that a path visible inside the browser container is automatically a host path. The safest pattern is to run the test client in a container with a mounted output directory, or retrieve the image bytes and write them in the client process. Selenium’s Docker documentation discusses volumes for browser downloads, but it does not define one universal screenshot-file transfer mechanism for every binding and Grid setup.
Set Docker display and browser dimensions
Three dimensions can differ: the X display resolution, the Chrome window size and the page’s layout viewport. Set the values deliberately and verify the resulting image.
Screen variables in docker-selenium
docker-selenium documents environment variables including SE_SCREEN_WIDTH, SE_SCREEN_HEIGHT, screen depth and DPI. Set them before the container starts:
docker run -d --name selenium-chrome
--shm-size=2g
-e SE_SCREEN_WIDTH=1440
-e SE_SCREEN_HEIGHT=900
-p 4444:4444
selenium/standalone-chrome:4.35.0-20250808
These variables configure the display exposed to the session; they do not promise a full-length page image. Browser window dimensions, device scale factor, responsive breakpoints and the selected screenshot method all affect the pixels captured.
Rank #3
Headless or display-backed Chrome
Chrome supports Selenium-driven headless operation with --headless. Chrome for Developers explains that headless and headful modes share the unified implementation, and notes that from Chrome 132.0.6793.0 the old headless mode is distributed separately as chrome-headless-shell (Chrome Headless mode).
Do not blindly disable Xvfb. docker-selenium’s SE_START_XVFB behavior and recommended settings vary with image and Chrome versions. Follow the documentation for the exact image tag, then choose one of these approaches:
- Headless: pass the Chrome headless argument and use the image’s documented headless configuration.
- Display-backed: allow the image’s Xvfb setup to start, which can make visual debugging possible through the optional inspection port.
Full-page and element screenshots
The standard screenshot endpoint captures the current browsing context. It is not a universal guarantee of a complete, scrollable page in every browser and binding. For a normal viewport capture:
driver.get("https://example.com")
driver.set_window_size(1440, 900)
driver.save_screenshot("viewport.png")
For one component, locate the element and use the element-screenshot method supported by your Selenium language binding and version:
card = driver.find_element("css selector", ".pricing-card")
card.screenshot("pricing-card.png")
Verify the binding’s current element-screenshot documentation before depending on behavior such as clipping, device scale or off-screen scrolling (Selenium WebDriver interactions). If you need a complete page image, a practical fallback is to use a page-specific JavaScript or CSS strategy, or a capture service that explicitly implements full-page scrolling.
Free tools Windows power users keep installed
One-click scans. No signup required.
Make captures deterministic
A screenshot taken immediately after get() can contain a loading state. Add an explicit wait for content that proves the page is ready:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
wait = WebDriverWait(driver, 30)
driver.get("https://example.com/dashboard")
wait.until(lambda d: d.find_element(By.CSS_SELECTOR, "main.dashboard").is_displayed())
driver.save_screenshot("dashboard.png")
- Use a stable selector instead of a fixed sleep where possible.
- Set a viewport before navigation when responsive layout matters.
- Control authentication, cookies and test data so the same URL produces the intended state.
- Record the Selenium image tag, Selenium binding version, Chrome version, viewport, and local-versus-remote setup for every reproducible capture.
Common Docker failures and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
| Chrome exits or the session disappears | Insufficient shared memory | Start the container with --shm-size=2g as a starting point, then tune it for the workload; inspect logs. |
| Connection refused or timeout creating a session | Wrong hostname, port, path or container network | Use the published host address from outside Docker, the service name inside a shared network, and confirm port 4444 is listening. |
| Driver-service timeout or Chrome fails at startup | Headless/Xvfb settings do not match the image or Chrome version | Compare SE_START_XVFB, headless arguments and the selected image’s version-specific guidance. |
| Image is missing on the host | It was written inside a container filesystem | Mount an output directory, write there, or transfer bytes from the client process. |
| Unexpected mobile layout or cropped content | Window, display and device scale settings differ | Set SE_SCREEN_WIDTH/SE_SCREEN_HEIGHT and Chrome window size, then inspect actual image dimensions. |
| Capture shows a spinner or blank section | Screenshot taken before application readiness | Wait for a meaningful selector or application condition instead of relying only on navigation completion. |
| Works today, fails after rebuild | Unpinned browser/Grid image or changed binding | Pin a full Selenium image tag and record all component versions. |
Container output is sent to stdout; inspect it with:
docker logs selenium-chrome
Performance, reliability and cost considerations
Browser startup is usually more expensive than writing the PNG. Reuse a WebDriver session for several pages when isolation requirements permit, but create a fresh session when cookies, permissions or extensions could contaminate results. Parallel sessions increase CPU and memory demand; increase shared memory and monitor the container rather than assuming one configuration fits every workload.
Remote capture adds network latency and introduces another failure point. Keep the test client and Selenium container on a low-latency Docker network when possible. For CI, retain the exact image tag and upload screenshots as build artifacts. A failed navigation, browser crash or timeout should be treated separately from a successful screenshot containing an application error page.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. One GET request returns PNG, JPEG, WebP or PDF, so you do not need to maintain Chrome, Xvfb, Docker networking or WebDriver sessions for a straightforward URL capture. Before the capture it accepts the cookie or consent banner like a visitor and removes more than 60 known consent platforms, newsletter popups and chat widgets; each cleanup step can be switched off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and response headers identify the page verdict and billing result.
It also supports full-page captures with lazy images loaded, CSS-selector element captures, dark mode, device presets or custom viewports, retina scale, PDF paper and page settings, custom CSS and JavaScript, clicks, selector or network-idle waits, request and resource blocking, headers, cookies, user agents, Authorization, timezone, geolocation, transparent backgrounds, resizing, chosen cache TTLs, signed image links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, a usage API and an OpenAPI specification. Its MCP server exposes take_screenshot, get_page_info and capture_pdf to Claude, Cursor and other MCP clients.
Best Value
- 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}`);
See the complete parameter reference in the ScreenshotNeo documentation. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. An account is free to create.
Frequently Asked Questions
Can I use Selenium screenshots with a remote browser?
Yes. Construct a Remote WebDriver with the Selenium container’s reachable URL, then call the same screenshot method on that remote driver.
Does Selenium automatically save a remote screenshot to my host?
No. The destination belongs to the process and filesystem performing the write. Use a mounted directory or explicitly transfer image bytes.
What port is used by standalone Selenium Chrome?
The docker-selenium quick start uses port 4444 for WebDriver traffic; port 7900 is optional visual inspection.
Is 2 GB of shared memory mandatory?
No. docker-selenium calls --shm-size=2g a known-to-work starting value and recommends tuning it for your workload.
Quick Recap
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.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.

