ScreenshotNeo

BlogScreenshots on your device

How to Capture Screenshots in Python with MSS

Capture a whole display or a precise region with Python MSS, save PNGs, select monitors, and use screenshot pixels in image-processing code.

By the ScreenshotNeo team4 October 20268 min read

Use the MSS Python library to capture a physical display or a screen-coordinate region. For a simple PNG, open an MSS context and call sct.shot(); for a specific monitor or crop, call sct.grab(...) and save the returned screenshot object. The current documented entry point is from mss import MSS.

1. Install MSS and capture a PNG

Install the library into the same Python environment that will run your script:

python -m pip install mss

Save the primary monitor using the helper method:

from mss import MSS

with MSS() as sct:
    filename = sct.shot()
    print(f"Saved screenshot to {filename}")

shot() writes a PNG and returns its filename. The examples and API offer output naming and monitor selection options; for an explicit output name and selected monitor, use save():

from mss import MSS

with MSS() as sct:
    files = sct.save(mon=1, output="desktop-{mon}.png")
    for filename in files:
        print(filename)

The MSS examples use mon=1 for the first individual display. Its file helpers support filename placeholders such as {mon}, {width}, {height}, {left}, {top}, and {date}. Consult the MSS examples for the current helper behavior.

2. Choose the right monitor

sct.monitors is indexed with a special entry at zero: monitors[0] describes the combined virtual desktop spanning all attached displays. Individual monitors start at index 1. It is not correct to treat index zero as the first physical monitor.

from mss import MSS

with MSS() as sct:
    print("Available monitor geometry:")
    for number, monitor in enumerate(sct.monitors):
        print(number, monitor.left, monitor.top, monitor.width, monitor.height)

    primary = sct.primary_monitor
    image = sct.grab(primary)
    print("Captured", image.size.width, "x", image.size.height)

Use sct.primary_monitor when you mean the primary display. Use sct.monitors[n] when you need a particular enumerated display. A monitor exposes geometry through left, top, width, and height attributes. Do not assume a secondary display starts at coordinate (0, 0); it may be positioned left of or above the primary display and therefore have a negative offset.

Save every display as separate PNGs with:

from mss import MSS

with MSS() as sct:
    for filename in sct.save(mon=0, output="monitor-{mon}.png"):
        print(filename)

The helper’s monitor numbering is documented separately from grab(): save(mon=0) saves each monitor, while save(mon=-1) requests the entire virtual screen. For explicit single-monitor captures, prefer sct.grab(sct.monitors[n]) or inspect the current API documentation.

3. Capture only part of the screen

A crop uses desktop screen coordinates, not coordinates relative to the selected window. A Region consists of left, top, width, and height. Capture and write it as a PNG like this:

import mss.tools
from mss import MSS
from mss.models import Region

region = Region(left=160, top=160, width=320, height=240)

with MSS() as sct:
    image = sct.grab(region)
    mss.tools.to_png(image.rgb, image.size, output="region.png")

You can also use the familiar Pillow-style bounding box, (left, top, right, bottom). The right and bottom values are edges; convert to width and height by subtracting the left and top.

import mss.tools
from mss import MSS

with MSS() as sct:
    monitor = sct.primary_monitor
    left = monitor.left + 100
    top = monitor.top + 80
    right = left + 640
    bottom = top + 360

    image = sct.grab((left, top, right, bottom))
    mss.tools.to_png(image.rgb, image.size, output="crop.png")

To make a crop relative to a secondary display, add its left and top offsets before applying the local crop offset:

from mss import MSS
from mss.models import Region

with MSS() as sct:
    monitor = sct.monitors[2]
    crop = Region(
        left=monitor.left + 50,
        top=monitor.top + 50,
        width=400,
        height=300,
    )
    image = sct.grab(crop)
    image.to_pil().save("secondary-crop.png")

Make sure the requested rectangle lies within the available desktop geometry. Out-of-range coordinates, unusual display layouts, rotations, and remote display environments can produce errors or results that differ from the intended crop.

4. Work with image data or change output format

grab() returns an MSS ScreenShot object. Its to_pil() method creates a Pillow image suitable for editing and saving in other formats:

from mss import MSS

with MSS() as sct:
    screenshot = sct.grab(sct.primary_monitor)
    image = screenshot.to_pil()
    image.save("desktop.jpg", quality=90)

You can save PNG bytes without asking the helper to write a file, which is useful when sending the image to another API or storage layer:

import mss.tools
from mss import MSS

with MSS() as sct:
    screenshot = sct.grab(sct.primary_monitor)
    png_bytes = mss.tools.to_png(screenshot.rgb, screenshot.size)

# Example: write the bytes later
with open("desktop.png", "wb") as output:
    output.write(png_bytes)

The MSS documentation also exposes conversion helpers such as to_numpy() for NumPy and integrations for other image frameworks. Use the representation your next processing step expects. A PNG encoding creates output bytes; for repeated pixel analysis, retaining a screenshot buffer or using a compatible buffer-based workflow can avoid unnecessary conversions. Note that rgb is a computed view of the raw pixels, while bgra exposes the raw channel order.

5. Reuse MSS in scripts and applications

Use the context manager so the capture object is closed cleanly when the block exits. For repeated captures, keep one MSS instance open around the capture loop rather than repeatedly setting up the capture backend:

