Recommended Free Tools
Install Pillow and pyscreenshot, call pyscreenshot.grab(), then save the returned Pillow image. Use grab(bbox=(left, top, right, bottom)) for a rectangle. The API is small, but capture also depends on an operating-system backend and your desktop session. The project’s current README says pyscreenshot is obsolete for most uses because Pillow’s ImageGrab now works on Windows, macOS, and Linux; pyscreenshot remains useful when you need backend selection, certain Wayland routes, subprocess isolation, or a backend that behaves better on a particular machine.
Install pyscreenshot and its image dependency
Create or activate the Python environment that will run the capture, then install both packages:
python3 -m pip install Pillow pyscreenshot
The README lists Python 3.9, 3.10, and 3.11 as supported versions. PyPI currently shows pyscreenshot 3.1 (the release file was uploaded on March 12, 2023); its metadata also advertises a broad Python >=3.4 requirement, which is not the same as the narrower, currently listed tested versions. Check the package metadata for your interpreter before deploying.
Installing the wrapper does not install every possible capture engine. pyscreenshot can use Pillow, MSS, desktop D-Bus services, or command-line programs such as scrot, maim, ImageMagick, Grim, and platform screenshot tools. A missing or unusable backend is the most common reason that installation succeeds but capture fails.
Free tools Windows power users keep installed
One-click scans. No signup required.
#1 Best Overall
Capture the entire screen
The documented interface aliases pyscreenshot to ImageGrab, making the call resemble Pillow’s API:
import pyscreenshot as ImageGrab
im = ImageGrab.grab()
im.save("screenshot.png")
grab() returns an image object held in Pillow memory. The save() method chooses the output format from the filename extension in common cases, so .png, .jpg, and .webp are convenient choices. Questions about image conversion, color modes, and Pillow file handling belong to Pillow’s documentation.
Use an absolute output path when running from a scheduler or service, and make sure the process has permission to create the destination directory. The capture is non-interactive: the project says the mouse pointer is not visible.
Capture a selected rectangle
Pass a four-number bounding box in the form (left, top, right, bottom):
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
import pyscreenshot as ImageGrab
im = ImageGrab.grab(bbox=(10, 10, 510, 510))
im.save("region.png")
The first pair is the upper-left corner and the second pair is the lower-right corner, in desktop coordinates. For a 500-pixel-wide region beginning at x 10, use right = 510. Coordinates are supplied by the operating system; multi-monitor arrangements can therefore include negative values or a virtual desktop whose origin is not the primary display’s upper-left corner.
Validate coordinates before calling the API when they come from user input. A practical helper keeps the rectangle ordered and rejects an empty area:
Rank #2
import pyscreenshot as ImageGrab
def capture_box(box, filename):
left, top, right, bottom = box
if right <= left or bottom <= top:
raise ValueError("right and bottom must be greater than left and top")
image = ImageGrab.grab(bbox=(left, top, right, bottom))
image.save(filename)
capture_box((10, 10, 510, 510), "region.png")
Choose a backend deliberately
When the default route does not work, force a backend that is installed and appropriate for the current desktop:
import pyscreenshot as ImageGrab
image = ImageGrab.grab(backend="scrot")
image.save("scrot-shot.png")
The backend name is not an automatic installer. For example, selecting scrot requires the scrot executable to be present and discoverable in PATH. The README lists integrations for Pillow, MSS, xdg-desktop-portal Screenshot, GNOME Shell Screenshot, scrot, maim, ImageMagick, PyQt5, PySide2, wxPython, Grim, Quartz, and macOS screencapture. Availability and behavior vary by operating system, desktop, and session type.
pyscreenshot also documents an MSS route with subprocess execution disabled:
import pyscreenshot as ImageGrab
image = ImageGrab.grab(backend="mss", childprocess=False)
image.save("mss-shot.png")
The project describes subprocess mode as safer isolation. Turning it off can improve speed in some environments, but it removes that isolation and may expose the main process to backend problems. Treat this as a measured optimization, not a default setting.
Wayland, X11, and desktop-session behavior
Wayland capture is compositor- and portal-dependent. The project documents three routes:
- xdg-desktop-portal: D-Bus
org.freedesktop.portal.Screenshoton desktops that provide the portal. - GNOME: D-Bus
org.gnome.Shell.Screenshot. - wlroots compositors: Grim through
wlr-screencopy-unstable-v1; the README specifically says this works with Sway, not GNOME or KDE.
If both Wayland and X are available, the project prefers Wayland because Xwayland cannot be used for screenshot capture. Portal security can display a confirmation dialog, so an unattended job may stop waiting for user approval. KDE Wayland may show a notification, and GNOME may show a screenshot flash. These effects are desktop behavior, not image content that pyscreenshot can universally suppress.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Interactive selection is not supported by the project’s general interface. If you need a user to drag a rectangle, obtain the coordinates with a separate desktop tool or GUI and then pass them as bbox.
pyscreenshot or Pillow ImageGrab?
The maintainers’ current guidance begins with “TL;DR: Use Pillow.” Pillow’s ImageGrab now supports Linux and macOS as well as Windows, so it is normally the simpler direct dependency. pyscreenshot is worth keeping when one of its backend choices solves a concrete problem.
| Decision point | Prefer Pillow ImageGrab when… | Prefer pyscreenshot when… |
|---|---|---|
| API simplicity | You want the shortest dependency chain and direct Pillow interface. | You want one wrapper API while trying different capture engines. |
| Wayland | Your Pillow route works in the target compositor. | You need the documented portal, GNOME Shell, or Grim route. |
| Backend choice | The built-in route is reliable on every deployment. | You must select MSS, scrot, maim, ImageMagick, or another listed integration. |
| Process isolation | A single in-process call is acceptable. | You value optional subprocess isolation or need to compare isolated and in-process routes. |
| Speed | Your measured capture time is already adequate. | A benchmark on your own machine shows a backend setting is faster. |
There is no universal speed winner. The README’s sample timings were measured on Ubuntu 22.04 X11 with pyscreenshot 3.1, Pillow 9.0.1, MSS 7.0.1, and specific subprocess settings; they are not a current cross-platform benchmark. Measure the backend and settings you will actually deploy.
Make captures repeatable in a script
A small command-line program makes paths, regions, and backend choices explicit:
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errors#!/usr/bin/env python3
import argparse
from pathlib import Path
import pyscreenshot as ImageGrab
parser = argparse.ArgumentParser()
parser.add_argument("output", type=Path)
parser.add_argument("--bbox", nargs=4, type=int, metavar=("LEFT", "TOP", "RIGHT", "BOTTOM"))
parser.add_argument("--backend")
args = parser.parse_args()
kwargs = {}
if args.bbox:
left, top, right, bottom = args.bbox
if right <= left or bottom <= top:
parser.error("RIGHT must exceed LEFT and BOTTOM must exceed TOP")
kwargs["bbox"] = (left, top, right, bottom)
if args.backend:
kwargs["backend"] = args.backend
image = ImageGrab.grab(**kwargs)
args.output.parent.mkdir(parents=True, exist_ok=True)
image.save(args.output)
print(f"saved {args.output}")
Examples:
python capture.py full.png
python capture.py panel.png --bbox 0 0 900 700
python capture.py shot.png --backend scrot
For a service, log the selected backend, session type (X11 or Wayland), output path, and exception text. Do not silently retry indefinitely: a portal prompt or unavailable display usually requires an environment fix rather than more retries.
Troubleshooting common failures
“No backend” or executable-not-found errors
Install the operating-system utility named by the backend, or remove the forced backend= argument and test the default. Confirm the executable is on the same user’s PATH as the Python process. In containers and minimal servers, no graphical capture service may exist at all.
Works in a terminal but fails from cron, SSH, or systemd
Those contexts often lack DISPLAY, Wayland session variables, D-Bus access, or permission to connect to the desktop. Run the job inside the logged-in graphical session, pass only the required environment deliberately, and verify that the target user owns the display connection. A headless server cannot capture a physical desktop that is not running.
Wayland shows a dialog or hangs
The portal may require confirmation. Use a compositor-supported non-interactive route such as the documented Grim path where applicable, or run the capture where a user can approve the request. Grim is documented for Sway, not GNOME or KDE.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →The image is black, partial, or from the wrong monitor
Check the session type, monitor geometry, and coordinates. Try another available backend, and test a full-screen capture before a bbox. Negative coordinates can be valid on a multi-monitor virtual desktop.
Capture is too slow
Benchmark the default and a backend such as MSS on the actual machine. The project suggests testing available settings; disabling child processes may improve speed but trades away isolation. Avoid presenting a README timing as a guarantee.
The output file is missing or has the wrong format
Use an absolute writable path and a recognized extension. Ensure the process reaches save(); print or log the destination after saving. Pillow performs the image encoding, so format-specific errors originate there rather than in coordinate capture.
Or skip the browser setup
If your real goal is a webpage image rather than the physical desktop, ScreenshotNeo provides a website screenshot API. One GET request returns PNG, JPEG, WebP, or PDF; it is not dependent on your local X11 or Wayland session.
Best Value
Python:
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)
cURL:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
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}`);
See the ScreenshotNeo documentation for parameters and response headers. Before capture it accepts cookie/consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the page verdict and billing status with X-Page-Verdict and X-Billed headers. An MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.
The free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots; every feature is available on every plan. Create a free ScreenshotNeo account.
FAQ
Does pyscreenshot capture the mouse cursor?
The project says its interactive capture is not supported and the mouse pointer is not visible. A custom backend can have its own behavior, so verify it separately if the pointer matters.
Can I use pyscreenshot without Pillow?
The documented installation includes Pillow, and the returned image uses Pillow’s memory and saving APIs. Install both packages for the supported examples.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallIs pyscreenshot actively current?
PyPI displays version 3.1, released in 2023, while the project README calls the package obsolete for most cases. Recheck package metadata and backend support before selecting it for a new long-lived application.
Frequently Asked Questions
Can pyscreenshot record a video or a sequence of frames?
It is a still-image capture interface. For video, use a screen-recording tool or repeatedly call a capture method with timing and encoding handled by a separate library.
Will a screenshot taken through a remote desktop look identical to the local display?
Not necessarily. Remote sessions can expose a different virtual monitor, scaling factor, compositor, or permission boundary. Test in the exact session used in production.
How do I capture a webpage after it finishes loading?
pyscreenshot captures the desktop, not a URL. Use a browser automation workflow or a web screenshot API such as ScreenshotNeo when the input is a webpage.
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.

