Use Selenium 4 with Microsoft Edge WebDriver, create an EdgeOptions object, add Edge’s documented --headless=new argument, open the page, wait for the content you need, and call your language binding’s screenshot method before quitting the driver. Headless mode removes the visible browser window; it does not change the WebDriver commands used to control Edge.
What you need before starting
Edge automation has three separate components:
- Microsoft Edge: the browser being controlled.
- Microsoft Edge WebDriver (EdgeDriver): the driver implementation that starts Edge and translates WebDriver commands.
- A language binding or framework: for example, Selenium’s Python, .NET, Java, or JavaScript package.
Use Selenium 4. Microsoft’s Edge WebDriver guidance says Selenium 3 is no longer supported for automating Microsoft Edge, while Selenium 4 has built-in Edge support. Keep Edge and EdgeDriver compatible with one another; a mismatched installation commonly prevents a session from starting.
Headless Edge still loads pages, runs JavaScript, applies cookies and headers, and exposes a normal WebDriver session. The difference is that it does not create a visible browser window.
Start EdgeDriver in headless mode
Python
Install Selenium in the environment that will run the script:
#1 Best Overall
python -m pip install -U selenium
Microsoft’s documented EdgeOptions pattern is:
from selenium import webdriver
from selenium.webdriver.edge.options import Options
options = Options()
options.add_argument("--headless=new")
driver = webdriver.Edge(options=options)
The --headless=new value is an Edge command-line argument passed through EdgeOptions. Do not confuse it with Edge’s user-facing Screenshot or Web Capture feature; those are separate browser features.
C#
using OpenQA.Selenium.Edge;
var options = new EdgeOptions();
options.AddArgument("--headless=new");
using var driver = new EdgeDriver(options);
Add the current Selenium WebDriver and EdgeDriver packages to the project before running this code. The session constructor receives the configured options.
Java
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.edge.EdgeDriver;
import org.openqa.selenium.edge.EdgeOptions;
EdgeOptions options = new EdgeOptions();
options.addArguments("--headless=new");
WebDriver driver = new EdgeDriver(options);
JavaScript
import { Builder } from "selenium-webdriver";
import edge from "selenium-webdriver/edge.js";
const options = new edge.Options();
options.addArguments("--headless=new");
const driver = await new Builder()
.forBrowser("MicrosoftEdge")
.setChromeOptions(options)
.build();
Exact package names and imports can vary with the binding release. The important part of the Edge configuration is the same: create Edge options, add --headless=new, and pass those options when building the session.
Capture a screenshot after the page is ready
Starting a session and taking a reliable capture are separate operations. A navigation command can return before images, client-rendered components, or a particular element has appeared. Choose a wait that matches the page rather than relying on an arbitrary sleep.
Rank #2
Complete Python example
Selenium’s Python binding exposes save_screenshot, which writes the current viewport image to a file and returns a Boolean indicating whether the save operation succeeded. This example waits for the document’s ready state and then waits for a target element:
from pathlib import Path
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.edge.options import Options
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
url = "https://example.com"
out = Path("edge-headless.png")
options = Options()
options.add_argument("--headless=new")
# Set a deterministic viewport; headless defaults are not the same as every desktop.
options.add_argument("--window-size=1440,1200")
driver = webdriver.Edge(options=options)
try:
driver.get(url)
wait = WebDriverWait(driver, 30)
wait.until(lambda d: d.execute_script("return document.readyState") == "complete")
wait.until(EC.visibility_of_element_located((By.TAG_NAME, "body")))
if not driver.save_screenshot(str(out)):
raise RuntimeError("Selenium reported that the screenshot was not saved")
print(f"Saved {out.resolve()}")
finally:
driver.quit()
Replace https://example.com with the page you own or are authorized to automate. The finally block closes the WebDriver session even when navigation or capture raises an exception.
What this screenshot contains
- Viewport capture: the visible browser viewport at the configured window size.
- Current state: anything rendered when the command runs, including the effects of JavaScript and CSS.
- Not automatically a full-page image: a tall page may extend below the viewport. Full-page behavior differs by browser and binding, so do not assume that a viewport screenshot includes all document content.
For a full-page result, first check the current API documentation for your chosen Selenium binding and Edge version. If that binding only exposes viewport capture, you need a separate scrolling or DevTools-based implementation and must account for sticky headers, lazy-loaded images, and duplicated content.
Saving screenshots in other bindings
The setup is documented consistently across Microsoft’s language examples, but screenshot return types and file-writing calls belong to the individual Selenium binding. Verify the method for the exact package version you install rather than copying a method from another language.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Repair Windows errors before they cause bigger problems3Fix the driver behind crashes, sound loss and screen glitches- Python:
driver.save_screenshot("edge.png")writes the image directly. - .NET: use the current Selenium .NET screenshot API and save the returned screenshot object with its documented file method. Do not treat the Python Boolean return value as a .NET return type.
- Java: use the binding’s
TakesScreenshotinterface and its documented output conversion. - JavaScript: use the current binding’s screenshot method and write the returned representation with Node’s file APIs according to that release’s documentation.
These differences matter in CI: a method can exist in one binding while another returns bytes, a Base64 string, or an object that must be converted before writing.
Rank #3
- Used Book in Good Condition
Make headless captures deterministic
Set the viewport explicitly
Specify a window size such as --window-size=1440,1200 or use the binding’s window-size command before navigation. Responsive layouts can change at breakpoints, so a screenshot taken on a developer laptop may not match one taken on a build agent.
Wait for the condition that matters
- Wait for
document.readyStatewhen the initial document must finish loading. - Wait for a specific element when a client-rendered component is the real capture target.
- Wait for an image or status indicator when the page displays asynchronous data.
- Use a short, explicit delay only when the application has no observable condition; keep the delay bounded and explain why it is needed.
Lazy images may not load until they approach the viewport. Scroll the page or trigger the application’s own loading behavior before capturing if those images are required.
Control state that changes the result
Set cookies, authentication, locale, timezone, viewport, and user-agent before the page reaches the state you want. A login redirect, consent dialog, geolocation branch, or A/B test can otherwise produce a different image on every run. Treat credentials as secrets and do not place them directly in source control.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Choose an output format
Most Selenium screenshot methods produce PNG data. Convert the file afterward if your pipeline needs JPEG or WebP, and document the conversion step. Do not rename a PNG to a different extension and assume its encoding changed.
Troubleshooting EdgeDriver screenshots
| Symptom | Likely cause | Fix |
|---|---|---|
| Session cannot be created | EdgeDriver and Edge versions are incompatible, or the driver is not on the executable path. | Install a matching Edge WebDriver, update the Selenium binding, and confirm the driver can be found by the process running the script. |
| Corporate machine refuses to start WebDriver | Microsoft documents that the DeveloperToolsAvailability policy value 2 blocks Edge WebDriver because the driver uses Microsoft Edge DevTools. |
Ask the administrator to review that managed policy. Do not attempt to bypass an organization’s control. |
| Screenshot is blank or missing content | The command ran before the application rendered, an iframe was not ready, or the requested content is below the viewport and lazy-loaded. | Wait for a meaningful element or state, switch into the required frame, and trigger lazy loading before capturing. |
| Unexpected mobile or desktop layout | The headless viewport differs from the interactive browser or crosses a responsive breakpoint. | Set a fixed window size and, if needed, use the binding’s device or user-agent configuration. |
| Cookie banner or chat widget covers the page | The automated session sees the same overlays as a normal visitor. | Handle the consent dialog in the test flow, hide an authorized selector with page-specific CSS, or use a capture service that removes known overlays. |
| File exists but is not usable | The output directory is relative to the process working directory, or the returned screenshot data was written using the wrong representation. | Print the absolute path, create the directory first, and follow the exact file-writing API for your Selenium language binding. |
Microsoft’s DisableScreenshots policy concerns screenshots initiated through keyboard shortcuts or extension APIs. Microsoft’s WebCaptureEnabled policy controls the user-facing Screenshot/Web Capture feature. Neither document, by itself, establishes that a WebDriver screenshot command is blocked or allowed, so test the managed environment and consult your administrator rather than inferring behavior from those policy names.
When a screenshot API is simpler
Launching a browser gives you control over authentication, JavaScript, custom waits, and application state, but you also maintain driver compatibility, cleanup, rendering timing, and overlay handling. A hosted screenshot API is often preferable for scheduled page images, documentation builds, link previews, and bulk URLs where you do not need an interactive session.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. It accepts a URL in one request and returns PNG, JPEG, WebP, or PDF. Before capture, it accepts consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be turned off. 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.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
For a direct request, see the ScreenshotNeo API documentation:
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)
r.raise_for_status()
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}`);
if (!res.ok) throw new Error(`${res.status} ${res.statusText}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));
ScreenshotNeo also supports full-page capture with lazy images loaded, CSS-selector element capture, dark mode, 12 device presets and custom viewports, retina scale, PDF paper settings and page ranges, HTML/CSS-to-image, custom CSS and JavaScript, pre-capture clicks, selector hiding, waits for selectors, delays or network idle, request and resource blocking, custom headers and cookies, authorization, timezone and geolocation, transparent backgrounds, resizing, selectable cache TTLs, signed public-image links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, a usage API, and an OpenAPI specification. Its parameter names also accept the names used by other screenshot APIs, easing migration.
Best Value
An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. Every feature is available on every plan: 1,000 screenshots per month are free with no card; paid plans start at $5 for 3,000 screenshots. Create a free ScreenshotNeo account to try it.
Operational and cost considerations
- Reliability: close every driver with
quit()so failed jobs do not leave browser processes running. Record the URL, viewport, browser version, and wait condition with each artifact. - Performance: reuse a controlled browser session for related captures when isolation is not required; starting a new session for every URL adds startup overhead. For parallel jobs, size concurrency for the machine’s CPU and memory instead of assuming headless is free.
- Security: restrict URLs, protect cookies and authorization headers, and avoid capturing pages containing secrets into shared artifacts.
- Cost: self-hosted EdgeDriver consumes your own compute and maintenance time. A hosted service charges according to its plan and may remove operational work, but you should still check its verdict and billing headers and select caching deliberately.
A practical decision checklist
- Choose EdgeDriver when you need browser-level interaction, private session state, custom JavaScript, or a test that must run in the same browser family as your users.
- Choose a hosted API when the input is primarily a URL and you want repeatable capture without installing Edge, EdgeDriver, and a Selenium binding.
- For either approach, define the viewport, wait condition, authentication state, output format, and failure policy before putting screenshots into CI.
Frequently Asked Questions
Does headless Edge use a different rendering engine?
No. Headless mode changes whether a window is displayed; Edge still runs as a WebDriver-controlled browser session.
Recommended Free Tools
Can I use Selenium 3 with EdgeDriver?
Microsoft’s Edge WebDriver guidance marks Selenium 3 unsupported for Microsoft Edge automation. Use Selenium 4.
Are Edge’s Web Capture policy and WebDriver screenshots the same feature?
No. WebCaptureEnabled governs Edge’s user-facing Screenshot/Web Capture feature, while a WebDriver binding issues automation commands.
Why does my screenshot differ between my laptop and CI?
The sessions may have different Edge versions, viewport sizes, fonts, policies, cookies, locale, or page timing. Record and control those inputs when visual consistency matters.
Quick Recap
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.




