Examples

Basics

One screenshot per monitor

for filename in sct.save():
    print(filename)

Screenshot of the monitor 1

filename = sct.shot()
print(filename)

A screenshot to grab them all

filename = sct.shot(mon=-1, output='fullscreen.png')
print(filename)

Callback

Screenshot of the monitor 1 with a callback:

import os
import os.path

import mss


def on_exists(fname):
    # type: (str) -> None
    """
    Callback example when we try to overwrite an existing screenshot.
    """

    if os.path.isfile(fname):
        newfile = fname + '.old'
        print('{0} -> {1}'.format(fname, newfile))
        os.rename(fname, newfile)


with mss.mss() as sct:
    filename = sct.shot(output='mon-{mon}.png', callback=on_exists)
    print(filename)

Part of the screen

You can capture only a part of the screen:

import mss
import mss.tools


with mss.mss() as sct:
    # The screen part to capture
    monitor = {'top': 160, 'left': 160, 'width': 160, 'height': 135}
    output = 'sct-{top}x{left}_{width}x{height}.png'.format(**monitor)

    # Grab the data
    sct_img = sct.grab(monitor)

    # Save to the picture file
    mss.tools.to_png(sct_img.rgb, sct_img.size, output)
    print(output)

New in version 3.0.0.

Use PIL bbox style and percent values

You can use the same value as you would do with PIL.ImageGrab(bbox=tuple(...)). This is an example that uses it, but also using percentage values:

import mss
import mss.tools


with mss.mss() as sct:
    # Use the 1st monitor
    monitor = sct.monitors[1]

    # Capture a bbox using percent values
    left = monitor['left'] + monitor['width'] * 5 // 100  # 5% from the left
    top = monitor['top'] + monitor['height'] * 5 // 100  # 5% from the top
    right = left + 400  # 400px width
    lower = top + 400  # 400px height
    bbox = (left, top, right, lower)

    # Grab the picture
    # Using PIL would be something like:
    # im = ImageGrab(bbox=bbox)
    im = sct.grab(bbox)

    # Save it!
    mss.tools.to_png(im.rgb, im.size, 'screenshot.png')

New in version 3.1.0.

Advanced

You can handle data using a custom class:

import mss


class SimpleScreenShot(object):
    """
    Define your own custom method to deal with screen shot raw data.
    Of course, you can inherit from the ScreenShot class and change
    or add new methods.
    """

    def __init__(self, data, monitor, **kwargs):
        self.data = data
        self.monitor = monitor


with mss.mss() as sct:
    sct.cls_image = SimpleScreenShot
    image = sct.grab(sct.monitors[1])
    # ...

New in version 3.1.0.

PIL

You can use the Python Image Library (aka Pillow) to do whatever you want with raw pixels. This is an example using frombytes():

import mss
from PIL import Image


with mss.mss() as sct:
    # Get rid of the first, as it represents the "All in One" monitor:
    for num, monitor in enumerate(sct.monitors[1:], 1):
        # Get raw pixels from the screen
        sct_img = sct.grab(monitor)

        # Create the Image
        img = Image.frombytes('RGB', sct_img.size, sct_img.rgb)

        # And save it!
        output = 'monitor-{0}.png'.format(num)
        img.save(output)
        print(output)

New in version 3.0.0.

Playing with pixels

This is an example using putdata():

import mss
from PIL import Image


with mss.mss() as sct:
    # Get a screenshot of the 1st monitor
    sct_img = sct.grab(sct.monitors[1])

    # Create an Image
    img = Image.new('RGB', sct_img.size)

    # Best solution: create a list(tuple(R, G, B), ...) for putdata()
    pixels = zip(sct_img.raw[2::4],
                 sct_img.raw[1::4],
                 sct_img.raw[0::4])
    img.putdata(list(pixels))

    # But you can set individual pixels too (slower)
    """
    pixels = img.load()
    for x in range(sct_img.width):
        for y in range(sct_img.height):
            pixels[x, y] = sct_img.pixel(x, y)
    """

    # Show it!
    img.show()

New in version 3.0.0.

OpenCV/Numpy

See how fast you can record the screen. You can easily view a HD movie with VLC and see it too in the OpenCV window. And with __no__ lag please.

import time

import cv2
import mss
import numpy


with mss.mss() as sct:
    # Part of the screen to capture
    monitor = {'top': 40, 'left': 0, 'width': 800, 'height': 640}

    while 'Screen capturing':
        last_time = time.time()

        # Get raw pixels from the screen, save it to a Numpy array
        img = numpy.array(sct.grab(monitor))

        # Display the picture
        cv2.imshow('OpenCV/Numpy normal', img)

        # Display the picture in grayscale
        # cv2.imshow('OpenCV/Numpy grayscale',
        #            cv2.cvtColor(img, cv2.COLOR_BGRA2GRAY))

        print('fps: {0}'.format(1 / (time.time()-last_time)))

        # Press "q" to quit
        if cv2.waitKey(25) & 0xFF == ord('q'):
            cv2.destroyAllWindows()
            break

New in version 3.0.0.

FPS

Benchmark

Simple naive benchmark to compare with Reading game frames in Python with OpenCV - Python Plays GTA V:

import time

import cv2
import mss
import numpy


def screen_record():
    try:
        from PIL import ImageGrab
    except ImportError:
        return 0

    # 800x600 windowed mode
    mon = (0, 40, 800, 640)

    title = '[PIL.ImageGrab] FPS benchmark'
    fps = 0
    last_time = time.time()

    while time.time() - last_time < 1:
        img = numpy.asarray(ImageGrab.grab(bbox=mon))
        fps += 1

        cv2.imshow(title, cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
        if cv2.waitKey(25) & 0xFF == ord('q'):
            cv2.destroyAllWindows()
            break

    return fps


def screen_record_efficient():
    # 800x600 windowed mode
    mon = {'top': 40, 'left': 0, 'width': 800, 'height': 640}

    title = '[MSS] FPS benchmark'
    fps = 0
    sct = mss.mss()
    last_time = time.time()

    while time.time() - last_time < 1:
        img = numpy.asarray(sct.grab(mon))
        fps += 1

        cv2.imshow(title, img)
        if cv2.waitKey(25) & 0xFF == ord('q'):
            cv2.destroyAllWindows()
            break

    return fps


print('PIL:', screen_record())
print('MSS:', screen_record_efficient())

New in version 3.0.0.