from mss import MSS

with MSS() as sct:
    monitor = sct.primary_monitor
    for index in range(3):
        frame = sct.grab(monitor)
        frame.to_pil().save(f"frame-{index}.png")

This example shows the lifecycle, not a measured throughput claim. Capturing large displays at high frequency moves substantial pixel data and can make encoding, disk writes, and downstream processing the limiting work. Capture only the region you need, avoid conversions if the next library can use the available buffer, and benchmark the full application on its target machine.

For multiprocessing or threaded applications, follow the library’s current guidance for the target OS and capture backend. A screenshot object and its underlying data should not be assumed safe to mutate concurrently. Treat captured pixels as sensitive: they may include private information visible on screen, so limit access, retention, and upload.

6. Linux, remote, and headless environments

MSS documents xshmgetimage as its Linux default backend and describes fallback to xgetimage when MIT-SHM is unavailable, such as with some remote SSH displays. The project also lists xlib as a legacy backend. This does not mean every headless server or Wayland setup has a capturable display: verify that the process has access to the display environment required by your deployment.

Check the current MSS usage documentation for platform specifics and backend options. If your goal is to capture a website rendered in a browser rather than the desktop’s visible pixels, use a browser automation tool or a website screenshot API instead; a desktop capture library does not navigate to a URL on its own.

7. Or skip the browser setup

MSS captures the display your Python process can access. For a website URL, ScreenshotNeo returns an image or PDF from one GET request. See the ScreenshotNeo API documentation.

import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
open("shot.webp", "wb").write(r.content)

Cookie banners are accepted and removed before capture, along with known newsletter popups and chat widgets; each step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and the response identifies page verdict and billing status in headers. An MCP server lets AI agents use screenshot and PDF capture tools. The free plan includes 1,000 screenshots each month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.

8. Troubleshooting

Symptom Likely cause What to do
ModuleNotFoundError: No module named 'mss' MSS was installed into a different Python environment. Run python -m pip install mss with the same interpreter used to launch the script.
No display or capture backend error The process cannot access a graphical display, or the OS/backend setup is unavailable. Run where a display is available and check the MSS platform requirements. On Linux, inspect X11/Wayland and remote-session access rather than assuming a headless process has a desktop.
The wrong monitor is captured Index zero was treated as a physical display, or monitor ordering was assumed. Print sct.monitors geometry, choose an individual index starting at 1, or use sct.primary_monitor.
The crop is offset or empty Coordinates were treated as monitor-relative, or the monitor has a nonzero/negative origin. Add the selected monitor’s left and top offsets. Check whether values are a width/height region or a right/bottom bounding box.
PNG helper receives unexpected data The dimensions or pixel representation do not match the helper arguments. Pass screenshot.rgb and screenshot.size to mss.tools.to_png(), or call screenshot.to_pil().save(...).
Image looks different across systems Display scaling, rotation, color representation, and platform capture behavior vary. Inspect returned dimensions and monitor geometry on the target environment; do not hard-code assumptions from another machine.
Repeated capture slows down Large frames, encoding, conversions, or disk writes dominate. Reduce the captured region or frequency, reuse the MSS context, and avoid converting to multiple representations unnecessarily.

9. MSS options and practical choices

Need Use
Save a straightforward PNG sct.shot() or sct.save()
Capture one display or exact coordinates sct.grab(monitor) or sct.grab(region)
Get a Pillow image for manipulation screenshot.to_pil()
Use pixel buffers in analysis code Use the screenshot buffer or a documented array conversion such as to_numpy()
Choose CLI monitor, coordinates, output, compression, cursor, or backend Run python -m mss --help and use the documented CLI flags

The MSS command-line interface includes monitor and coordinate selection, output filename, PNG compression level, optional cursor inclusion, backend selection, quiet mode, and version display. The Python API also exposes PNG compression configuration. Use the official API and examples for details that depend on the installed MSS version.

MSS examples document both file and buffer workflows. The library uses PNG for its direct screenshot helper; convert through Pillow when another file format is required.

10. MSS versus Pillow ImageGrab

Choose based on the interface and environment you need. MSS provides monitor enumeration, region capture, and screenshot buffers; Pillow’s ImageGrab.grab() returns a Pillow image directly and accepts a bbox. Pillow documents RGB output on most platforms and RGBA on macOS, plus Retina behavior and Linux screenshot-tool fallbacks. Check the official Pillow ImageGrab documentation for the platform details. Neither interface is universally the right choice for every display setup.

11. Frequently asked questions

Can MSS capture a browser page by URL?

No. MSS captures visible display pixels. To render a URL, use browser automation or a screenshot service such as ScreenshotNeo.

Does MSS include the mouse cursor?

The CLI documents an optional --with-cursor flag. For other cursor requirements, check the API behavior for your MSS version and platform.

Can I save the result as JPEG?

Yes. Convert with to_pil() and call Pillow’s save() with a JPEG filename and desired quality.

What does monitors[0] mean?

It is the aggregate virtual desktop geometry. Individual displays begin at index 1.

Does capturing a region use window coordinates?

No. MSS region coordinates refer to the desktop coordinate space. Add the monitor’s origin when calculating a crop relative to a non-primary monitor.