Skip to main content

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)
info

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
tip

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)
warning

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​

LibrarySpeedMulti-MonitorRegion CapturePlatform
pyautoguiModerateNoYesWindows, macOS, Linux
Pillow (ImageGrab)ModerateLimitedYesWindows, macOS
mssFastYesYesWindows, macOS, Linux
Use CaseRecommended Library
Quick single screenshotpyautogui
Integration with image processingPillow (ImageGrab)
High-performance repeated capturesmss
Multi-monitor capturemss
GUI automation with screenshotspyautogui

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