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

Fix the Python line before troubleshooting Selenium. An “end-of-line string literal” (also shown as “unterminated string literal”) error means Python could not parse the path because its opening quote has no valid matching closing quote, or a backslash changed how the quote was interpreted. Selenium has not run yet. Close the quote and write the Windows path with a raw string, doubled backslashes, or forward slashes, then pass that string to driver.save_screenshot().

For example: screenshot_path = r"C:Usersmeshotspage.png" followed by driver.save_screenshot(screenshot_path). The sections below show why each form works, how to build paths safely, and what to check when the syntax error is gone but no image appears.

What the error means

Python parses the entire source file before it starts WebDriver. If the parser reaches the end of a line while still inside a quoted string, it raises a syntax error and stops. The browser, Selenium, and the screenshot filename have not been processed at that point. Python’s lexical-analysis rules say that the quote used to start a literal also terminates it, except where escaping rules apply. See the Python language reference.

A typical failing line is:

screenshot_path = "C:Usersmeshotspage.png

There is no closing double quote. Even when both quotes are present, a Windows backslash can introduce an escape sequence. For instance, n becomes a newline and t becomes a tab; an unintended escape can make the value invalid or change its contents. The diagnostic points at the line where parsing finally became impossible, which may be after the original typo.

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

Use one of three valid Windows path forms

Raw string

Prefix the literal with r so backslashes are retained:

screenshot_path = r"C:Usersmeshotspage.png"
driver.save_screenshot(screenshot_path)

A raw string still needs matching quotes. It also cannot end with a single backslash: that final backslash would escape the closing quote. Thus this is invalid:

folder = r"C:Usersmeshots

Use a filename, add another backslash, or construct the directory with pathlib instead of appending a lone separator.

Escaped backslashes

In an ordinary string, double every Windows separator:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
screenshot_path = "C:\Users\me\shots\page.png"
driver.save_screenshot(screenshot_path)

Each pair represents one literal backslash in the resulting value. This is explicit and works wherever a normal Python string is required.

Forward slashes

Python accepts forward slashes as separators on Windows, avoiding backslash escapes:

screenshot_path = "C:/Users/me/shots/page.png"
driver.save_screenshot(screenshot_path)

Choose the style that makes the source easiest to review; do not mix an unescaped backslash with a closing quote.

Build the path with pathlib

pathlib.Path avoids hand-written separators and handles the operating system’s native path rules. It also makes directory creation and existence checks clear:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
from pathlib import Path
from selenium import webdriver

output_dir = Path.home() / "shots"
output_dir.mkdir(parents=True, exist_ok=True)
screenshot_path = output_dir / "page.png"

driver = webdriver.Chrome()
try:
    driver.get("https://example.com")
    saved = driver.save_screenshot(str(screenshot_path))
    if not saved:
        raise OSError(f"Selenium could not save {screenshot_path}")
    print(f"Saved to {screenshot_path.resolve()}")
finally:
    driver.quit()

Passing str(screenshot_path) is compatible with Selenium versions whose method signature expects a filename string. The directory is created before the capture, so a missing folder is not confused with a parser problem.

A complete Selenium example

This minimal script uses a relative path, which avoids Windows-specific quoting altogether:

from pathlib import Path
from selenium import webdriver

screenshot_path = Path("screenshots") / "example.png"
screenshot_path.parent.mkdir(parents=True, exist_ok=True)

driver = webdriver.Chrome()
try:
    driver.get("https://example.com")
    if not driver.save_screenshot(str(screenshot_path)):
        raise OSError("save_screenshot returned False")
finally:
    driver.quit()

Selenium documents save_screenshot(filename) as saving the current window to a PNG image and recommends a full path with a .png extension. Its return value is True on success and False on an I/O error; inspect it instead of assuming that a parsed program saved a file. The official API reference is Selenium’s Python WebDriver documentation, and the guide’s basic example is driver.save_screenshot('./image.png') (see the Selenium browser-windows guide).

Diagnose the exact source line

  1. Read the complete traceback. Locate the reported file and line, then inspect that line and the one immediately above it. An unmatched quote often starts on the preceding line.
  2. Pair the delimiters. Confirm that every opening single quote, double quote, or triple quote has the same kind of closing delimiter. A single-quoted path containing an apostrophe needs escaping or a different quote style.
  3. Inspect backslashes. In a normal string, double Windows separators or replace them with forward slashes. Do not “fix” the error by randomly adding a quote inside the path.
  4. Check accidental line breaks. A path split across physical lines needs parentheses with adjacent literals, a backslash continuation, or a triple-quoted design; the simplest option is to keep the path on one line or use Path.
  5. Run a syntax-only check. Execute python -m py_compile your_script.py. If it succeeds, Python can parse the file and any remaining failure occurs at runtime.
  6. Only then investigate Selenium. Start the browser, navigate, call save_screenshot, and check its boolean result and the resolved filesystem location.

