How to Capture a Website Screenshot with Selenium and ChromeDriver
Capture a website screenshot with Selenium and ChromeDriver in Python. Learn driver setup, waits, element captures, troubleshooting, and a no-browser API option.
Use Selenium’s Python WebDriver to open a page and call save_screenshot("screenshot.png"). The method saves a PNG of the current browser window and returns a boolean, so check the result and always close the browser with driver.quit(). With Selenium 4.6 and later, Selenium Manager can usually obtain the driver automatically.
from selenium import webdriver
url = "https://example.com"
driver = webdriver.Chrome()
try:
driver.get(url)
saved = driver.save_screenshot("screenshot.png")
if not saved:
raise OSError("Screenshot could not be saved")
finally:
driver.quit()
Install Selenium with python -m pip install selenium, save the code as screenshot.py, then run python screenshot.py. The image is written to the current working directory. Use a .png filename: this API saves PNG data.
1. What this screenshot captures
driver.save_screenshot() captures the current browser window. It does not promise a full-page image of every page below the fold. If you need one element, capture that element directly; if you need the entire document, choose and verify a full-page technique compatible with your Selenium and Chrome versions.
| Need | Approach | What to know |
|---|---|---|
| Visible browser window | driver.save_screenshot("shot.png") |
Captures the current window. |
| One element | element.screenshot("element.png") |
Captures the element rather than the whole window. |
| Entire long page | Use a full-page capture technique supported by your environment | Verify output dimensions and behavior; the basic method does not establish a universal Chrome full-page guarantee. |
2. Install Python, Selenium, and Chrome
- Install Python and Google Chrome in your environment.
- Install Selenium:
python -m pip install selenium. - Run the example. Selenium Manager, included with Selenium 4.6 and later, supports automatic driver management.
You do not always need to download ChromeDriver yourself. For a controlled or restricted environment, you can install a driver manually, put it on PATH, or provide its location through Selenium’s Chrome Service object. Selenium’s Chrome documentation says that Chrome and ChromeDriver must match by major version. See the [Selenium driver installation guide](https://www.selenium.dev/documentation/getting_started/installing_browser_drivers/) and [Chrome-specific documentation](https://www.selenium.dev/documentation/webdriver/browsers/chrome/).
Optional: specify a ChromeDriver path
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
service = Service(executable_path="/path/to/chromedriver")
driver = webdriver.Chrome(service=service)
try:
driver.get("https://example.com")
if not driver.save_screenshot("screenshot.png"):
raise OSError("Screenshot could not be saved")
finally:
driver.quit()
Replace the example path with the driver executable path for your machine. This is useful when the executable is not on PATH or you need to select a particular installation.
3. Wait for dynamic content before capturing
driver.get() normally waits for the document’s ready state to reach complete. JavaScript can still update the page after that point, so navigation completing does not prove that every image, chart, or application component is ready. Wait for the specific condition that matters to your screenshot rather than adding an arbitrary long sleep. Selenium also warns that mixing implicit and explicit waits can cause unpredictable timeout behavior. Read [Selenium’s wait guidance](https://www.selenium.dev/documentation/en/webdriver/waits/).
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
url = "https://example.com"
driver = webdriver.Chrome()
try:
driver.get(url)
WebDriverWait(driver, 15).until(
EC.visibility_of_element_located((By.CSS_SELECTOR, "main"))
)
if not driver.save_screenshot("screenshot.png"):
raise OSError("Screenshot could not be saved")
finally:
driver.quit()
Change main to a selector that appears when the content you need is ready. A timeout means that condition did not become true in the allotted time; it does not necessarily mean the browser failed to load the page.
4. Capture one element instead of the window
When you only need a chart, card, or other element, wait for it and call the element’s screenshot method. The output is scoped to that element.
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
url = "https://example.com"
driver = webdriver.Chrome()
try:
driver.get(url)
card = WebDriverWait(driver, 15).until(
EC.visibility_of_element_located((By.CSS_SELECTOR, ".card"))
)
if not card.screenshot("card.png"):
raise OSError("Element screenshot could not be saved")
finally:
driver.quit()
Use a selector that identifies the intended element. If it is outside the viewport or hidden, adjust the page state or wait condition and verify the resulting image. See Selenium’s [window and element interaction documentation](https://www.selenium.dev/documentation/webdriver/interactions/windows/).
5. Full-page screenshots: know the limits
The basic Python screenshot API is described as a current-window screenshot. Do not assume that scrolling or calling save_screenshot() automatically creates one image containing the entire document. Full-page capture behavior depends on the browser, Selenium API, and technique you choose. Confirm support for your installed versions and inspect the output dimensions and bottom of the page.
For pages with lazy-loaded images, content may only appear after scrolling. A full-page workflow may need to trigger that content before capture; the method must be selected for your environment. If a reliable full-page result is a hard requirement, test the chosen technique on representative pages rather than treating the basic window screenshot as equivalent.
6. Run Chrome headlessly in automation
For a server or CI job without a visible desktop, Chrome can run headlessly. The screenshot calls and cleanup remain the same.
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_argument("--headless")
url = "https://example.com"
driver = webdriver.Chrome(options=options)
try:
driver.get(url)
if not driver.save_screenshot("screenshot.png"):
raise OSError("Screenshot could not be saved")
finally:
driver.quit()
Headless and desktop rendering can differ due to viewport, fonts, installed browser components, or environment configuration. If visual output matters, set an intentional window size and compare captures in the same environment used for production.
7. Troubleshoot common failures
| Symptom | Likely cause | Fix |
|---|---|---|
| Unable to locate driver or driver startup error | Selenium Manager could not obtain a compatible driver, or a manual path is wrong. | Check network and browser installation; update Selenium; verify the driver path and executable permissions, or put the driver on PATH. |
| Chrome and ChromeDriver version error | The browser and driver major versions do not match. | Use a compatible driver for the installed Chrome major version or let Selenium Manager resolve it. |
| Screenshot is blank or content is missing | The page is still rendering, the target selector was wrong, or the page content depends on later JavaScript or scrolling. | Wait for the specific visible element or application condition; inspect the page and screenshot dimensions. |
save_screenshot() returns False |
The screenshot could not be written, commonly due to an invalid path or filesystem permissions. | Use a writable directory, check the filename and permissions, and keep the False check. |
| Timeout waiting for an element | The selector never became visible, the page changed, or the wait is too short for the environment. | Confirm the selector in the page, wait for the correct condition, and set a reasonable timeout for observed load behavior. |
| Image differs between local and CI | Viewport, fonts, browser version, or machine rendering differs. | Align browser and viewport settings and capture in a consistent environment. |
| Browser remains running after a failure | Cleanup did not run after an exception. | Put browser work in try/finally and call driver.quit() in the finally block. |
8. Performance, reliability, and cost
- Performance: A local capture includes browser startup, navigation, page rendering, and file writing. Reusing a browser session for a batch can avoid repeated startup, but isolate page state and close the session when the batch ends.
- Reliability: Use explicit waits tied to the content you need, keep browser and driver compatible, and guarantee cleanup with
finally. Capture failures and navigation timeouts should be handled as separate outcomes. - Cost: Selenium and ChromeDriver are an open-source, self-managed approach; operational cost comes from the machine and time spent maintaining browser environments. Remote browser infrastructure may be useful when scaling, but choose it based on your deployment needs.
9. Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server for developers. One GET request returns an image or PDF. It removes cookie and consent banners, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers report the page verdict and billing status. Its MCP server gives AI agents tools to take screenshots, get page information, and capture PDFs.
See the [ScreenshotNeo API documentation](https://screenshotneo.com/docs/) for request options. This cURL example saves a WebP screenshot:
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}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer())));
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. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots. Sign up for 1,000 free screenshots a month, with no card required.
10. Frequently asked questions
Do I need to download ChromeDriver separately?
Not necessarily. Selenium 4.6 and later supports automatic driver management through Selenium Manager. Manual installation remains an option for controlled environments.
Does a PNG extension matter?
Use a .png filename for save_screenshot(), which saves PNG data.
Can I capture only a specific part of the page?
Yes. Locate the element and use its screenshot method. That captures the element rather than the full browser window.
Does page load completion mean the screenshot is ready?
No. JavaScript may continue to change the page after the document reaches its complete ready state. Wait for the content your capture requires.
Sources
- Selenium Python Chromium WebDriver API: screenshot method, PNG output, and boolean result.
- Selenium Chrome documentation: Chrome and ChromeDriver compatibility.
- Selenium driver installation guide: Selenium Manager and manual driver configuration.
- Selenium wait strategies: navigation readiness and explicit waits.
- Selenium window and tab documentation: window and element screenshot examples.


