How to Take Screenshots with Selenium in Python, Java, and C#
Capture a page or element with Selenium in Python, Java, or C#. Learn how to save screenshots, handle frames and common errors, or use a screenshot API.
Selenium can capture the current browsing context or a specific element. Use the driver-level screenshot method for the current page context and the element-level method when you only need one component. Python saves directly with save_screenshot; Java uses TakesScreenshot; C# uses ITakesScreenshot.
The examples below use ChromeDriver and save PNG files. A normal driver screenshot should not be assumed to capture an entire long page: capture extent can depend on the browser driver and its behavior. The Selenium WebDriver screenshot endpoint returns Base64-encoded image data; bindings expose convenient ways to save or retrieve it. Selenium’s screenshot examples cover driver and element captures in these languages.
1. Set up the browser and wait for the page
Install Selenium for your language, make sure Chrome is available, and create a ChromeDriver session. Selenium Manager can handle driver setup in supported Selenium installations. If your environment manages browser drivers separately, configure the matching driver there.
Navigate to the target URL and wait for the content you need before taking the screenshot. A navigation call returning does not necessarily mean a single-page app has finished rendering its important content. Use an explicit wait for a meaningful element when timing matters.
2. Take a screenshot in Python
Install the Python binding with pip install selenium. This complete example opens a page, waits for its body, saves a driver screenshot, and closes the session even if an error occurs.
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
options = webdriver.ChromeOptions()
# Uncomment to run without opening a visible browser window:
# options.add_argument("--headless=new")
driver = webdriver.Chrome(options=options)
try:
driver.get("https://www.example.com")
WebDriverWait(driver, 15).until(
EC.presence_of_element_located((By.TAG_NAME, "body"))
)
driver.save_screenshot("page.png")
finally:
driver.quit()
For a single element, locate it and call screenshot on the element. The element must be present and visible for a useful capture.
element = WebDriverWait(driver, 15).until(
EC.visibility_of_element_located((By.CSS_SELECTOR, "main article"))
)
element.screenshot("article.png")
To work with the image in memory instead of writing it directly, use get_screenshot_as_png(), which returns PNG bytes:
png_bytes = driver.get_screenshot_as_png()
with open("page.png", "wb") as image_file:
image_file.write(png_bytes)
3. Take a screenshot in Java
Add Selenium Java to your project and use the Selenium version and build setup already used by your application. This example uses Maven-style imports and Java’s built-in file copying, so it does not need Apache Commons IO.
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Duration;
import org.openqa.selenium.By;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
public class PageScreenshot {
public static void main(String[] args) throws Exception {
WebDriver driver = new ChromeDriver();
try {
driver.get("https://www.example.com");
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(15));
wait.until(ExpectedConditions.presenceOfElementLocated(By.tagName("body")));
byte[] png = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
Files.write(Path.of("page.png"), png);
WebElement article = wait.until(ExpectedConditions.visibilityOfElementLocated(
By.cssSelector("main article")
));
byte[] elementPng = ((TakesScreenshot) article).getScreenshotAs(OutputType.BYTES);
Files.write(Path.of("article.png"), elementPng);
} finally {
driver.quit();
}
}
}
The Selenium documentation also demonstrates OutputType.FILE followed by copying the returned file. If you use FileUtils.copyFile in that form, add Apache Commons IO to your project; the byte-array example above avoids that extra dependency.
4. Take a screenshot in C#
Add the Selenium WebDriver NuGet package and use a compatible Chrome installation. This example waits for the page body and a target element, saves each capture as PNG, and always quits the driver.
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;
var options = new ChromeOptions();
// Uncomment to run without opening a visible browser window:
// options.AddArgument("--headless=new");
var driver = new ChromeDriver(options);
try
{
driver.Navigate().GoToUrl("https://www.example.com");
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(15));
wait.Until(d => d.FindElement(By.TagName("body")));
var pageScreenshot = (driver as ITakesScreenshot).GetScreenshot();
pageScreenshot.SaveAsFile("page.png", ScreenshotImageFormat.Png);
var article = wait.Until(d =>
{
var element = d.FindElement(By.CssSelector("main article"));
return element.Displayed ? element : null;
});
var elementScreenshot = (article as ITakesScreenshot).GetScreenshot();
elementScreenshot.SaveAsFile("article.png", ScreenshotImageFormat.Png);
}
finally
{
driver.Quit();
}
The documented ScreenshotImageFormat values include BMP, GIF, JPEG, PNG, and TIFF. The example explicitly chooses PNG so the file extension and format agree.
5. Choose a page, element, or frame capture
| Need | Use | Keep in mind |
|---|---|---|
| Current browsing context | Driver screenshot method | Extent may be viewport-sized; do not assume universal full-page behavior. |
| One component | Element screenshot method | Wait for the element to be visible and ensure it is not covered or clipped unexpectedly. |
| Content inside an iframe | Switch to the frame, then capture | Switch back to default content when finished. |
| Image bytes for further processing | Use the binding’s byte or data API | Write bytes in binary mode and match the extension to the actual format. |
WebDriver commands operate in the currently selected browsing context. To target an iframe, switch into it first. Selenium documents selecting frames by element, name or ID, or index; return to the top-level page with the default-content switch. See Selenium’s frame documentation.
# Python example: switch to a frame element, capture its current context, then return.
frame = driver.find_element(By.CSS_SELECTOR, "iframe#preview")
driver.switch_to.frame(frame)
driver.save_screenshot("frame-context.png")
driver.switch_to.default_content()
For an element within the iframe, locate it after switching into the frame and use the element screenshot method. A screenshot of the driver while switched into a frame is still subject to the browser driver’s screenshot behavior; it does not establish a universal full-page capture rule.
6. Make captures more reliable
- Wait for the thing you need. Prefer an explicit wait for a visible selector over a fixed sleep. For content loaded after navigation, wait for its own selector or state.
- Select the right window. If your flow opened a new tab, switch to its window handle before capture.
- Select the right frame. Switch into an iframe before locating its contents, then return to default content afterward.
- Use stable selectors. A durable ID or test-specific attribute is less likely to break than a long positional CSS path.
- Close the session in a
finallyblock. This prevents failed waits or file operations from leaving browser processes running. - Keep file format and extension aligned. The examples save PNG data as
.png.
7. Troubleshoot common screenshot problems
| Symptom | Likely cause | Fix |
|---|---|---|
| Browser does not start or driver session fails | Browser/driver mismatch, unavailable browser binary, or restricted runtime | Use a compatible installed browser, update Selenium and the driver setup, and check that the execution environment permits browser processes. |
| Screenshot is blank or content is missing | Capture ran before the page or app rendered, or the wrong tab/frame is selected | Wait for a visible content selector and verify the current window and frame before capture. |
| Element lookup times out | Selector is wrong, element is in an iframe, or it never became visible | Check the selector, switch into the correct frame, and wait for visibility rather than mere presence when taking an element shot. |
| Only part of a long page appears | Driver-level screenshot extent is not necessarily full-page | Confirm the selected driver’s documented behavior. If the requirement is a full-page capture, use a supported full-page method or a screenshot service that provides it. |
| Image file cannot be opened | Text mode, wrong extension, incomplete write, or wrong output format | Write byte data in binary mode, save the returned data fully, and make the extension match the selected image format. |
| Browser processes remain after an error | Quit was skipped by an exception path | Put quit() in Python/Java finally or C# finally/using cleanup. |
| Screenshot differs between runs | Dynamic content, animation, fonts, or remote assets changed during capture | Wait for required assets, disable animation through your test setup if appropriate, and stabilize test data and viewport. |
8. Performance, reliability, and cost
Selenium launches and controls a real browser session, so startup and page loading are part of the capture time. For a small number of captures during browser-based testing, this is often exactly the desired behavior. For repeated captures, reuse a driver session when your test design allows it, avoid unnecessary navigation, and always clean up the session after the batch.
Reliability depends on more than the screenshot call: the browser and driver must be compatible, the target page must load, and the correct tab/frame and application state must be selected. Explicit waits make failures easier to diagnose than arbitrary delays. Save captures to a known writable path and treat transient network or page failures as separate from screenshot encoding failures.
Selenium itself is an open-source browser automation tool. Your operating cost comes from the machine and browser runtime, infrastructure, and any external services your workflow uses; Selenium’s screenshot API does not by itself define a per-image service price. If you need screenshots without provisioning browser automation, the API option below is billed according to its stated plans and response billing headers.
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. The API accepts the parameter names used by other screenshot APIs, which can make switching easier. See the ScreenshotNeo documentation for request options.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
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)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
- Cookie banners are accepted and removed, along with known consent platforms, newsletter popups, and chat widgets, before the shot; each step can be turned off.
- Bot checks, blank pages, timeouts, failed loads, and cache hits are never billed. Responses include
X-Page-VerdictandX-Billedheaders. - An MCP server lets AI agents use
take_screenshot,get_page_info, andcapture_pdf. - 1,000 screenshots per month are free with no card; paid plans start at $5 for 3,000 screenshots.
Sign up for 1,000 free screenshots a month, with no card.
10. Frequently asked questions
Does taking a screenshot change the page?
The screenshot call captures the current rendered state. Your navigation, clicks, waits, and application behavior determine what that state contains.
Can I save screenshots to a different directory?
Yes. Pass an absolute or relative path to the save method, and ensure the process can write to that directory.
Can Selenium capture only one element?
Yes. Locate the element and use the binding’s element screenshot API shown above.
Does a driver screenshot always include the whole page?
No universal full-page guarantee is established by the documented examples. Check the behavior for your browser and driver, or choose a full-page capture method when that is a requirement.


