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

Give Selenium an explicit, resolved filename, create its parent directory first, and check the Boolean result. In Python, driver.save_screenshot() and driver.get_screenshot_as_file() write the current browser window to the exact .png path you provide; Selenium does not select a hidden screenshot folder for you.

The reliable pattern: resolve, create, save, verify

A screenshot path should be based on a directory you control, not on whatever directory happens to be current when the test starts. This matters because an IDE, a shell, a test runner and CI can each choose a different working directory.

from pathlib import Path
from selenium import webdriver

screenshot_dir = Path(__file__).resolve().parent / "artifacts" / "screenshots"
screenshot_dir.mkdir(parents=True, exist_ok=True)
output_file = screenshot_dir / "login-page.png"

driver = webdriver.Chrome()
try:
    driver.get("https://example.com")
    ok = driver.save_screenshot(str(output_file))
    if not ok:
        raise OSError(f"Selenium could not write screenshot: {output_file}")
    print(f"Saved screenshot to {output_file}")
finally:
    driver.quit()

This example does four important things:

  • Builds an absolute path: Path(__file__).resolve() anchors the destination to the test file’s location rather than the process working directory.
  • Creates missing folders: mkdir(parents=True, exist_ok=True) creates both artifacts and screenshots when necessary.
  • Uses a PNG filename: Selenium’s Python API documents PNG output and expects the filename to end in .png.
  • Checks the result: save_screenshot() returns True after a successful write and False when an I/O error occurs.

If the browser setup itself fails, driver = webdriver.Chrome() raises before the save call. The Boolean check covers the later filesystem write, so a test cannot quietly pass while its artifact is missing.

How Selenium chooses the destination

The filename argument is the destination

The Python WebDriver method receives a filename and opens that exact filename for binary writing. There is no Selenium-managed “screenshots” directory to configure. The caller owns the path. A relative filename such as screenshots/home.png is interpreted relative to the process’s current working directory, not relative to the Python file containing the test.

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

For predictable local and CI output, pass a full path. You can print Path.cwd() while diagnosing a relative-path problem, but resolving the project or test-artifact directory up front is safer than relying on it.

Parent directories are not created for you

Opening artifacts/screenshots/login-page.png fails when either parent directory is absent. Create the complete directory tree before calling WebDriver. exist_ok=True also makes repeated test runs safe when the folders already exist.

The extension should be .png

The API describes this operation as saving the current window to a PNG image file and warns when a supplied name does not end in .png. The extension does not convert the image to another format. If you need JPEG or WebP, save the PNG and convert it in a separate image-processing step.

Choosing a path that works on every machine

Anchor paths to the test file

Path(__file__).resolve().parent is useful for a small project whose artifacts should sit beside the tests. A repository-level layout might instead derive a known project root and append a standard artifact directory:

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.
from pathlib import Path

project_root = Path(__file__).resolve().parents[1]
output_file = project_root / "test-artifacts" / "screenshots" / "checkout.png"
output_file.parent.mkdir(parents=True, exist_ok=True)

Choose one convention and use it everywhere. Mixing relative paths with file-relative paths is a common reason screenshots appear in an unexpected directory.

Use the runner’s artifact directory in CI

Continuous-integration systems often collect a particular directory after a job. Point output_file at that directory (or copy the file there after capture) so the image survives workspace cleanup. The exact environment variable differs by runner, so read the runner’s documentation and convert its value to a Path before appending your screenshot filename.

Prevent accidental overwrites

Writing the same path again targets that path again. That is useful when you want one current image, but it destroys the previous image when retaining every failure artifact. Include a test name, case identifier or timestamp in the filename. Sanitize names supplied by tests so they cannot introduce path separators.

from datetime import datetime, timezone

stamp = datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%SZ")
filename = f"login-failure-{stamp}.png"
output_file = screenshot_dir / filename

Two equivalent file-saving methods

Method Output Use it when Failure signal
driver.save_screenshot(filename) Writes PNG to the supplied path You want the concise, commonly used call Returns True or False
driver.get_screenshot_as_file(filename) Writes PNG to the supplied path You prefer the explicitly named “get … as file” API Returns True or False

Both calls represent the same file-oriented workflow: create the directory, pass a full .png path and test the Boolean. The second form is equivalent in the documented Python API.

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

When you should keep the screenshot in memory

File output is not required if your application uploads the image, embeds it in a report or chooses the storage location itself. Selenium also exposes byte and Base64 representations:

png_bytes = driver.get_screenshot_as_png()

with open(output_file, "wb") as image_file:
    image_file.write(png_bytes)

base64_image = driver.get_screenshot_as_base64()
  • get_screenshot_as_png() gives you PNG bytes for an object store, HTTP upload or custom writer.
  • get_screenshot_as_base64() gives a Base64 string, which is convenient when an HTML report expects an embedded image.
  • When you write the bytes yourself, your code—not Selenium—controls directory creation and error handling. Catch or propagate the file exception appropriate to your test framework.

Diagnosing “wrong folder” and missing-file problems

My screenshot is in a different directory

Cause: the path was relative, so it followed the process working directory. Fix: print the resolved destination and pass an absolute path:

print(output_file.resolve())
ok = driver.save_screenshot(str(output_file.resolve()))

