Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Use Selenium’s driver.get_screenshot_as_png(), then wrap the returned PNG bytes with NumPy:
import numpy as np
png_bytes = driver.get_screenshot_as_png()
png_byte_array = np.frombuffer(png_bytes, dtype=np.uint8)
This produces a one-dimensional NumPy array containing the encoded PNG file. It is not a height-by-width (or height-by-width-by-channels) matrix of image pixels. If you need pixels for computer-vision or image analysis, decode the PNG first and convert the decoded image to NumPy.
What the two lines actually return
Selenium’s Python WebDriver exposes get_screenshot_as_png() as an in-memory capture method. It returns Python bytes containing a PNG image; Selenium obtains the screenshot response and decodes it from base64 before returning those bytes. See the Selenium WebDriver API documentation and its implementation.
numpy.frombuffer interprets that buffer as a one-dimensional array. With dtype=np.uint8, each element is one unsigned byte from the PNG stream. NumPy’s frombuffer reference documents this buffer interpretation and notes that the result is a view where possible.
#1 Best Overall
| Representation | How to obtain it | What it is useful for |
|---|---|---|
| PNG bytes | driver.get_screenshot_as_png() |
Writing a file, uploading, hashing, or sending through an API |
| One-dimensional NumPy byte array | np.frombuffer(png_bytes, dtype=np.uint8) |
Byte-level processing or libraries that accept NumPy buffers |
| Decoded pixel array | Decode the PNG with an image decoder, then convert the decoded image to NumPy | Image analysis, computer vision, channel or color operations |
| PNG file on disk | driver.save_screenshot(path) or driver.get_screenshot_as_file(path) |
Persistent files and tools that expect a filename |
Complete in-memory example
The following script opens a page, captures the current browser viewport, and creates a NumPy array of the encoded PNG bytes. Install Selenium and NumPy in the environment used to run the script, and provide a WebDriver compatible with your browser.
import numpy as np
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
# Uncomment this on a machine without a graphical display.
# options.add_argument("--headless")
with webdriver.Chrome(options=options) as driver:
driver.set_window_size(1280, 900)
driver.get("https://example.com")
png_bytes = driver.get_screenshot_as_png()
png_byte_array = np.frombuffer(png_bytes, dtype=np.uint8)
print(type(png_bytes).__name__) # bytes
print(png_byte_array.dtype) # uint8
print(png_byte_array.ndim) # 1
print(png_byte_array.shape) # (number of PNG bytes,)
# The same encoded image can be persisted without decoding it.
with open("example.png", "wb") as image_file:
image_file.write(png_bytes)
The exact array length depends on the page, viewport, browser, device scale factor, and PNG compression. It is not the number of pixels. A screenshot that is 1280 pixels wide does not produce an array with shape (1280, ...) at this stage.
Capture the right browser state
Navigate before capturing
WebDriver captures the current browser state. Call get(), perform any login or interaction, and wait for content that is rendered asynchronously before calling the screenshot method. A screenshot taken immediately after navigation can contain a loading state.
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
with webdriver.Chrome(options=options) as driver:
driver.get("https://example.com/dashboard")
WebDriverWait(driver, 20).until(
lambda d: d.find_element(By.CSS_SELECTOR, "main.dashboard")
)
png_bytes = driver.get_screenshot_as_png()
png_byte_array = np.frombuffer(png_bytes, dtype=np.uint8)
Choose a condition that represents the page being ready rather than relying on a fixed sleep. If the site changes its markup, update the selector or readiness condition.
Viewport versus full page
The standard WebDriver screenshot method captures the current browser window or viewport according to the driver and browser implementation. Setting the window size makes captures more repeatable:
driver.set_window_size(1440, 1000)
Full-page behavior varies by browser and driver. If a full document image is required, use the capabilities documented for the specific browser/driver or capture and stitch sections yourself; do not assume that a viewport screenshot is a full-page screenshot.
Frames and windows
WebDriver captures the top-level browser view, not an isolated frame as a separate image. Switch to the desired window and, when interacting with an iframe, switch into the frame before locating elements. Switch back to the default content before continuing with page-level operations.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Rank #2
Saving, base64, and byte-array workflows
Write the PNG directly
save_screenshot(path) and get_screenshot_as_file(path) write a PNG file and return True when the save succeeds or False on an I/O error. Selenium expects a filename ending in .png and warns when it does not. Check the return value when the path may be missing, unwritable, or on a disconnected volume.
ok = driver.save_screenshot("artifacts/checkout.png")
if not ok:
raise OSError("Selenium could not save the screenshot")
Use get_screenshot_as_png() instead when you already need bytes. It avoids a needless disk round trip and lets you upload or transform the data in memory.
Use base64 only when a string is required
get_screenshot_as_base64() returns a base64-encoded string, documented as useful for embedding an image in HTML. It is not the same representation as a PNG byte array. Decode the string before passing it to a byte-buffer workflow; prefer get_screenshot_as_png() when your next function accepts bytes.
import base64
encoded = driver.get_screenshot_as_base64()
png_bytes = base64.b64decode(encoded)
png_byte_array = np.frombuffer(png_bytes, dtype=np.uint8)
Turning the PNG into actual pixels
A PNG is a compressed file format. The one-dimensional array created with frombuffer contains the file signature, chunks, metadata, and compressed image data. Indexing it does not reveal a pixel’s red, green, or blue value.
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minutePC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11For pixel work, use a PNG decoder supported by your project, obtain its decoded image object or raw pixel buffer, and then construct a NumPy array from that decoded data. The resulting shape is commonly two-dimensional for grayscale or three-dimensional for color, but the channel order, alpha handling, and data type depend on the decoder and image. Verify those details against the decoder version you deploy.
- Keep the original
png_bytesif you need to upload or archive the exact screenshot. - Keep the encoded byte array separate from the decoded pixel array so later code cannot confuse the two.
- Inspect dimensions and channels after decoding rather than assuming RGB, RGBA, or a particular bit depth.
- If a decoder returns a mutable buffer and you will mutate it, make an explicit copy where appropriate.
Understanding frombuffer views and copies
NumPy can create a view into the input buffer instead of copying every byte. That is efficient for a screenshot that you only inspect or pass onward. NumPy also advises considering a copy for mutable or untrusted buffers. If downstream code must own an independent, writable array, request one explicitly:
png_byte_array = np.frombuffer(png_bytes, dtype=np.uint8)
owned_byte_array = png_byte_array.copy()
The copy is still an array of encoded PNG bytes. It does not decode the image.
Common mistakes and fixes
Calling a nonexistent pixel API
Symptom: Code expects get_screenshot_as_png() to return a two-dimensional image.
Free tools Windows power users keep installed
One-click scans. No signup required.
Fix: Treat the result as bytes. Wrap it with np.frombuffer(..., dtype=np.uint8) for encoded-byte operations, or decode it first for pixels.
Passing a file path to frombuffer
Symptom: The array contains characters from a path or the call raises a type error.
Fix: Read the file in binary mode, or capture directly with get_screenshot_as_png():
with open("example.png", "rb") as image_file:
png_bytes = image_file.read()
byte_array = np.frombuffer(png_bytes, dtype=np.uint8)
Unexpected shape
Symptom: array.shape is a single tuple such as (48231,).
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Fix: That is the expected shape for encoded bytes. Decode the PNG before converting to a pixel array.
Empty, stale, or partially rendered captures
Symptom: The PNG is valid but shows a spinner, blank content, or a previous state.
Fix: Wait for a meaningful element, complete authentication and interactions, and confirm you are in the intended window and frame. A fixed delay alone is less reliable than an explicit readiness condition.
Save returns False
Symptom: Selenium does not create the requested file.
Fix: Verify the directory exists, the process can write there, the filename ends in .png, and the storage volume is available. For diagnostics, capture in memory and write with Python so you can inspect the resulting exception.
Driver or browser startup failure
Symptom: The script fails before reaching the screenshot call.
Fix: Confirm that the browser, WebDriver, Selenium package, and driver-compatible versions are installed for the execution environment. In headless containers, configure the browser’s headless and sandbox settings according to that environment; screenshot conversion cannot repair a driver that never starts.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Performance, reliability, and cost considerations
In-memory capture avoids disk I/O, which is useful for pipelines that upload screenshots or process many pages. The PNG itself is compressed, so its byte length varies with visual complexity. Large pages, high-density displays, and large viewport dimensions increase capture time and memory use.
For repeatable automation, fix the viewport, browser version, device scale factor, locale, and logged-in state where possible. Wait for deterministic page conditions, and retain the original bytes when a later investigation may need to reproduce exactly what WebDriver returned. If you capture many pages, release each driver or reuse a controlled session rather than creating unbounded browser processes.
Best Value
Neither Selenium nor NumPy charges per screenshot; your practical costs are browser-process resources, storage, network transfer, and any external service used to render pages. The Selenium documentation currently surfaced for this method is the Selenium 4.49.0 API material. The buffer reference linked above is the NumPy 2.1 page; the NumPy reference landing page identifies the current manual as NumPy 2.5, dated June 28, 2026. Check the versions installed in your environment before relying on behavior outside the stable method and buffer semantics described here.
Or skip the browser setup
If you only need a rendered website image rather than an interactive WebDriver session, ScreenshotNeo returns a screenshot from one HTTP request. Its cleanup step accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each cleanup step can be disabled. 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. ScreenshotNeo also provides an MCP server with take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.
Use the API documentation at screenshotneo.com/docs/ for the available options. A minimal cURL call is:
Recommended Free Tools
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
The same request in 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)
And in 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}`);
Every plan includes the features: full-page capture with lazy images loaded, CSS-selector element capture, dark mode, device presets and custom viewports, retina scale, PDF controls, HTML/CSS-to-image, custom CSS and JavaScript, pre-capture clicks, hidden selectors, selector/delay/network-idle waits, request and resource blocking, custom headers, cookies, user agent and Authorization, timezone and geolocation, transparent backgrounds, resizing, chosen cache TTLs, signed image links, asynchronous jobs with signed webhooks, bulk capture for up to 100 URLs per call, a usage API, an OpenAPI specification, and compatibility with the parameter names used by other screenshot APIs.
The Free plan includes 1,000 shots per month with no card. Paid plans start at $5 for 3,000 shots; yearly billing gives two months free. Create a free ScreenshotNeo account to try the 1,000 monthly shots without a card.
Frequently Asked Questions
Does np.frombuffer decompress the screenshot?
No. It exposes the PNG file’s existing bytes as a one-dimensional uint8 array. A separate image-decoding step is required for pixel values.
Can I modify the returned byte array and change the screenshot?
Modifying an array of PNG bytes does not edit pixels; it changes a compressed file stream and will usually make it invalid. Decode the image for pixel edits, then encode it again.
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 minuteWhich Selenium method is best when I need bytes immediately?
Use get_screenshot_as_png(). It returns bytes directly, whereas the base64 method returns a string and the file methods write to disk.
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.

