How to Take a Full-Page Website Screenshot with Selenium on Mac
Use Selenium with Firefox on macOS to save a full-page website screenshot as a PNG, with setup steps, troubleshooting, and a browser-free API option.
To capture an entire web page with Selenium on a Mac, use Selenium’s Firefox driver and its full-document screenshot method. The example below saves a PNG to your Desktop. Selenium’s cited Safari API documents a screenshot of the current window, not a matching full-page method, so Firefox is the documented route for this workflow.
1. Install the prerequisites
Use Python 3 and install Selenium in the environment where you will run the script:
python3 -m pip install selenium
Selenium’s Firefox driver uses Firefox. Install Firefox for macOS if it is not already available. The code below uses Selenium’s standard driver setup; if your environment requires a separately managed driver binary or browser configuration, follow the Selenium documentation for that setup.
2. Capture a full-page PNG with Firefox
Save this as full_page_screenshot.py. It navigates to the target URL, writes the screenshot to an absolute path, and checks whether Selenium reports an I/O error.
from pathlib import Path
from selenium import webdriver
url = "https://example.com"
output = Path.home() / "Desktop" / "page.png"
with webdriver.Firefox() as driver:
driver.get(url)
saved = driver.get_full_page_screenshot_as_file(str(output))
if not saved:
raise OSError(f"Could not save screenshot to {output}")
print(f"Saved full-page screenshot to {output}")
Run it from Terminal:
python3 full_page_screenshot.py
The output path should be writable and end in .png. Change example.com and the Desktop path to suit your task. The method saves a full-document image, including regions beyond the visible window; it is different from a viewport-only screenshot. See the Selenium Firefox WebDriver API.
Wait for the page before capturing
Navigation returning does not guarantee that every site-specific asynchronous component is ready. For a page with a known element that signals readiness, wait for it before capture:
from pathlib import Path
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
url = "https://example.com"
output = Path.home() / "Desktop" / "page.png"
with webdriver.Firefox() as driver:
driver.get(url)
WebDriverWait(driver, 20).until(
lambda browser: browser.find_element(By.CSS_SELECTOR, "main")
)
saved = driver.get_full_page_screenshot_as_file(str(output))
if not saved:
raise OSError(f"Could not save screenshot to {output}")
Replace main with a selector appropriate to the page. If the page fills content only as you scroll, wait for that content to load before taking the screenshot; the full-page API does not by itself establish that every lazy or dynamic component has finished loading.
3. Choose the right browser and output method
| Need | Approach | What the cited API documents |
|---|---|---|
| Full document saved to a file | Firefox: get_full_page_screenshot_as_file(path) |
Full-page PNG file; use a full path and check the boolean result. |
| Full-page image data in memory | Firefox: get_full_page_screenshot_as_png() or get_full_page_screenshot_as_base64() |
PNG bytes or a base64 representation, useful when another part of your program handles storage. |
| Current browser window | Safari: save_screenshot(path) |
The cited Selenium Safari API documents current-window capture. It does not document that method as full-document capture. |
Firefox’s full-page methods are listed in the Firefox API reference. Safari automation is available through Apple’s WebDriver support, using safaridriver, but the cited Selenium Safari API reference describes a current-window screenshot method.
4. Use cURL, Python, or Node.js with a screenshot API
The Selenium example above is the do-it-yourself browser workflow. If you need to request a screenshot from a service instead, ScreenshotNeo provides a website screenshot API and an MCP server for developers. The API accepts one GET request with a URL and can return PNG, JPEG, WebP, or PDF. Read the ScreenshotNeo API documentation for its parameters and response details.
cURL
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://example.com \
-o shot.webp
Python
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://example.com"},
timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
Node.js
const q = new URLSearchParams({
access_key: 'YOUR_API_KEY',
url: 'https://example.com'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
const bytes = new Uint8Array(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', bytes));
Or skip the browser setup
ScreenshotNeo removes cookie banners, newsletter popups, and chat widgets before the shot; each cleanup step can be turned off. Bot checks, blank pages, and failed loads are never billed, and response headers report the page verdict and billing status. Its MCP server lets AI agents use screenshot tools. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. ScreenshotNeo supports full-page capture with lazy images loaded, along with image formats, PDF, custom waits, and other capture options.
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://example.com \
-o shot.webp
Create a free ScreenshotNeo account to get 1,000 screenshots a month with no card. Visit ScreenshotNeo to learn more.
5. Troubleshooting and reliability
| Symptom | Likely cause | What to do |
|---|---|---|
The output file is missing or the method returns False |
The destination path is invalid or not writable, or an I/O error occurred. | Use an absolute path, confirm the directory exists and is writable, and keep the .png extension. |
| The screenshot shows only a viewport | A current-window screenshot method was used instead of Firefox’s full-document method. | Call get_full_page_screenshot_as_file() on the Firefox driver. |
| The page is missing content | Content may be asynchronous, lazy-loaded, or dependent on scrolling. | Wait for a page-specific readiness element or the content itself. If scrolling triggers more content, make the page load that content before capture. |
| The capture is of an unexpected page | The requested page may have redirected, shown an interstitial, or failed to load as expected. | Check the final browser URL and page state before saving; add a condition that verifies the expected page element. |
| Safari capture does not include the whole document | The cited Selenium Safari API describes current-window capture, not a full-document method. | Use Firefox’s documented full-page method for this workflow, or capture the full page through a service that supports it. |
Full-page capture records the page state available at capture time; it is not a guarantee that animations have settled or that every dynamically generated section has appeared. For repeatable results, use a stable URL, wait for a meaningful page condition, and verify the saved output on representative pages.
6. Performance and cost notes
With Selenium, your script manages a browser session, so the work includes starting the browser, loading the page, waiting for readiness, and writing the image. Runtime varies with the site, network, browser, and page length; no fixed timing is implied here. Very long pages can create large image files, so check available disk space and consider whether a full-document image is necessary for every run.
Selenium and Firefox are the software components in the local workflow; ScreenshotNeo is a metered API with a free monthly allowance and paid tiers. ScreenshotNeo bills only clean shots: bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing. The response includes X-Page-Verdict and X-Billed headers so a client can inspect the result. Pricing is Free for 1,000 shots/month, Starter $5 for 3,000, Growth $15 for 15,000, Pro $39 for 60,000, Scale $99 for 250,000, and Business $249 for 1,000,000; yearly billing gives two months free. Every feature is on every plan.
7. Frequently asked questions
Does the Selenium Firefox method save PNG or JPEG?
The cited full-page file method saves PNG. The file path should end with .png.
Can I capture the image without writing a file first?
Yes. Firefox’s API also exposes full-page methods that return PNG bytes or base64 data.
Does full-page mean every dynamic element will be present?
No. It describes the capture extent beyond the window bounds. The page still needs to reach the state you want to record before capture.
Can I use the same method in Safari?
The cited Selenium Safari API documents a current-window screenshot method. For documented full-document capture with Selenium, use Firefox.