Do not assume the directory containing the test is the working directory; those are separate concepts.

save_screenshot returns False

Cause: Selenium encountered an I/O error while opening or writing the requested filename. Typical causes include a missing parent directory, an unwritable location, a read-only CI workspace or an invalid path. Create the parent directory, select a writable artifact directory and raise an error that includes the resolved path. The method’s documented contract is to return False for an I/O failure rather than raising that failure itself.

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

The directory exists, but the file still is not there

Check that you are looking at the same absolute path your process used. Log output_file.resolve(), verify the Boolean, and make sure cleanup code did not remove the artifact after the test. In parallel tests, also check that another case did not reuse the same filename.

The filename has the wrong extension

Use a name ending exactly in .png. A different suffix does not request a different image format; it conflicts with the API’s PNG contract and can trigger a warning.

The browser closes before the image is written

Keep the save call inside the try block and call driver.quit() in finally, as in the example. If navigation or an assertion fails, capture the screenshot in an exception handler before quitting:

try:
    driver.get("https://example.com")
    # test steps and assertions here
except Exception:
    failure_file = screenshot_dir / "unexpected-failure.png"
    if not driver.save_screenshot(str(failure_file)):
        print(f"Could not save failure screenshot: {failure_file.resolve()}")
    raise
finally:
    driver.quit()

This pattern preserves the original exception while making a failed artifact write visible.

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

Designing a maintainable screenshot helper

Centralize path construction and result checking so individual tests only provide a logical name. A helper also gives you one place to enforce filename sanitization, timestamps and artifact retention.

from pathlib import Path
import re
from selenium.webdriver.remote.webdriver import WebDriver

def save_png(driver: WebDriver, root: Path, name: str) -> Path:
    safe_name = re.sub(r"[^A-Za-z0-9._-]+", "_", name).strip(".")
    if not safe_name:
        safe_name = "screenshot"
    if not safe_name.lower().endswith(".png"):
        safe_name += ".png"

    root.mkdir(parents=True, exist_ok=True)
    destination = (root / safe_name).resolve()
    if destination.parent != root.resolve():
        raise ValueError("Screenshot name resolved outside the artifact directory")

    if not driver.save_screenshot(str(destination)):
        raise OSError(f"Selenium could not write screenshot: {destination}")
    return destination

# Example:
# path = save_png(driver, Path("test-artifacts/screenshots"), "cart-checkout")
# print(path)

Keep the helper’s root directory stable for the test run, and let the test framework publish that directory as an artifact. Returning the path makes it easy to include a link in logs or reports.

Performance, reliability and storage considerations

  • Capture only when useful: screenshots add disk writes and storage. Capturing on assertion failures usually gives more diagnostic value than capturing every step.
  • Use unique names in parallel runs: include a worker or test-case identifier to avoid races and overwrites.
  • Prefer bytes for custom pipelines: get_screenshot_as_png() avoids a temporary file when the next operation is an upload or report embedding.
  • Check every write: a missing screenshot should fail the artifact step loudly, even if the browser test result is otherwise successful.
  • Keep artifacts bounded: configure your CI retention policy and remove stale local runs so a long test history does not fill the workspace.

The screenshot call captures the current browser window. Navigate, wait for the state you want to document, then save; a path fix cannot correct a page captured before it finished rendering.

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

Or skip the browser setup

When you need a URL image rather than a browser test artifact, ScreenshotNeo provides a single HTTP request. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups and chat widgets. 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 lets Claude, Cursor and other MCP clients call take_screenshot, get_page_info and capture_pdf.

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

See the ScreenshotNeo API documentation for parameters and response details. A direct call looks like this:

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}`);

ScreenshotNeo includes full-page captures with lazy images loaded, CSS-selector element captures, dark mode, device presets or custom viewports, retina scale, PDF controls, custom CSS and JavaScript, click-before-capture, selector hiding, selector/delay/network-idle waits, request and resource blocking, custom headers/cookies/user agents/Authorization, timezone and geolocation, transparent backgrounds, resizing, configurable-TTL caching, signed links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, a usage API and an OpenAPI specification. Parameter names used by other screenshot APIs also work, which can simplify migration.

The Free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots; yearly billing provides two months free, and every feature is available on every plan. Create a free ScreenshotNeo account to try it without adding a card.

FAQ

Can Selenium save a screenshot as JPEG directly?

The documented Python file methods save PNG images. Save the PNG first, then convert it with an image library if a JPEG deliverable is required.

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

Should I use an absolute path in every test?

For reproducible local and CI artifacts, yes. A relative path is valid, but its meaning depends on the process working directory, which can change between launchers.

Is a successful browser test proof that the screenshot exists?

No. Treat the Boolean returned by the file-saving method as a separate check and fail or log clearly when it is False.

Frequently Asked Questions

Can Selenium save a screenshot as JPEG directly?

The documented Python file methods save PNG images. Save the PNG first, then convert it with an image library if a JPEG deliverable is required.

Should I use an absolute path in every test?

For reproducible local and CI artifacts, yes. A relative path depends on the process working directory, which can change between launchers.

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

Is a successful browser test proof that the screenshot exists?

No. Check the Boolean returned by the file-saving method and report a failure when it is false.

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.