How to Capture a Webpage Screenshot in Selenium with Firefox Headless
Run Firefox without a visible window, save a viewport screenshot as PNG, and learn when to use Firefox’s full-page screenshot method.
Use Selenium’s Firefox WebDriver with Firefox’s -headless option, navigate to the page, then call save_screenshot(). That method saves the current browser window as a PNG; it does not mean the entire document is captured. Use Firefox’s separate full-page screenshot method when you need the full document.
1. Install and prepare Firefox
Install Selenium for Python and make sure Firefox is installed. Selenium’s Firefox guide says Selenium 4 requires Firefox 78 or greater and recommends using the latest geckodriver. If WebDriver cannot start, check the versions of Selenium, Firefox, and geckodriver together. See the Selenium Firefox guide.
python -m pip install selenium
Save the following as screenshot.py. Change the target URL and output path as needed. The path shown is absolute on a Unix-like system; use an absolute path that exists and is writable on your operating system.
2. Capture the current Firefox window
from selenium import webdriver
from selenium.webdriver.firefox.options import Options
url = "https://example.com"
output_path = "/tmp/page.png"
options = Options()
options.add_argument("-headless")
driver = webdriver.Firefox(options=options)
try:
driver.get(url)
saved = driver.save_screenshot(output_path)
if not saved:
raise OSError(f"Could not save screenshot to {output_path}")
finally:
driver.quit()
print(f"Saved screenshot to {output_path}")
Firefox runs without a visible browser window because the option is supplied when creating the WebDriver session. The script navigates before capturing, checks the screenshot method’s boolean result, and quits the browser even if navigation or saving raises an exception.
Selenium documents save_screenshot(filename) as saving the current window to a PNG and returning False for an I/O error. Use a .png filename and a full path. See the Firefox WebDriver API.
3. Choose the screenshot scope and output form
| Need | Use | What it returns or captures |
|---|---|---|
| PNG file of the current window | driver.save_screenshot(path) |
Writes a PNG; check its boolean result. |
| PNG bytes for further processing | driver.get_screenshot_as_png() |
Returns screenshot bytes for the current window. |
| Screenshot of the full document | driver.save_full_page_screenshot(path) |
Firefox-specific full-document screenshot method. |
The viewport method and full-document method are distinct. Do not assume save_screenshot() includes content below the current window. Firefox’s API describes save_full_page_screenshot() as capturing the full document. For method details, consult the Firefox WebDriver API and Firefox functionality guide.
Save a full-document screenshot
from selenium import webdriver
from selenium.webdriver.firefox.options import Options
options = Options()
options.add_argument("-headless")
driver = webdriver.Firefox(options=options)
try:
driver.get("https://example.com")
saved = driver.save_full_page_screenshot("/tmp/full-page.png")
if not saved:
raise OSError("Could not save full-page screenshot")
finally:
driver.quit()
This method is specific to Firefox’s WebDriver API. Choose it when the requested output is the entire document rather than the current window.
Get screenshot bytes instead of writing a file
from pathlib import Path
from selenium import webdriver
from selenium.webdriver.firefox.options import Options
options = Options()
options.add_argument("-headless")
driver = webdriver.Firefox(options=options)
try:
driver.get("https://example.com")
png_bytes = driver.get_screenshot_as_png()
Path("/tmp/page.png").write_bytes(png_bytes)
finally:
driver.quit()
Use the bytes form when another part of your program needs the image in memory, or when you want to control file writing yourself. It captures the current window, just like save_screenshot().
4. Handle page readiness and output paths
driver.get(url) navigates to the target before the screenshot call. A page may still have content that appears later, such as client-rendered sections or images. If a particular element must be present before capture, wait for that element before taking the screenshot. Selenium’s documentation demonstrates the general navigate-then-screenshot workflow in its windows and tabs guide.
- Use the correct URL, including
https://where the site requires it. - Make sure the output directory exists and the process can write there.
- Use
.pngfor these screenshot methods. - Keep
driver.quit()in afinallyblock so the browser session is closed after success or failure. - If you need more than the current window, select the Firefox full-document method explicitly.
5. Or skip the browser setup
If you need a screenshot without installing and managing Firefox and geckodriver, ScreenshotNeo provides a website screenshot API and MCP server. One GET request returns an image or PDF. Its capture can accept cookie and consent banners and remove 60+ 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 cost nothing, and response headers report the page verdict and billing status. Its MCP tools let AI agents take screenshots. The free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. Every feature is on every plan. See the ScreenshotNeo API documentation.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://example.com"},
timeout=90,
)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
Sign up for 1,000 free screenshots a month with no card.
6. Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Firefox fails to start | Firefox, Selenium, or geckodriver is missing or incompatible. | Install Firefox, use Selenium 4 with Firefox 78 or later, and check the installed geckodriver version against the current Selenium Firefox guidance. |
| The screenshot file is missing | The destination directory does not exist, the path is not writable, or the save call returned False. |
Use an existing writable directory and absolute path; check the boolean result and raise an error when it is false. |
| The image shows only the top part of a long page | save_screenshot() captures the current window. |
Use Firefox’s save_full_page_screenshot() when you need the full document. |
| The screenshot is blank or missing late content | The page or target content may not have finished rendering when capture was requested. | Wait for the relevant page element or content condition before calling the screenshot method. |
| The process remains running after capture | The WebDriver session was not closed. | Call driver.quit() in a finally block. |
| Output is not a PNG | The wrong API or file extension was used. | Use Selenium’s PNG screenshot methods and a .png path. |
7. Performance, reliability, and cost
A local Selenium capture requires a working browser installation and WebDriver session, so startup and navigation are part of the workflow. Reuse a session when capturing multiple pages in one run if that fits your application, and always close it when finished. Choose viewport or full-document capture according to the required output; full-document capture is a separate Firefox method.
For reliability, use an absolute writable output path, check the file method’s return value, wait for required dynamic content, and ensure cleanup runs on errors. The Selenium workflow itself has no per-screenshot service charge, but it does require you to provision and maintain the browser environment. ScreenshotNeo instead has a free allowance of 1,000 shots per month and paid tiers beginning at $5 for 3,000; only clean shots are billed, with verdict and billing headers in each response. See the API docs for its options and response behavior.
8. FAQ
Does headless Firefox need a desktop display?
No. The -headless Firefox argument runs without a visible browser window.
Does save_screenshot() capture the whole page?
It captures the current window. Use Firefox’s save_full_page_screenshot() for a full-document capture.
Can I use the screenshot without saving it immediately?
Yes. get_screenshot_as_png() returns PNG bytes for the current window.
What should I check first when WebDriver startup fails?
Confirm Firefox is installed, Selenium is version 4, Firefox meets the guide’s version requirement, and geckodriver is current.


