How to Take Screenshots Using Python
Capturing screenshots programmatically is useful for a variety of tasks: automated testing, monitoring dashboards, creating documentation, recording screen activity, or building desktop automation tools. Python provides several libraries for taking screenshots, from simple full-screen captures to targeted region captures. This guide covers multiple methods using pyautogui, Pillow, and mss, with practical examples for different use cases.
Method 1: Using PyAutoGUI
PyAutoGUI is a cross-platform GUI automation library that includes a simple screenshot function. It captures the entire screen and returns a PIL (Pillow) Image object.
Installation
pip install pyautogui
pip install Pillow
Taking a Full Screenshot
import pyautogui
# Capture the entire screen
screenshot = pyautogui.screenshot()
# Save to a file
screenshot.save("full_screenshot.png")
print(f"Screenshot saved: {screenshot.size[0]}x{screenshot.size[1]} pixels")
Output:
Screenshot saved: 1920x1080 pixels
You can also save directly by passing a filename to screenshot():
import pyautogui
# Capture and save in one step
screenshot = pyautogui.screenshot("my_screenshot.png")
Capturing a Specific Region
To capture only a portion of the screen, pass a region tuple (left, top, width, height):
import pyautogui
# Capture a 400x300 region starting at position (100, 200)
region_screenshot = pyautogui.screenshot(region=(100, 200, 400, 300))
region_screenshot.save("region_screenshot.png")
print(f"Region captured: {region_screenshot.size[0]}x{region_screenshot.size[1]} pixels")
Output:
Region captured: 400x300 pixels
Method 2: Using Pillow's ImageGrab
Pillow's ImageGrab module provides direct screen capture functionality. It is available on Windows and macOS.
Installation
pip install Pillow
Full Screen Capture
from PIL import ImageGrab
# Capture the entire screen
screenshot = ImageGrab.grab()
screenshot.save("pillow_screenshot.png")
print(f"Screenshot size: {screenshot.size}")
Output:
Screenshot size: (1920, 1080)
Capturing a Specific Region
Pass a bounding box tuple (left, upper, right, lower) to grab():
from PIL import ImageGrab
# Capture region from (0, 0) to (500, 400)
region = ImageGrab.grab(bbox=(0, 0, 500, 400))
region.save("pillow_region.png")
print(f"Region size: {region.size}")
Output:
Region size: (500, 400)
Note the difference in region specification: PyAutoGUI uses (left, top, width, height) while Pillow's ImageGrab uses (left, upper, right, lower). Confusing these formats is a common source of bugs.
Method 3: Using MSS (Fast Multi-Screen Capture)
The mss library is optimized for speed and supports multi-monitor setups. It is significantly faster than PyAutoGUI and Pillow for repeated captures, making it ideal for screen recording or real-time monitoring.
Installation
pip install mss
Full Screen Capture
import mss
with mss.mss() as sct:
# Capture the primary monitor
screenshot = sct.grab(sct.monitors[1])
# Save to file
mss.tools.to_png(screenshot.rgb, screenshot.size, output="mss_screenshot.png")
print(f"Screenshot size: {screenshot.width}x{screenshot.height}")
Output:
Screenshot size: 1920x1080
Capturing All Monitors
import mss
with mss.mss() as sct:
# monitors[0] is the combined virtual screen of all monitors
print(f"Total monitors: {len(sct.monitors) - 1}")
for i, monitor in enumerate(sct.monitors[1:], start=1):
screenshot = sct.grab(monitor)
filename = f"monitor_{i}.png"
mss.tools.to_png(screenshot.rgb, screenshot.size, output=filename)
print(f"Monitor {i} saved: {screenshot.width}x{screenshot.height}")
Output:
Total monitors: 2
Monitor 1 saved: 1920x1080
Monitor 2 saved: 1920x1080
Capturing a Specific Region
import mss
with mss.mss() as sct:
region = {"top": 100, "left": 100, "width": 400, "height": 300}
screenshot = sct.grab(region)
mss.tools.to_png(screenshot.rgb, screenshot.size, output="mss_region.png")
print(f"Region captured: {screenshot.width}x{screenshot.height}")
Output:
Region captured: 400x300
mss is the best choice for performance-critical applications. It is 2-10x faster than PyAutoGUI for capturing screenshots, especially when taking multiple screenshots in succession.
Taking Multiple Screenshots at Intervals
To capture screenshots at regular intervals: useful for monitoring or time-lapse recording:
import pyautogui
import time
num_screenshots = 5
interval = 2 # seconds
for i in range(num_screenshots):
filename = f"screenshot_{i + 1}.png"
pyautogui.screenshot(filename)
print(f"Saved {filename}")
if i < num_screenshots - 1:
time.sleep(interval)
print(f"\nCaptured {num_screenshots} screenshots at {interval}-second intervals")
Output:
Saved screenshot_1.png
Saved screenshot_2.png
Saved screenshot_3.png
Saved screenshot_4.png
Saved screenshot_5.png
Captured 5 screenshots at 2-second intervals
Converting a Screenshot to a NumPy Array
For image processing with OpenCV or other libraries, convert the screenshot to a NumPy array:
import pyautogui
import numpy as np
# Take a screenshot
screenshot = pyautogui.screenshot()
# Convert to NumPy array
img_array = np.array(screenshot)
print(f"Array shape: {img_array.shape}")
print(f"Data type: {img_array.dtype}")
Output:
Array shape: (1080, 1920, 3)
Data type: uint8
For use with OpenCV, convert from RGB to BGR:
import pyautogui
import numpy as np
import cv2
screenshot = pyautogui.screenshot()
img_array = np.array(screenshot)
# Convert RGB (Pillow) to BGR (OpenCV)
img_bgr = cv2.cvtColor(img_array, cv2.COLOR_RGB2BGR)
# Save using OpenCV
cv2.imwrite("opencv_screenshot.png", img_bgr)
Common Mistake: Not Converting Color Channels for OpenCV
PyAutoGUI and Pillow produce images in RGB format, while OpenCV expects BGR. Using the image directly without conversion results in swapped red and blue channels:
import pyautogui
import numpy as np
import cv2
screenshot = pyautogui.screenshot()
img_array = np.array(screenshot)
# WRONG: saving RGB as BGR - colors will be swapped
cv2.imwrite("wrong_colors.png", img_array)
The saved image will have blue objects appearing red and red objects appearing blue.
The correct approach
# CORRECT: convert RGB to BGR before using with OpenCV
img_bgr = cv2.cvtColor(img_array, cv2.COLOR_RGB2BGR)
cv2.imwrite("correct_colors.png", img_bgr)
Always convert color channels when moving images between Pillow/PyAutoGUI (RGB) and OpenCV (BGR). The images will look correct in the viewer but have wrong colors in processing if the conversion is skipped.
Method Comparison
| Library | Speed | Multi-Monitor | Region Capture | Platform |
|---|---|---|---|---|
pyautogui | Moderate | No | Yes | Windows, macOS, Linux |
Pillow (ImageGrab) | Moderate | Limited | Yes | Windows, macOS |
mss | Fast | Yes | Yes | Windows, macOS, Linux |
| Use Case | Recommended Library |
|---|---|
| Quick single screenshot | pyautogui |
| Integration with image processing | Pillow (ImageGrab) |
| High-performance repeated captures | mss |
| Multi-monitor capture | mss |
| GUI automation with screenshots | pyautogui |
For simple, one-off screenshots, PyAutoGUI offers the easiest API. For performance-sensitive applications or multi-monitor setups, mss is the better choice. All three libraries are well-maintained and cross-platform (with minor limitations for Pillow on Linux).