Get screenshot on Windows with Python?
Asked Answered
T

8

61

I am creating a Beta Testers reporting module so they can send in thier comments on my software, but I would like to have the option to include a screenshot with the report. How do I take a screenshot of the screen with Python on Windows? I have found several examples on Linux, but haven't had much luck on Windows.

Trebuchet answered 17/5, 2010 at 6:4 Comment(1)
This one worked for me: #4589706Wolff
S
49

Another approach that is really fast is the MSS module. It is different from other solutions in the way that it uses only the ctypes standard module, so it does not require big dependencies. It is OS independant and its use is made easy:

from mss import mss

with mss() as sct:
    sct.shot()

And just find the screenshot.png file containing the screen shot of the first monitor. There are a lot of possibile customizations, you can play with ScreenShot objects and OpenCV/Numpy/PIL/etc..

Sanative answered 5/7, 2017 at 12:9 Comment(7)
see more examples in python-mss.readthedocs.io/en/dev/examples.htmlFelloe
@tal: Your link is outdated. Could you please update?Area
@Tiger-222: How would you get multiple monitors?Area
@AdrianKeister: The good link is python-mss.readthedocs.io/en/latest/examples.html ; you will find answers :)Sanative
@Tiger-222: Excellent! One thing more: when I did one monitor with your code, I got a very nicely small 63kB file. In the examples link, when I did a single screenshot for all three monitors, I get a whopping 1.2 MB file. Any way to get the full screenshot down to compare in size with the single monitor?Area
Never mind. I found out that the png filesize is a lot more dependent on what's on the screen than anything else. Thanks again!Area
MSS is a lot faster than the others because it does not save the screen into a temp file but relies on a system CoreGraphics module (on OS X at least). So, you can probably either avoid saving pngs altogether or you may want to save the screenshots as jpeg.Incognizant
T
31

Worth noting that ImageGrab only works on MSWindows.

For cross platform compatibility, a person may be best off with using the wxPython library. http://wiki.wxpython.org/WorkingWithImages#A_Flexible_Screen_Capture_App

import wx
app = wx.App()  # Need to create an App instance before doing anything
screen = wx.ScreenDC()
size = screen.GetSize()
bmp = wx.Bitmap(size[0], size[1])
mem = wx.MemoryDC(bmp)
mem.Blit(0, 0, size[0], size[1], screen, 0, 0)
del mem  # Release bitmap
bmp.SaveFile('screenshot.png', wx.BITMAP_TYPE_PNG)
Terrie answered 10/4, 2012 at 13:23 Comment(7)
AttributeError: 'module' object has no attribute 'App'Glissando
app = wx.App() otherwise you might get: wx._core.PyNoAppError: The wx.App object must be created first! Also, download wxPython from here: wxpython.org/download.php For some reason it's not the same "wx" if you just do "pip install wx"Cr
CLI windows coming out emptyLamentation
@Sepero: How would you get multiple monitors?Area
@ChristianAdam: your must pip install -U wxPythonSpheno
wx.EmptyBitmap is deprecated: wxPyDeprecationWarning: Call to deprecated item EmptyBitmap. Use :class :wx.Bitmap instead use wx.BitmapGreenland
Note that you actually need to assign the result of wx.App() as cSN writes, otherwise it will get GC'd with unpredictable results.Craddock
P
16

You can use the ImageGrab module. ImageGrab works on Windows and macOS, and you need PIL (Pillow) to use it. Here is a little example:

from PIL import ImageGrab
snapshot = ImageGrab.grab()
save_path = "C:\\Users\\YourUser\\Desktop\\MySnapshot.jpg"
snapshot.save(save_path)
Pycnidium answered 29/12, 2016 at 17:13 Comment(0)
B
11

For pyautogui users:

