Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

For 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_bytes if 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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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,).

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.Support on Ko-Fi

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

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:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Which 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.

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.