How to Use Selenium Screenshots to Document a Web App Workflow
Capture clear, repeatable screenshots at each important step in a web app workflow with Selenium, then organize and check the images as useful documentation.
Selenium can capture the browser state at each point in a web app workflow and save it as a PNG. Navigate to the page, wait until the state you want to document is visible, call driver.save_screenshot(), and repeat at meaningful checkpoints. Use element screenshots when one control or result is the evidence you need. A screenshot shows what was visible in the browser; by itself, it does not establish hidden application state or backend success.
1. Install Selenium and prepare a workflow
This example uses Python and Selenium WebDriver. It opens a page, saves a screenshot of the current browser view, and closes the browser even if an error occurs. Selenium’s official documentation shows the same core sequence: create a driver, navigate, save a screenshot, and quit.
python -m pip install selenium
from pathlib import Path
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
output_dir = Path("artifacts/workflow")
output_dir.mkdir(parents=True, exist_ok=True)
options = webdriver.ChromeOptions()
# Uncomment to run without opening a visible browser window.
# options.add_argument("--headless=new")
# Selenium Manager can manage the driver for supported setups.
driver = webdriver.Chrome(options=options)
try:
driver.set_window_size(1440, 1000)
driver.get("https://example.com")
# Wait for a meaningful state before taking the screenshot.
WebDriverWait(driver, 20).until(
EC.visibility_of_element_located((By.TAG_NAME, "h1"))
)
saved = driver.save_screenshot(str(output_dir / "01-page-loaded.png"))
if not saved:
raise OSError("Selenium could not write the screenshot")
finally:
driver.quit()
Replace the example URL and condition with your app and the state that matters. For a real workflow, put the user actions between waits and captures. Use a test account and non-sensitive fixture data if screenshots may be shared.
2. Capture meaningful workflow checkpoints
Plan the screenshot sequence around visible transitions that help someone understand the workflow: its starting state, the result of an important action, validation or error feedback when relevant, and completion. A capture immediately after a click may show the old state if the page is still updating. Wait for a visible result or status before saving.
from pathlib import Path
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
out = Path("artifacts/checkout")
out.mkdir(parents=True, exist_ok=True)
options = webdriver.ChromeOptions()
driver = webdriver.Chrome(options=options)
wait = WebDriverWait(driver, 20)
def capture(filename):
path = out / filename
if not driver.save_screenshot(str(path)):
raise OSError(f"Screenshot write failed: {path}")
try:
driver.set_window_size(1440, 1000)
driver.get("https://your-test-app.example/checkout")
wait.until(EC.visibility_of_element_located((By.NAME, "email")))
capture("01-checkout-start.png")
driver.find_element(By.NAME, "email").send_keys("qa@example.test")
driver.find_element(By.CSS_SELECTOR, "button[type='submit']").click()
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "[role='alert']")))
capture("02-validation-message.png")
# Continue with the workflow's next action and wait for its visible result.
# capture("03-confirmation.png")
finally:
driver.quit()
The selectors and flow above are illustrative: adapt them to the test app. Keep the viewport, browser, test data, and relevant setup consistent across a sequence when readers need to compare images. These are documentation practices, not Selenium requirements.
Name files in workflow order, such as 01-login.png, 02-search-results.png, and 03-confirmation.png. Pair each with a caption that says what action was taken and what visible result followed. Describe only what the image shows; do not present a screenshot as proof of an invisible server-side event.
3. Choose the screenshot scope
| Scope | Use it for | Selenium approach |
|---|---|---|
| Current browser view | Workflow context and the visible viewport | driver.save_screenshot(path) |
| One element | A focused control, form, status, or result | Find the element and call its screenshot method |
| Full document | Content extending below the viewport | Use a documented full-document method for the specific browser and driver, or capture deliberate scroll positions |
Capture one element
Element screenshots are useful when the surrounding page would distract from the evidence. Wait for the element to be visible, then save its image:
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
status = WebDriverWait(driver, 20).until(
EC.visibility_of_element_located((By.CSS_SELECTOR, "[data-testid='status']"))
)
if not status.screenshot("artifacts/workflow/status.png"):
raise OSError("Could not write element screenshot")
Element capture can fail or produce a poor image if the element is hidden, outside a usable layout, or covered by an overlay. Wait for visibility and inspect the output. The official Selenium examples demonstrate element screenshots in Python and other bindings.
Capture a full document
A normal driver screenshot represents the current browser view; do not assume it includes all content below the viewport. The reviewed Selenium 4.50.0 Python Firefox API documents save_full_page_screenshot(filename). This is a Firefox-specific documented API in that reference, so check the API for the browser and driver you actually use rather than assuming identical support everywhere.
# Firefox-specific method documented by Selenium's Python API
if not driver.save_full_page_screenshot("artifacts/workflow/full-document.png"):
raise OSError("Could not write full-page screenshot")
If your chosen driver has no documented full-document method, capture deliberate scroll positions and label them clearly. A set of viewport captures is not automatically a single continuous full-page image.
4. Save screenshot data as files, bytes, or Base64
The Python WebDriver API provides file-saving methods as well as PNG image data as bytes and Base64. The file methods expect a PNG filename; the file-saving method returns False if an I/O error occurs. Selenium’s WebDriver documentation describes the screenshot response as Base64-encoded, which bindings can expose or save for you.
# Save directly to a PNG file
ok = driver.save_screenshot("artifacts/workflow/current.png")
if not ok:
raise OSError("Screenshot save failed")
# Keep PNG data in memory
png_bytes = driver.get_screenshot_as_png()
# Get a Base64 string, for example when another system expects Base64
png_base64 = driver.get_screenshot_as_base64()
Use bytes when another step in your pipeline accepts image data directly. Base64 is useful when an integration expects an encoded string, but it adds encoding overhead and is larger than the binary image data. For ordinary documentation files, saving a PNG directly is simpler.
5. Make the images reproducible and useful
- Choose a stable test account and fixture data; remove or sanitize personal and confidential information before sharing.
- Set a consistent browser window size when images will be compared. Selenium WebDriver provides window sizing methods.
- Wait for the expected state to appear, not just for an arbitrary short pause. Use a delay only when the application has a known timing requirement that cannot be represented by a state condition.
- Decide whether dialogs, cookie banners, or other overlays are part of the evidence. Close or handle them if they obscure the workflow, unless the overlay itself is what you are documenting.
- After a run, confirm that the files exist, open correctly, and show the intended state before embedding them in a report.
- Record the browser, viewport, and relevant test fixture in the surrounding documentation so another person can interpret the conditions represented.
These recommendations help readers interpret a screenshot sequence; they are not guarantees that a workflow is correct or that the same rendering will occur in every environment.
6. Troubleshooting Selenium screenshots
| Symptom | Likely cause | Fix |
|---|---|---|
| No image file appears | The destination directory does not exist, the path is invalid, or the process cannot write there. | Create the directory, use a valid full path, check permissions, and check the method’s Boolean result. |
| The screenshot shows the previous state | The capture ran before the page finished updating. | Wait for a visible, state-specific element or result before capture. |
| Lower-page content is missing | A regular screenshot captured the current browser view, not necessarily the full document. | Use a full-document method documented for the selected driver, or capture and label intentional scroll positions. |
| An element screenshot fails or is blank | The element may be hidden, not rendered, or covered by a transient overlay. | Wait for visibility, verify the locator, and inspect the page state and saved artifact. |
| The images differ between runs | Viewport, browser, test data, timing, or page content changed. | Keep the environment and fixture consistent, wait on the same visible state, and note relevant conditions. |
| The browser is left running after a failure | Cleanup did not run on an exception path. | Put driver.quit() in a finally block or equivalent cleanup mechanism. |
7. Performance, reliability, and cost
Screenshot capture adds browser work and file I/O to an automated workflow. Capture only the checkpoints that help explain or review the process, and avoid taking repeated images while a state is unchanged. Large full-document images and many checkpoints consume more storage and take longer to write and review than a small set of focused viewport captures.
For reliability, use explicit waits for meaningful states, close the driver in cleanup code, use stable test fixtures, and check each save result. A successful screenshot write only confirms that an image artifact was produced; it does not validate the application behavior that led to the visible screen.
Selenium itself is an open-source browser automation project; this article does not assign a per-screenshot service price. Your operational costs depend on where browsers run and how you store and retain artifacts. If you need screenshots without managing browser setup, ScreenshotNeo offers a website screenshot API and MCP server. Its billing rules and plans are described below.
8. Or skip the browser setup
If you need a screenshot of a URL rather than a browser-driven sequence of interactions, ScreenshotNeo takes a screenshot with one GET request. See the ScreenshotNeo API documentation for request options.
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 removes cookie banners, newsletter popups, and chat widgets before the shot. Bot checks, blank pages, and failed loads are never billed, and response headers say which page verdict and billing result apply. Its MCP server lets AI agents use take_screenshot, get_page_info, and capture_pdf. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots. For a Selenium workflow that depends on clicks, form entry, or intermediate states, Selenium remains the method shown above; the API call is for capturing a URL directly.
Create a free ScreenshotNeo account for 1,000 screenshots a month with no card.
9. FAQ
Does a screenshot prove a workflow succeeded?
It documents what was visible at capture time. Pair it with appropriate test assertions or other evidence for claims about application behavior.
Should I use a screenshot for every step?
Capture transitions that help a reader understand or review the workflow. Extra images of unchanged states add little context.
Can I use Selenium screenshots in a report?
Yes. Save the PNG artifacts, verify they open, and include captions that describe the action and visible outcome. Sanitize sensitive data before sharing.
Can ScreenshotNeo replace Selenium for an interactive journey?
A direct URL screenshot does not perform the sequence of browser actions in this Selenium guide. Use Selenium when the journey requires interaction; use ScreenshotNeo when a URL capture fits the task.


