What's the fastest way to take a screenshot on windows? PIL.ImageGrab
is rather slow.. it takes between 4-5 seconds to take 30 screenshots of the same small window. Taking screenshots of the whole desktop is even slower.
-
Sound like what you realy want are screen videos, a la CamStudio on Sourceforge. What's the use case? – Simon Hibbs Aug 27 '10 at 16:35
-
8to get the highest score ever on [winterbells](http://www.ferryhalim.com/orisinal/g3/bells.htm) =P – Claudiu Aug 27 '10 at 17:25
-
Just gave Winterbells a play and it's surprisingly addicting – jack.py Sep 06 '19 at 13:59
4 Answers
You could use win32 APIs directly .
First give the focus to the App that you want to take screenshot of. link text
Win32 API can help with the screenshot:
import win32gui
import win32ui
import win32con
w = 1920 # set this
h = 1080 # set this
bmpfilenamename = "out.bmp" #set this
hwnd = win32gui.FindWindow(None, windowname)
wDC = win32gui.GetWindowDC(hwnd)
dcObj=win32ui.CreateDCFromHandle(wDC)
cDC=dcObj.CreateCompatibleDC()
dataBitMap = win32ui.CreateBitmap()
dataBitMap.CreateCompatibleBitmap(dcObj, w, h)
cDC.SelectObject(dataBitMap)
cDC.BitBlt((0,0),(w, h) , dcObj, (0,0), win32con.SRCCOPY)
dataBitMap.SaveBitmapFile(cDC, bmpfilenamename)
# Free Resources
dcObj.DeleteDC()
cDC.DeleteDC()
win32gui.ReleaseDC(hwnd, wDC)
win32gui.DeleteObject(dataBitMap.GetHandle())

- 12,186
- 6
- 68
- 106

- 65,343
- 15
- 148
- 136
-
14VERY IMPORTANT, as this recently bit me in the ass: you HAVE TO delete/release all the DCs created by this, or after taking ~90 images, you won't be able to anymore. in this case, `dcObj.DeleteDC(); cDC.DeleteDC(); win32gui.ReleaseDC(hwnd, wDC)` – Claudiu Sep 01 '10 at 15:39
-
See this script for more details: http://bytes.com/topic/python/answers/576924-win32ui-vs-wxpy-screen-capture-multi-monitor – Alex L Jan 06 '13 at 07:33
-
2As a followup from @Claudiu's comment (which is indeed necessary as he notes), I found `win32gui.DeleteObject(dataBitMap.GetHandle())` also necessary. I've edited the answer to include both comments. – jedwards Jul 15 '14 at 05:19
-
-
1
-
For some reason this isn't working for me. If I create a DC object like this `dcObj = win32ui.CreateDCFromHandle(wDC)` I can't access the functions of that object, so `dcObj.CreateCompatibleDC()` isn't working (I use VSCode and it usually gives suggestions when typing a dot after an object, but here it doesn't do that so I'm thinking I need to import something else? I installed pywin32 in my virtual environment and imported `win32gui, win32ui, win32con` in the program. Anyone an idea? – xvk Sep 05 '21 at 16:41
-
To take a screenshot, yes. But in the case what you screenshot is a 3D rendered image, isn't it faster to grab the Framebuffer, instead of waiting that windows gets hold of it back? – Sandburg Jan 14 '22 at 16:10
Just found out how to do it with gtk. Seems fastest by far:
def image_grab_gtk(window):
left, top, right, bot = get_rect(window)
w = right - left
h = bot - top
s = gtk.gdk.Pixbuf(
gtk.gdk.COLORSPACE_RGB, False, 8, w, h)
s.get_from_drawable(
gtk.gdk.get_default_root_window(),
gtk.gdk.colormap_get_system(),
left, top, 0, 0, w, h )
final = Image.frombuffer(
"RGB",
(w, h),
s.get_pixels(),
"raw",
"RGB",
s.get_rowstride(), 1)
return final
Without converting to a PIL
Image, it's 8x faster than PIL on my test case. With converting, it's still ~2.7x faster.

- 224,032
- 165
- 485
- 680
You can try my newly created project DXcam: I think for raw speed it's the fastest out there (in python, and without going too deep into the rabbit hole). It's originally created for a deep learning pipeline for FPS games where the higher FPS you get the better. Plus I (am trying to) design it to be user-friendly: For a screenshot just do
import dxcam
camera = dxcam.create()
frame = camera.grab() # full screen
frame = camera.grab(region=(left, top, right, bottom)) # region
For screen capturing:
camera.start(target_fps=60) # threaded
for i in range(1000):
image = camera.get_latest_frame() # Will block until new frame available
camera.stop()
I copied the part of the benchmarks section from the readme:
DXcam | python-mss | D3DShot | |
---|---|---|---|
Average FPS | 238.79 | 75.87 | 118.36 |
Std Dev | 1.25 | 0.5447 | 0.3224 |
The benchmarks is conducted through 5 trials on my 240hz monitor with a constant 240hz rendering rate synced w/the monitor (using blurbuster ufo test).
You can read more about the details here: https://github.com/ra1nty/DXcam

- 61
- 1
-
this is an interesting library! please get that on main PyPI. their testing repo is just for testing. – Christoph Rackwitz Jul 15 '22 at 13:06
-
FWIW this was much slower than mss for my application, but the guarantee of every frame being new is nice. – Eric M. Sep 16 '22 at 08:32
You can use package mss:
Save screenshot to image file
import mss
with mss.mss() as sct:
filename = sct.shot(output="output.png")
Get the numpy representation of screenshot
import mss
import numpy as np
with mss.mss() as sct:
monitor = {"top": 160, "left": 160, "width": 160, "height": 135}
img_array = np.array(sct.grab(monitor))
# Do whatever you want...

- 143
- 1
- 4
-
How fast is this compared to other options, if you checked? TY for sharing, regardless! – Eric Carmichael Nov 02 '21 at 01:53
-
-
Ty for sharing! Using other methods at 1440p I got 13fps, but with mss I was able to achieve 20fps. It's fast for sure :) – Eric Carmichael Nov 03 '21 at 06:07