Does Puppeteer Work with Microsoft Edge?
Yes. Use puppeteer-core with Edge’s executable path, then validate the exact browser and Puppeteer versions you deploy.
Yes. Puppeteer works with Microsoft Edge because Edge is Chromium-based and exposes the Chrome DevTools Protocol. For an existing Edge installation, Microsoft documents using puppeteer-core with executablePath pointing to the Edge executable. [Microsoft’s Edge automation guide](https://learn.microsoft.com/en-us/microsoft-edge/test-and-automation/test-and-automation) describes this integration.
The important limitation is version support: Puppeteer guarantees compatibility with its bundled browser, while a browser selected through executablePath is outside that guarantee. Puppeteer’s launch documentation says to use an external executable at your own risk, so test the exact Edge version, Puppeteer version and operating system combination you will run in production.
1. Choose the right Puppeteer package
Use puppeteer-core when Edge is already installed and you want Puppeteer to launch that executable. The full puppeteer package is designed to download and use Puppeteer’s bundled browser, which is useful when you do not need Microsoft Edge specifically.
npm install puppeteer-core
Microsoft’s [Puppeteer overview](https://learn.microsoft.com/en-us/microsoft-edge/puppeteer/) shows the same installed-browser approach. Puppeteer’s [supported browsers documentation](https://pptr.dev/chromium-support/) lists its supported browser types; Edge is supplied as a custom Chromium executable rather than as a separately guaranteed browser type.
2. Find the Microsoft Edge executable
Do not copy a single path from an example and assume it applies to every computer. Edge Stable, Beta, Dev and Canary can use different locations, and installation scope varies between per-user and system installs.
- Open Microsoft Edge.
- Navigate to
edge://version. - Copy the value shown for the executable path.
- Pass that path to
puppeteer.launch({ executablePath }).
Microsoft specifically recommends checking edge://version when locating the executable. Store the path in an environment variable or configuration file so deployment changes do not require source edits.
3. Complete JavaScript example
This runnable script launches Edge, opens a page, waits for the document to load, captures a screenshot and closes the browser even when an error occurs.
import puppeteer from 'puppeteer-core';
const executablePath = process.env.EDGE_EXECUTABLE_PATH;
const targetUrl = process.env.TARGET_URL || 'https://example.com';
if (!executablePath) {
throw new Error('Set EDGE_EXECUTABLE_PATH to the path shown by edge://version');
}
const browser = await puppeteer.launch({
executablePath,
headless: true,
defaultViewport: { width: 1440, height: 900, deviceScaleFactor: 1 },
args: ['--no-sandbox']
});
try {
const page = await browser.newPage();
page.setDefaultNavigationTimeout(45_000);
page.setDefaultTimeout(15_000);
await page.goto(targetUrl, { waitUntil: 'networkidle2' });
await page.screenshot({ path: 'edge-shot.png', fullPage: true });
console.log(`Saved screenshot for ${targetUrl}`);
} finally {
await browser.close();
}
Run it with:
EDGE_EXECUTABLE_PATH="/path/to/msedge" TARGET_URL="https://example.com" node capture.mjs
On Linux containers, --no-sandbox is sometimes required when the process cannot create a sandbox. Apply it only when your runtime requires it and use the isolation controls provided by your deployment environment.
4. Useful launch and page options
| Option | Purpose | Guidance |
|---|---|---|
executablePath |
Selects the installed Edge binary. | Read it from configuration; verify it exists before launching. |
headless |
Runs without a visible window. | Use true for servers and CI. Use a visible mode while diagnosing local browser behavior. |
defaultViewport |
Sets width, height and device scale factor. | Set these explicitly for repeatable screenshots. |
args |
Passes Chromium command-line flags. | Add only flags required by your environment. |
waitUntil |
Controls when page.goto resolves. |
domcontentloaded is faster; networkidle2 waits for a quieter network. |
page.setDefaultNavigationTimeout |
Limits navigation time. | Choose a value that covers your slowest expected page without hanging workers. |
page.setDefaultTimeout |
Limits selectors and other waits. | Keep it separate from navigation timeout so a missing element fails quickly. |
page.setViewport |
Changes viewport per page. | Set it before navigation when responsive layout matters. |
page.screenshot |
Writes PNG, JPEG or other supported screenshot output. | Use fullPage: true for the complete scrollable document. |
Waiting for application state
Navigation completion does not guarantee that a single-page application has rendered its content. Wait for a stable selector or an application-specific condition:
await page.goto('https://example.com/app', { waitUntil: 'domcontentloaded' });
await page.waitForSelector('[data-testid="dashboard"]', { visible: true });
await page.screenshot({ path: 'dashboard.png' });
For delayed content, use a bounded delay only when you cannot identify a reliable selector:
await new Promise(resolve => setTimeout(resolve, 1500));
Capturing one element
const card = await page.waitForSelector('.report-card', { visible: true });
await card.screenshot({ path: 'report-card.png' });
PDF output
await page.pdf({
path: 'page.pdf',
format: 'A4',
printBackground: true,
margin: { top: ' margin-top: 16mm', right: '16mm', bottom: '16mm', left: '16mm' }
});
Use valid CSS length strings for margins, such as 16mm. Remove the accidental leading space if you copy the example above: top: '16mm'.
5. Edge channels, profiles and permissions
Stable, Beta, Dev and Canary are separate Edge installations. Point executablePath at the channel you intend to test, and record the browser version in CI logs. Avoid sharing a mutable user profile between parallel jobs; create an isolated temporary profile when a site depends on cookies, extensions or local storage.
Headless automation can fail because of file permissions, missing shared libraries, a locked profile or a policy that prevents launching child processes. Run the same executable as the service account, not only as your interactive desktop user.
6. Troubleshooting
| Error or symptom | Likely cause | Fix |
|---|---|---|
Failed to launch the browser process |
Wrong path, missing execute permission or missing system dependency. | Verify the path from edge://version, run it as the deployment user and inspect the first launch error. |
spawn ... ENOENT |
The executable path does not exist. | Check spelling, quoting and whether the selected Edge channel is installed. |
| Browser opens locally but not in CI | Different user, permissions, libraries or sandbox restrictions. | Install required OS dependencies, use a writable temporary directory and add --no-sandbox only if required. |
| Page is blank | Capture happened before client-side rendering, or navigation failed. | Check the response and console, wait for a real content selector and capture a diagnostic screenshot. |
Navigation timeout exceeded |
Slow page, blocked request or an overly strict timeout. | Increase the timeout deliberately, use a suitable waitUntil value and inspect failed requests. |
| Element not found | Selector changed, element is inside an iframe, or it appears later. | Wait for the selector, inspect frames and verify the selector in DevTools. |
| Different layout from a desktop browser | Viewport, device scale, media queries or fonts differ. | Set viewport and scale explicitly and install the fonts required by the page. |
| Unexpected login or consent screen | The page requires cookies, authentication or an interaction. | Supply a controlled profile or cookies, then wait for the post-login selector before capturing. |
| Protocol or API method errors | The installed Edge build and Puppeteer revision are not a tested combination. | Pin versions, reproduce with a minimal script and validate the pair before upgrading. |
For deeper diagnosis, enable browser process logging, listen for page.on('console'), page.on('pageerror') and page.on('requestfailed'), and save an HTML or screenshot artifact at the point of failure.
7. Performance, reliability and cost
- Reuse a browser: Launching Edge is expensive compared with opening a new page. Keep one browser per worker and create or close pages per job.
- Limit concurrency: Too many pages compete for CPU, memory and file descriptors. Start with a small worker pool and increase it while watching resource use.
- Use deterministic waits: A specific selector is usually faster and more reliable than a long fixed delay.
- Control network work: Block nonessential resources only when doing so cannot change the page you need to capture.
- Retry carefully: Retry transient launch or navigation failures with a limit and backoff. Do not retry invalid URLs or missing selectors indefinitely.
- Pin and test: Because an external Edge executable is outside Puppeteer’s compatibility guarantee, pin the Puppeteer package and Edge channel in production and run a smoke capture after upgrades.
- Budget infrastructure: Puppeteer itself does not charge per screenshot, but your compute, memory, storage, browser maintenance and proxy or network services still have operating costs.
8. Or skip the browser setup
If you only need a clean screenshot or PDF, ScreenshotNeo provides a hosted screenshot API. It accepts one GET request and returns PNG, JPEG, WebP or PDF. Cookie and consent banners are accepted and removed before capture, along with more than 60 known consent platforms, newsletter popups and chat widgets; each step can be disabled.
Only clean shots are billed. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads and cache hits cost nothing, and the response identifies the result with X-Page-Verdict and X-Billed headers. ScreenshotNeo also has an MCP server with take_screenshot, get_page_info and capture_pdf tools for Claude, Cursor and other MCP clients.
See the ScreenshotNeo API documentation for all options.
cURL
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(`Screenshot failed: ${res.status}`);
const data = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', data));
The Free plan includes 1,000 screenshots per month without a card. Paid plans start at $5 for 3,000 shots, and every feature is available on every plan. Create a free ScreenshotNeo account.
9. FAQ
Can Puppeteer launch Edge on macOS or Linux?
Yes, provided Edge is installed and you pass the executable path for that operating system. Confirm the path in Edge and validate the exact build in your environment.
Should I use puppeteer or puppeteer-core?
Use puppeteer-core when you supply an installed Edge executable. Use puppeteer when you want Puppeteer’s bundled browser workflow.
Is every Puppeteer feature guaranteed to work in Edge?
No. Edge uses the Chromium DevTools Protocol, but Puppeteer’s compatibility guarantee covers its bundled browser. Test features that matter to your application against the Edge version you deploy.
Can I use an Edge profile with extensions?
You can launch with a controlled profile, but avoid sharing one profile across parallel jobs. Profile locks, state leakage and extension side effects can make captures nondeterministic.
Where can I verify the API details?
Use Microsoft’s [Edge automation documentation](https://learn.microsoft.com/en-us/microsoft-edge/test-and-automation/test-and-automation), the [Puppeteer launch API](https://pptr.dev/api/puppeteer.launchoptions), and the [Puppeteer FAQ](https://pptr.dev/faq).


