Use pyautogui.screenshot() to capture the current desktop. It returns a Pillow Image object, so you can inspect it in memory, save it with image.save(), or pass a filename directly to save and return the image in one call. To capture part of the screen, provide region=(left, top, width, height). The official function reference documents these forms and examples at PyAutoGUI’s screenshot functions page.
Quick answer: the three useful forms
Install PyAutoGUI and its screenshot prerequisites, then import it in the Python process that has access to the desktop session:
import pyautogui
# Capture the complete primary screen in memory
image = pyautogui.screenshot()
# Save while also receiving the Pillow Image object
saved_image = pyautogui.screenshot("screen.png")
# Capture a rectangle: left, top, width, height
region_image = pyautogui.screenshot(region=(0, 0, 300, 400))
image, saved_image, and region_image are Pillow image objects. The tuple is not (x1, y1, x2, y2); it is an origin plus dimensions: (left, top, width, height).
Install PyAutoGUI and prepare the desktop
Install the Python package
Use the Python interpreter that will run your automation:
Free tools Windows power users keep installed
One-click scans. No signup required.
#1 Best Overall
python -m pip install pyautogui
Keep the package installation in the same virtual environment as your script. Exact package versions change, so check the currently installed version with your package manager rather than relying on an old tutorial.
Platform prerequisites
- Windows: PyAutoGUI supports desktop screenshots on Windows. Run the script in an interactive graphical session rather than a service with no desktop.
- macOS: the screenshot implementation uses the built-in
screencapturecommand. macOS privacy controls may require granting the terminal or Python application permission to record the screen. - Linux: the documentation identifies
scrotas required for screenshots. Install it through your distribution’s package manager. The installation guidance also lists Linux Tkinter as a dependency for PyAutoGUI’s broader setup.
PyAutoGUI’s documented scope includes Windows, macOS, and Linux. Its overview says multi-monitor handling is limited to the primary monitor, so test the exact desktop environment and installed version before building a workflow around another display.
What screenshot() returns
Capture in memory
With no arguments, the function captures the current screen and returns a Pillow Image. This is useful when the next step is analysis, comparison, OCR performed by another library, or a conditional save:
import pyautogui
image = pyautogui.screenshot()
print(image.size) # (width, height)
print(image.mode) # Pillow image mode, such as RGB or RGBA
# Save later, after any checks or processing
image.save("screen.png")
The image remains available after the function returns; saving is not required at capture time.
Save and receive the image in one call
Passing a filename is the shortest way to write a file and retain the object:
import pyautogui
image = pyautogui.screenshot("screen.png")
# image is still a Pillow Image object
Use an extension that matches the format you want, such as .png, or pass an explicit format to Pillow when calling image.save(). Ensure the destination directory exists and that the process has write permission.
Use a deterministic output path
from pathlib import Path
import pyautogui
output = Path("artifacts")
output.mkdir(parents=True, exist_ok=True)
image = pyautogui.screenshot(output / "desktop.png")
Using pathlib.Path avoids hard-coded path separators. For repeated captures, generate unique names or deliberately overwrite a known file.
Capture only part of the screen with region
Pass a four-item tuple in this exact order:
- left: horizontal coordinate of the rectangle’s top-left corner;
- top: vertical coordinate of that corner;
- width: rectangle width in pixels;
- height: rectangle height in pixels.
import pyautogui
# Top-left 300 by 400 pixels
crop = pyautogui.screenshot(region=(0, 0, 300, 400))
crop.save("top_left.png")
# A 640 by 360 rectangle beginning at (120, 80)
preview = pyautogui.screenshot(region=(120, 80, 640, 360))
preview.save("preview.png")
A region reduces the captured image and is useful when only a stable panel matters. Coordinates refer to the desktop coordinate system used by the current session; confirm them visually, especially when display scaling is enabled.
Rank #3
Validate a region before capturing
import pyautogui
left, top, width, height = 120, 80, 640, 360
if width <= 0 or height <= 0:
raise ValueError("width and height must be positive")
image = pyautogui.screenshot(region=(left, top, width, height))
image.save("validated_region.png")
Keep the rectangle inside the visible primary display. If a window moves, a previously correct region may capture the wrong content; locate the window or establish its position before taking the shot.
Full-screen capture, bounded capture, and image processing
| Choice | Call | When it fits |
|---|---|---|
| Entire primary screen | pyautogui.screenshot() |
Evidence of the complete desktop state or a later crop performed in Pillow. |
| Rectangle at capture time | pyautogui.screenshot(region=(left, top, width, height)) |
Smaller files and a known panel, toolbar, or test fixture. |
| In-memory image | image = pyautogui.screenshot() |
Inspect, compare, transform, or decide whether to save. |
| Immediate file plus object | image = pyautogui.screenshot("name.png") |
Simple capture pipelines that need an artifact immediately. |
The screenshot call creates an image; it does not search for buttons or icons. Keep capture and visual matching as separate steps so failures are easier to diagnose.
Screenshot capture versus locating an image
To find a supplied visual on the screen, use a locate function such as locateOnScreen() after taking (or independently obtaining) the reference image. The optional confidence argument requires OpenCV. Restricting the search with a smaller region can reduce the area examined, and grayscale matching can speed a search at the cost of possible false positives.
import pyautogui
screen = pyautogui.screenshot("before_search.png")
# Example only: locate a reference image file on the current screen
match = pyautogui.locateOnScreen("button.png", confidence=0.9)
print(match)
Install and verify OpenCV separately before using confidence. A successful screenshot does not imply that a locate operation will succeed: matching depends on the reference image, scale, theme, timing, and the search area.
Timing, performance, and reliability
The official screenshot page gives a rough estimate of about 100 milliseconds for a 1,920 × 1,080 capture on its example setup. That is an environment-specific indication, not a guarantee for your machine. Display size, operating system, desktop compositor, Python environment, and disk speed all affect elapsed time.
- Capture a bounded region when a full desktop is unnecessary.
- Keep the image in memory if you only need to inspect it; avoid needless disk writes.
- When writing many files, use a dedicated output directory and unique names.
- Take the screenshot after the UI has reached a known state. A fast call can still capture an animation, loading indicator, or stale window.
- For image searches, constrain
locateOnScreen()with a region. The documentation’s rough one-to-two-second locate estimate is tied to its example environment and is not a current benchmark.
For repeatable automation, log the timestamp, requested region, output path, and any exception. This makes it clear whether a failure occurred during desktop access, image matching, or file output.
Common errors and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
| Import succeeds but screenshot capture raises an exception on Linux | The screenshot backend dependency is missing. | Install scrot using the operating system’s package manager, then rerun the script in a graphical session. |
| macOS returns a blank or denied capture | Screen-recording permission is not granted to the terminal, IDE, or Python host. | Allow the relevant application in macOS privacy settings, restart it, and test again. |
| File is not created | The destination directory does not exist or is not writable. | Create the directory, use an absolute path temporarily, and check the process user’s write permissions. |
| The image shows the wrong area | The region coordinates or window position changed. | Confirm the top-left origin, width, and height; stabilize or reposition the window before capture. |
| A second monitor is missing | The documented multi-monitor support is limited to the primary monitor. | Move the target window to the primary display or verify whether your installed version and desktop environment provide different behavior. |
locateOnScreen(..., confidence=...) fails before matching |
OpenCV is not installed or available to the running interpreter. | Install OpenCV in the same environment, or omit confidence and use the documented matching options. |
| Locate returns a false match | Grayscale matching or a broad search region matched a similar shape. | Search a smaller region, use color matching, or raise the confidence threshold and validate the result before clicking. |
A complete, defensive Python example
from datetime import datetime
from pathlib import Path
import pyautogui
out_dir = Path("captures")
out_dir.mkdir(parents=True, exist_ok=True)
# Use a timestamped filename so an earlier capture is not overwritten.
stamp = datetime.now().strftime("%Y%m%d-%H%M%S")
path = out_dir / f"desktop-{stamp}.png"
# Full primary-screen capture; returns a Pillow Image and writes the file.
image = pyautogui.screenshot(path)
print(f"saved {path} ({image.width}x{image.height})")
# Optional bounded capture using (left, top, width, height).
region = (0, 0, min(800, image.width), min(600, image.height))
pyautogui.screenshot(out_dir / f"corner-{stamp}.png", region=region)
This script creates its output directory, avoids accidental overwrites, reports the resulting dimensions, and derives a safe region from the captured image size.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Or skip the browser setup
PyAutoGUI captures the desktop of the machine running Python. If you need a rendered website image instead, ScreenshotNeo returns a PNG, JPEG, WebP, or PDF from one HTTP request and is the first service to try for this use case: it removes consent banners, newsletter popups, and chat widgets before capture, and only clean shots are billed.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
With an API key, the smallest call is:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo API documentation for request options. The same request in Python is:
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}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));
ScreenshotNeo reports X-Page-Verdict and X-Billed headers. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for 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 screenshots. Create a free ScreenshotNeo account.
ScreenshotNeo plans at a glance
| Plan | Included shots | Price |
|---|---|---|
| Free | 1,000 per month | $0, no card |
| Starter | 3,000 | $5 |
| Growth | 15,000 | $15 |
| Pro | 60,000 | $39 |
| Scale | 250,000 | $99 |
| Business | 1,000,000 | $249 |
Yearly billing gives two months free, and every feature is available on every plan. Choose PyAutoGUI when you need the visible desktop; choose the API when a URL is the input and a repeatable server-side artifact is the output.
Frequently Asked Questions
Does calling pyautogui.screenshot() control the mouse or keyboard?
No. It reads the current desktop and returns an image. Mouse and keyboard actions are separate PyAutoGUI operations, so a screenshot call by itself does not click, type, or move anything.
PC 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 & 11Crashes, 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 minuteCan I use the returned object without saving a file?
Yes. The returned value is a Pillow Image, so code can inspect or transform it in memory and save only when a persistent artifact is needed.
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.