Common mistakes and their fixes

Missing closing quote

# Wrong
screenshot_path = "C:/Users/me/shots/page.png

# Correct
screenshot_path = "C:/Users/me/shots/page.png"

Using a raw string with a trailing separator

# Wrong: the final backslash escapes the quote
folder = r"C:Usersmeshots"

# Correct: build the filename instead
from pathlib import Path
screenshot_path = Path(r"C:Usersmeshots") / "page.png"

Assuming a parser error is an I/O error

A parser error prevents all code from running. A parsed script that returns False, raises a permission exception, or produces no visible file is a separate filesystem or Selenium problem. Check that the parent directory exists, that the process can write there, and that you are looking at the path printed by Path.resolve().

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

Using a directory instead of a filename

Give Selenium a filename such as page.png, not only C:/Users/me/shots/. Create the directory first and append the filename with Path.

Expecting a full-page capture by default

save_screenshot captures the current browser window. It does not, by this filename fix alone, change viewport size or capture behavior. If the file is valid but the image is not the area you expected, treat that as a separate WebDriver configuration question.

Or skip the browser setup

If you only need an image or PDF from a URL, ScreenshotNeo provides a website screenshot API and MCP server. It accepts cookie or consent banners as a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each cleanup step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the page verdict and billing status in X-Page-Verdict and X-Billed headers.

One GET request returns PNG, JPEG, WebP, or a PDF. The API supports full-page captures with lazy images loaded, CSS-element capture, dark mode, device presets or custom viewports, retina scale, PDF paper and page options, custom CSS and JavaScript, clicks, waits, request 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, usage reporting, and an OpenAPI specification. Parameter names used by other screenshot APIs also work, which can simplify migration.

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

See the ScreenshotNeo documentation for the complete option list. A basic call is:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

The equivalent Python request is:

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)

And in 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(`HTTP ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));

The Free plan includes 1,000 shots each month with no card. Paid plans start at $5 for 3,000 shots; every feature is available on every plan, and yearly billing gives two months free. An MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients, so AI agents can capture pages without your own browser setup. Create a free ScreenshotNeo account to get started.

Performance, reliability, and cost considerations

  • Parse first: Fixing the literal costs nothing and is required before any browser startup, so do not tune waits or drivers while the file still fails compilation.
  • Filesystem: Use a stable absolute or resolved path in scheduled jobs. Create the directory once, use unique filenames when parallel tests run, and check the boolean result.
  • Browser lifecycle: Put driver.quit() in a finally block so a failed save does not leave a browser process running.
  • API alternative: ScreenshotNeo’s cache hits are not billed, while failed loads and bot-check pages are identified as non-clean outcomes and are not billed. Choose a cache TTL and asynchronous jobs when you have many URLs or slow pages.
  • Version awareness: The cited Python reference is version 3.14.7 and the Selenium API reference is version 4.49.0. If your installed Python or Selenium release differs, consult its matching documentation for signature or behavior changes.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshooting after the syntax fix

The file is not created

Print screenshot_path.resolve(), verify the parent directory, test write permission, and inspect the return value from save_screenshot. A False result indicates an I/O failure rather than a string-literal issue.

The image is blank or incomplete

Confirm that driver.get() completed and that the page is not still loading. Selenium’s filename argument does not control page readiness; add an explicit WebDriver wait appropriate to the page, then capture again.

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

The path works on one operating system but not another

A hard-coded drive letter is Windows-specific. Prefer Path.home(), a project-relative path, or environment-provided output directory. Let pathlib join components rather than embedding separators.

Python reports a different line than the typo

Check preceding lines for an unclosed quote, parenthesis, bracket, or triple-quoted string. The parser reports where it can no longer continue, not necessarily where the delimiter was first omitted.

FAQ

Does save_screenshot create missing folders?

No folder creation is documented by the method. Create the parent directory yourself, preferably with Path.mkdir(parents=True, exist_ok=True).

Can I save a JPEG by changing the extension?

The documented Python method saves a PNG image. Changing the filename suffix does not turn that Selenium method into a JPEG encoder.

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

Should I use single or double quotes?

Either works. Pick the delimiter that does not require unnecessary escaping and ensure it closes on the same logical string.

Frequently Asked Questions

Does save_screenshot create missing folders?

No folder creation is documented by the method. Create the parent directory yourself, preferably with pathlib.Path.mkdir(parents=True, exist_ok=True).

Can I save a JPEG by changing the extension?

The documented Python method saves a PNG image. Changing the filename suffix does not turn that Selenium method into a JPEG encoder.

Should I use single or double quotes?

Either works. Pick the delimiter that does not require unnecessary escaping and ensure it closes on the same logical string.

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

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.