Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
ImageGrab usually is not truncating a screenshot at random. Pillow defines a capture without bbox as the entire screen for the active capture path, but “whole screen” can mean the primary display, every monitor, or a display’s logical points rather than its physical pixels. On Windows, pass all_screens=True for the complete virtual desktop. On macOS, account for Retina’s 2x pixel dimensions (or use scale_down=True in Pillow 12.3.0 and newer). On Linux, verify XCB/display access and the documented utility fallbacks. Then compare the returned image size and crop coordinates with the coordinate space you actually intend to capture.
Start with a diagnostic capture
Record the environment before changing arguments. This separates a multi-monitor problem from scaling, permissions, or display-server issues.
import os
import platform
import PIL
from PIL import ImageGrab
print("Pillow:", PIL.__version__)
print("OS:", platform.platform())
print("DISPLAY:", os.environ.get("DISPLAY"))
print("WAYLAND_DISPLAY:", os.environ.get("WAYLAND_DISPLAY"))
image = ImageGrab.grab()
print("Captured pixels:", image.size)
image.save("diagnostic.png")
Also write down the exact grab() arguments, the exception text (if any), your desktop session, and whether “whole” means one display or the entire multi-monitor desktop. A screenshot that is twice as wide as expected may be correct Retina output, while a screenshot that omits a second monitor is a Windows virtual-desktop setting.
Windows: capture every monitor with all_screens=True
ImageGrab.grab() defaults to all_screens=False on Windows. That default captures the primary screen rather than the complete virtual desktop. Use:
#1 Best Overall
- CRISP CLARITY: This 23.8″ Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
- INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
- THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors
- WORK SEAMLESSLY: This sleek monitor is virtually bezel-free on three sides, so the screen looks even bigger for the viewer. This minimalistic design also allows for seamless multi-monitor setups that enhance your workflow and boost productivity
- A BETTER READING EXPERIENCE: For busy office workers, EasyRead mode provides a more paper-like experience for when viewing lengthy documents
from PIL import ImageGrab
image = ImageGrab.grab(all_screens=True)
print(image.size)
image.save("all-monitors.png")
all_screens is Windows-only and was added in Pillow 6.2.0. With it enabled, the virtual desktop can begin at a negative coordinate: a monitor positioned to the left or above the primary display has negative X or Y values. The image therefore represents the virtual desktop’s bounding rectangle, not a coordinate system whose origin is guaranteed to be the primary monitor’s top-left corner.
Make crops use the virtual-desktop coordinates
If you pass a bbox, use coordinates from the same desktop space as the all-monitor capture. A crop copied from a primary-monitor-only layout can select the wrong area or look clipped after a monitor is added on the left.
from PIL import ImageGrab
# Replace these with coordinates measured in the Windows virtual desktop.
left, top, right, bottom = -1920, 0, 0, 1080
image = ImageGrab.grab(bbox=(left, top, right, bottom), all_screens=True)
image.save("left-monitor.png")
Check your Windows display arrangement and compare its virtual bounds with image.size. Do not infer the origin solely from the pixel dimensions.
Do not confuse layered windows with additional monitors
include_layered_windows=True is a separate Windows-only option. It affects layered windows; it does not turn on multi-monitor capture. Use it only when you specifically need those windows included.
macOS: distinguish Retina pixels from a cropped image
macOS commonly reports display sizes in logical points while screenshots contain physical pixels. Pillow documents 2x capture on Retina screens. A display described as 1440 points wide can therefore produce an image 2880 pixels wide. That mismatch is scaling, not evidence that ImageGrab cut off part of the screen.
Rank #2
- CRISP CLARITY: This 22 inch class (21.5″ viewable) Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
- 100HZ FAST REFRESH RATE: 100Hz brings your favorite movies and video games to life. Stream, binge, and play effortlessly
- SMOOTH ACTION WITH ADAPTIVE-SYNC: Adaptive-Sync technology ensures fluid action sequences and rapid response time. Every frame will be rendered smoothly with crystal clarity and without stutter
- INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
- THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors
from PIL import ImageGrab
image = ImageGrab.grab()
print(image.size) # Retina output can be 2x the point dimensions
image.save("mac-retina.png")
If your downstream code requires 1x dimensions, Pillow 12.3.0 and newer provide the keyword-only scale_down option:
from PIL import ImageGrab
image = ImageGrab.grab(scale_down=True) # Pillow 12.3.0+
print(image.size)
image.save("mac-1x.png")
Check PIL.__version__ before using that argument. On an older Pillow release, upgrade or remove the option rather than treating a resulting argument error as a display failure.
Grant access to the application that launches Python
macOS controls screen capture per application. Open System Settings → Privacy & Security → Screen & System Audio Recording and enable the terminal, IDE, or launcher that actually starts your Python process. A permission granted to an IDE does not automatically grant it to a separate terminal. Restart the launching application after changing access, then repeat the diagnostic capture.
Linux: check XCB, the active display, and Pillow’s fallbacks
Pillow’s Linux capture path uses X11 through XCB. The process must be able to access the active display, and the installed Pillow build must include XCB support. Test that feature directly:
from PIL import Image, ImageGrab
print("XCB available:", Image.features.check_feature("xcb"))
image = ImageGrab.grab()
print("Captured pixels:", image.size)
image.save("linux-screen.png")
When xdisplay=None and the default X11 capture does not return a snapshot, Pillow documents a fallback attempt using an installed gnome-screenshot, grim, or spectacle utility. Pillow 11.3.0 added support for these named fallbacks. The behavior depends on your desktop session, display access, Pillow build, and which utility is installed; installing a generic screenshot package is not a universal fix.
Rank #3
- Clear visuals. Fluid motion: A 144Hz refresh rate and 1ms MPRT deliver smooth, tear‑free motion across work, gaming, and streaming for clearer, more fluid viewing.
- Eye comfort: TÜV Rheinland 3‑star* certification reduces harmful blue light while preserving stunning color quality without compromise. *TÜV Rheinland 3-star eye comfort certification.
- Wide viewing angle: Get consistent views across a wide 178° /178° viewing angle.
- In-Plane Switching (IPS): See excellent color accuracy and consistency across wide viewing angles with In-plane Switching (IPS) technology.
- Ultra-thin bezels: Maximize your viewing experience with thin bezels.
Leaving xdisplay at its default allows that documented fallback. Passing xdisplay="" disables it, so use an empty value only when you intentionally want to test the direct capture path.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Use bbox only after you understand the coordinate space
Without bbox, Pillow asks the platform capture path for its full screen. A bbox deliberately narrows the result. Before diagnosing a crop as a Pillow bug, verify:
- Whether coordinates are logical points or physical pixels (especially on macOS).
- Whether the origin is the primary display or a virtual desktop that can extend into negative coordinates (Windows).
- Whether the rectangle is inside the reported desktop bounds.
- Whether the image was resized after capture by your own code or an image viewer.
from PIL import ImageGrab
bbox = (100, 100, 900, 700)
image = ImageGrab.grab(bbox=bbox)
print("Requested:", bbox)
print("Returned:", image.size)
image.save("crop.png")
The returned dimensions should correspond to the rectangle in the platform’s capture units. If they do not, record the operating system, Pillow version, scaling mode, and exact arguments before changing more settings.
A platform-by-platform repair checklist
| Symptom | Likely distinction to check | Action |
|---|---|---|
| Second Windows monitor is missing | Primary display versus all monitors | Use ImageGrab.grab(all_screens=True); adapt crops to possible negative virtual-desktop coordinates. |
| macOS image is twice the expected size | Logical points versus Retina pixels | Accept 2x output or use scale_down=True on Pillow 12.3.0+. |
| macOS capture is blank or denied | Per-app screen-recording permission | Enable the app that launches Python under Screen & System Audio Recording, then restart it. |
| Linux capture fails | X11/XCB support or display access | Check Image.features.check_feature("xcb"), the active session, and the documented fallback utilities. |
| Crop is shifted or clipped | bbox does not match capture coordinate origin |
Compare the rectangle with virtual-desktop bounds and scaling units. |
Common errors and recovery steps
“It captures only one monitor”
On Windows, this is the expected default when all_screens is omitted. Add all_screens=True. The option is not portable to macOS or Linux, so do not copy it into a cross-platform call without a platform branch.
“The screenshot is huge on my Mac”
Compare the image with the display’s point dimensions. A 2x Retina result is documented behavior. Use scale_down=True only on Pillow 12.3.0 or later when your consumer needs 1x output; otherwise retain the physical-pixel image.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsRank #4
- CURVED FOR ENHANCED ENGAGEMENT: An immersive viewing experience with a curved monitor that wraps more closely around your field of vision; It creates a wider view, enhancing depth perception and minimizing peripheral distraction
- SMOOTH PERFORMANCE FOR SEAMLESS CONTENT: Stay in the action when playing games, watching videos, or working on creative projects; The 100Hz refresh rate reduces lag and motion blur so you don't miss a thing in fast-paced moments¹
- MORE GAMING POWER: Gain the edge with optimizable game settings; Color and image contrast can be adjusted to see scenes more vividly and spot enemies hiding in the dark; Game Mode adjusts any game to fill the screen so you can view every detail²
- KEEP IT EASY ON THE EYES: Care for your eyes and stay comfortable, even during long sessions; Advanced eye comfort technology certified by TÜV reduces eye strain by minimizing blue light and reducing irritating screen flicker²
- INCREASED VERSATILITY: Connect to more; Plug devices straight into your monitor for increased flexibility, making your computing environment even more convenient
“scale_down is an unexpected keyword”
Your Pillow version predates 12.3.0. Print PIL.__version__, upgrade if appropriate, or call grab() without that keyword and resize explicitly in a separate, documented step.
“The Linux result is black, blank, or raises an exception”
Do not assume one cause. Check XCB support, the DISPLAY environment variable, the desktop/session type, and whether the process can access the active display. Note whether gnome-screenshot, grim, or spectacle is installed so you can determine whether Pillow’s documented fallback can apply. A Wayland, protected-video, or permission explanation requires evidence from that particular machine.
“A crop works on one computer but not another”
Compare monitor arrangement, scaling, Pillow version, and the coordinate origin. On Windows with all monitors enabled, a left-hand display commonly makes the virtual origin negative. On macOS, point coordinates and pixel dimensions can differ by a factor of two.
Performance, reliability, and version notes
- Capture the smallest useful region when you do not need a full desktop; a smaller image reduces memory and encoding work.
- Keep the diagnostic metadata with failed captures: Pillow version, operating system, session, arguments, exception, and returned dimensions.
- Pin or record Pillow versions in reproducible automation. In particular,
all_screensrequires Pillow 6.2.0 or newer, whilescale_downrequires 12.3.0 or newer. - Test each monitor arrangement and scaling mode used by your application. A fixed
bboxis not portable across changing virtual-desktop layouts. - For Linux, treat fallback utilities as conditional behavior rather than a guarantee across every display-server setup.
Or skip the browser setup
If your goal is a website image rather than a local desktop, ScreenshotNeo provides a GET-based screenshot API. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing result. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →See the complete parameter list in the ScreenshotNeo documentation. A minimal cURL request is:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
The same request in Python:
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
And in Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const bytes = new Uint8Array(await res.arrayBuffer());
await Bun.write('shot.webp', bytes);
ScreenshotNeo includes full-page lazy-image loading, element capture by CSS selector, dark mode, device presets and custom viewports, retina scale, PDF paper and page controls, custom CSS and JavaScript, clicks, waits, request blocking, headers, cookies, user agents, authorization, timezone and geolocation, transparent backgrounds, resizing, selectable-TTL caching, signed image links, asynchronous signed webhooks, bulk capture of up to 100 URLs per call, a usage API, an OpenAPI specification, and compatible parameter names used by other screenshot APIs.
Best Value
- 【INTEGRATED SPEAKERS】Whether you're at work or in the midst of an intense gaming session, our built-in speakers provide rich and seamless audio, all while keeping your desk clutter-free.
- 【EASY ON THE EYES】 Protect your eyes and enhance your comfort with Blue-Light Shift technology. This feature reduces harmful blue light emissions from your screen, helping to alleviate eye strain during long hours of use and promoting healthier viewing habits.
- 【WIDEN YOUR PERSPECTIVE】Our sleek minimal bezel design ensures undivided attention. The nearly bezel-free display seamlessly connects in a dual monitor arrangement, delivering an unobstructed view that lets you focus on more at once, completely distraction-free.
| Plan | Included shots | Price |
|---|---|---|
| Free | 1,000 per month | No card |
| Starter | 3,000 | $5 |
| Growth | 15,000 | $15 |
| Pro | 60,000 | $39 |
| Scale | 250,000 | $99 |
| Business | 1,000,000 | $249 |
Yearly billing gives two months free, and every feature is available on every plan. Start with 1,000 free screenshots a month with no card; paid plans start at $5 for 3,000.
FAQ
Does omitting bbox guarantee every physical monitor?
No. It requests the entire screen for the active platform path. On Windows, all monitors require all_screens=True; other platforms have different definitions and scaling behavior.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →Is a 2x macOS image an error?
Not necessarily. Retina capture uses physical pixels, so dimensions can be twice the logical point size. Use scale_down=True on Pillow 12.3.0 or newer when 1x output is required.
What information should I include when asking for help?
Provide the operating system and session, Pillow version, exact grab() call, exception text, returned image.size, monitor arrangement, and whether the display is scaled or Retina.
Frequently Asked Questions
Can I use all_screens=True on Linux or macOS?
No. Pillow documents this switch as Windows-only; use the native capture path and platform-specific diagnosis on Linux or macOS.
Why does a negative Windows coordinate matter?
A monitor placed left or above the primary display makes the virtual desktop origin negative, so a bbox based on primary-monitor coordinates can select the wrong region.
Recommended Free Tools
Does include_layered_windows=True add monitors?
No. It controls layered-window inclusion and is separate from the Windows multi-monitor option.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