import pyautogui
screenshot = pyautogui.screenshot()
Brachium answered 13/1, 2018 at 16:57 Comment(4)
And how do I write the image into pgn file?Clymer
pyautogui.screenshot('filename.png')Revivalist
the result size of image with PIL is better than above module: from PIL import ImageGrab snapshot = ImageGrab.grab() save_path = r"E:\havaee\mypic.jpg" snapshot.save(save_path)Rational
@alireza pyautogui (currently) uses PIL under the hood.Bovid
S
5

A simple way to take a screenshot is through Pygame.

 pygame.image.save(Surface, filename)

Where 'Surface' is the surface you are taking a screenshot of, and 'filename' is the file path, name, and type where you save thew image.

You can export as BMP, TGA, PNG, or JPEG. As of Pygame 1.8, PNG, and JPEG also work.

If no file extension is specified it will default to a .TGA file.

You can even use the 'os' library for saving to specific file directories.

An example:

import os
import pygame
surface = pygame.display.set_mode((100, 100), 0, 32)
surface.fill((255, 255, 255))
pygame.draw.circle(surface, (0, 0, 0), (10, 10), 15, 0)
pygame.display.update()
pygame.image.save(surface, os.path.expanduser("~/Desktop/pic.png"))

This saves anything on the 'surface' Surface to the user's desktop as pic.png

Smitten answered 24/8, 2016 at 18:28 Comment(2)
Two questions: 1. Is pygame platform-independent? 2. Can you get a multiple-monitor screenshot?Area
As far as I know, Pygame is platform is independent. This code will only screenshot the pygame screen, and only the pygame screen. If your screen spans across 2 monitors, i would think that it would be able to (though I am unable to test this). Hope this helps!Smitten
L
1

If you want to snap particular running Windows app you’ll have to acquire a handle by looping over all open windows in your system.

It’s easier if you can open this app from Python script. Then you can convert process pid into window handle.

Another challenge is to snap the app that runs in particular monitor. I have 3 monitor system and I had to figure out how to snap display 2 and 3.

This example will take multiple application snapshots and save them into JPEG files.

import wx

print(wx.version())
app=wx.App()  # Need to create an App instance before doing anything
dc=wx.Display.GetCount()
print(dc)
#e(0)
displays = (wx.Display(i) for i in range(wx.Display.GetCount()))
sizes = [display.GetGeometry().GetSize() for display in displays]

for (i,s) in enumerate(sizes):
    print("Monitor{} size is {}".format(i,s))   
screen = wx.ScreenDC()
#pprint(dir(screen))
size = screen.GetSize()

print("Width = {}".format(size[0]))
print("Heigh = {}".format(size[1]))

width=size[0]
height=size[1]
x,y,w,h =putty_rect

bmp = wx.Bitmap(w,h)
mem = wx.MemoryDC(bmp)

for i in range(98):
    if 1:
        #1-st display:

        #pprint(putty_rect)
        #e(0)

        mem.Blit(-x,-y,w+x,h+y, screen, 0,0)

    if 0:
        #2-nd display:
        mem.Blit(0, 0, x,y, screen, width,0)
    #e(0)

    if 0:
        #3-rd display:
        mem.Blit(0, 0, width, height, screen, width*2,0)

    bmp.SaveFile(os.path.join(home,"image_%s.jpg" % i), wx.BITMAP_TYPE_JPEG)    
    print (i)
    sleep(0.2)
del mem

Details are here

Liebig answered 20/9, 2018 at 18:36 Comment(0)
I
0

First of all, install PrtSc Library using pip3.

 import PrtSc.PrtSc as Screen
 screenshot=PrtSc.PrtSc(True,'filename.png')
Insensate answered 29/1, 2021 at 17:7 Comment(0)
C
0

I struggled with a few python screenshot issues, and so far using shot-scraper has given the best results.

pip install shot-scraper

Then install Playwright

shot-scraper install

Take a screenshot:

shot-scraper <URL>

Details and the code in GitHub repository here.

Connection answered 24/5 at 14:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.