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