Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Repair Windows errors before they cause bigger problems3Scan for outdated or missing drivers - takes under a minuteSome links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
In Selenium WebDriver for JavaScript, call await driver.takeScreenshot(). Selenium returns a Base64-encoded PNG for the current browsing context; write it with Node.js’s base64 encoding to create a normal .png file. To capture one element instead, locate it and call await element.takeScreenshot(true).
Prerequisites and installation
Use a supported Node.js installation and a browser driver that Selenium can start. The current official JavaScript API page lists Node.js 22 or newer. Create or open your project, then install the Selenium binding:
npm install selenium-webdriver
The examples below use Chrome, Node’s built-in file-system module, and an immediately invoked async function so the browser is always closed in a finally block. Change the URL and browser configuration to match your WebDriver environment.
Free tools Windows power users keep installed
One-click scans. No signup required.
Capture the current page or browsing context
driver.takeScreenshot() captures the current page and resolves to a Base64-encoded PNG string. Selenium documents a best-effort preference order: the entire page, the current window, the visible portion of the current frame, and finally the entire display containing the browser. The exact result therefore depends on the browser and driver rather than being a promise that every page will become one infinite image.
#1 Best Overall
Complete JavaScript example
const { Builder, Browser } = require('selenium-webdriver');
const fs = require('node:fs');
(async function saveScreenshot() {
const driver = await new Builder().forBrowser(Browser.CHROME).build();
try {
await driver.get('https://example.com');
const encoded = await driver.takeScreenshot();
fs.writeFileSync('./screenshot.png', encoded, 'base64');
console.log('Saved ./screenshot.png');
} finally {
await driver.quit();
}
})();
Run the file with node screenshot.js. The resulting file is binary PNG data. Do not write the returned value as UTF-8 text: that would save the Base64 characters rather than decode them into an image.
What Selenium actually returns
- The value is a string containing PNG data encoded with Base64.
- It does not include a
data:image/png;base64,URL prefix. fs.writeFileSync(path, encoded, 'base64')decodes the string while writing the file.- The screenshot is taken from the current browsing context. Navigate, switch windows, or switch frames first if that is where the content you need lives.
Capture one element instead of the whole page
Find the target element, then call its screenshot method. Passing true requests the element screenshot behavior shown in Selenium’s JavaScript browser/windows example.
Runnable element-screenshot script
const { Builder, Browser, By } = require('selenium-webdriver');
const fs = require('node:fs');
(async function saveElementScreenshot() {
const driver = await new Builder().forBrowser(Browser.CHROME).build();
try {
await driver.get('https://example.com');
const heading = await driver.findElement(By.css('h1'));
const encoded = await heading.takeScreenshot(true);
fs.writeFileSync('./heading.png', encoded, 'base64');
console.log('Saved ./heading.png');
} finally {
await driver.quit();
}
})();
Use a selector that identifies the element you need. If findElement cannot match it, Selenium raises an error before any image is written. If the page creates the element after navigation, wait for it to exist before calling takeScreenshot.
Rank #2
Choose the right capture scope
| Goal | Call | Result and considerations |
|---|---|---|
| Page or current browsing context | await driver.takeScreenshot() |
Base64 PNG. Selenium tries, in order, the entire page, current window, visible current frame, then the display containing the browser. |
| One located element | await element.takeScreenshot(true) |
Base64 PNG focused on that element; the element must be found in the active context first. |
| Save either result | fs.writeFileSync(file, encoded, 'base64') |
Decodes the Base64 string into a binary PNG file. |
| Remote execution | Use a remote Builder configuration |
The capture runs in the browser session managed by the remote Selenium server; the API and Base64 handling remain the same. |
Frames, windows, and timing
Capture content inside an iframe
A screenshot call uses the current browsing context. If the desired element is inside an iframe, switch into that frame before locating it. Afterward, switch back if later steps belong to the top-level document.
const frame = await driver.findElement(By.css('iframe'));
await driver.switchTo().frame(frame);
const chart = await driver.findElement(By.css('.chart'));
const encoded = await chart.takeScreenshot(true);
fs.writeFileSync('./chart.png', encoded, 'base64');
await driver.switchTo().defaultContent();
Capture a newly opened window
When a click opens another tab or window, switch the driver to that window handle before calling takeScreenshot. Otherwise Selenium captures whichever window is still current.
Wait for the visual state you need
driver.get navigates before the screenshot call, but applications can continue rendering afterward. For dynamic pages, wait for a distinctive element or state, then capture. This is especially important for element screenshots: locating an element too early can produce a missing-element error, while capturing during an animation can produce an intermediate image.
Rank #3
Local browser versus remote Selenium
The screenshot API is the same in both deployments. With a local builder, the PNG is produced by the browser on the machine running your Node process. With a remote Selenium server, the browser session is elsewhere and the returned Base64 string travels back to your process, where you decode and save it. Remote execution is useful for centralized browser infrastructure, but network latency and the server’s browser/display configuration can affect completion time and the visible result.
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 →Common failures and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
Cannot find module 'selenium-webdriver' |
The package is not installed in the project whose script you are running. | Run npm install selenium-webdriver in that project and run the script from the same directory. |
| Browser cannot be started | No compatible browser/driver setup or an invalid builder configuration. | Confirm the browser is installed, use the correct Browser value, and check the WebDriver server or driver configuration used by your environment. |
StaleElementReferenceError |
The page replaced the element after you located it. | Wait for the final state, locate the element again, and then call takeScreenshot. |
NoSuchElementError |
The selector is wrong, the element is in another frame, or it has not rendered yet. | Verify the CSS selector, switch into the correct iframe, and wait for the element before locating it. |
| The image file is unreadable | The Base64 string was written as text or altered before saving. | Pass 'base64' as the third argument to fs.writeFileSync; do not add a data-URL prefix. |
| Only part of the page appears | The driver fell back to a current-window or visible-frame capture; full-page support is best effort. | Check the browser/driver combination, capture the specific element you need, or use a service designed for consistent full-page rendering. |
| Screenshot is from the wrong tab or frame | The driver remained in a different current window or browsing context. | Switch to the intended window handle and frame before capturing. |
| Browser remains running after an error | The script did not close the session on every path. | Keep await driver.quit() in finally, as in the examples. |
Make captures reliable in automation
- Use deterministic selectors for element captures rather than brittle positional selectors.
- Capture after the page reaches the state your test is asserting; a screenshot is evidence of that moment, not a substitute for synchronization.
- Keep navigation, frame switching, element lookup, capture, and file writing in explicit steps so a failed stage is easy to identify.
- Use unique filenames when a suite captures multiple states, or later files will overwrite earlier ones.
- On remote sessions, account for the time needed to transfer the Base64 response and write the file.
- Remember that Selenium’s full-page result is implementation-dependent. If your requirement is a predictable, clean site image rather than a test artifact from a live browser, an API can be simpler.
Or skip the browser setup
ScreenshotNeo provides a website screenshot API and MCP server for developers. One GET request returns PNG, JPEG, WebP, or PDF output. Before capture it accepts cookie or consent banners like a visitor 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 cost nothing, and response headers identify the page verdict and whether the request was billed. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.
See the ScreenshotNeo documentation for all request options. A one-call capture with cURL is:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
Equivalent Node.js code is:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
const file = Buffer.from(await res.arrayBuffer());
require('node:fs').writeFileSync('shot.webp', file);
Python:
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)
ScreenshotNeo has 63 options, including full-page capture with lazy images loaded, CSS-selector element capture, dark mode, 12 device presets plus custom viewports, retina scale, PDF paper and page controls, custom CSS and JavaScript, pre-capture clicks, hidden selectors, waits for a selector, delay or network idle, ad/tracker/request/resource blocking, custom headers, cookies, user agent and Authorization, timezone and geolocation, transparent backgrounds, resizing, configurable-TTL caching, signed image links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, a usage API, an OpenAPI specification, and compatibility with parameter names used by other screenshot APIs.
| Plan | Included shots | Price |
|---|---|---|
| Free | 1,000 per month | No card required |
| Starter | 3,000 | $5 |
| Growth | 15,000 | $15 |
| Pro | 60,000 | $39 |
| Scale | 250,000 | $99 |
| Business | 1,000,000 | $249 |
Every feature is on every plan, and yearly billing provides two months free. Start with 1,000 free screenshots a month; no card is required.
When to use Selenium versus an API
- Use Selenium when the screenshot is part of a browser test, must follow clicks and application state, or needs the same session your test is already controlling.
- Use an API when you need repeatable URL-to-image jobs without installing or maintaining browser drivers, especially for batch captures, PDFs, cleanup of consent UI, or AI-agent workflows.
- Use an element screenshot when the artifact should contain one component, assertion target, chart, or heading rather than the whole browsing context.
Frequently Asked Questions
Does Selenium return a PNG or a Base64 string?
It returns a Base64-encoded PNG string. Decode it while writing with Node’s 'base64' file-writing option to produce a PNG.
Can I capture only one DOM element?
Yes. Locate it with findElement and call await element.takeScreenshot(true), then save the returned Base64 string.
Best Value
Is Selenium’s full-page screenshot guaranteed to include the entire document?
No. Selenium documents a best-effort order that can fall back to the current window, visible frame, or display. Browser and driver behavior determine the final scope.
Can the same screenshot code run against a remote Selenium server?
Yes. Configure a remote WebDriver session; the screenshot call still returns Base64 data that your Node process can decode and save.
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.

