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 errorsPyAutoGUI screenshot problems usually come from one of four places: a missing Pillow or platform capture dependency, an unsupported or headless display session, a mismatch between logical and physical pixel dimensions, or a separate image-matching failure. First prove that a minimal full-screen capture works, inspect its size and pixels, and only then debug locateOnScreen(). This separates capture failures from template and coordinate problems.
Understand what PyAutoGUI is doing
PyAutoGUI delegates screenshots and image location to PyScreeze, while the screenshot image itself is a Pillow image. Screenshot functionality requires Pillow, and the returned image can be saved directly by passing a filename. The official API also accepts a four-value region tuple: (left, top, width, height). See the PyAutoGUI screenshot documentation.
Capture and matching are different operations. A file can be captured correctly even when locateOnScreen() cannot find a template. Conversely, a matching error may hide an earlier blank, black, scaled, or incorrectly sized capture. Diagnose these stages independently.
Start with a minimal diagnostic script
Run this in the same virtual environment, terminal, IDE interpreter, container, or service account that runs your real automation:
Free tools Windows power users keep installed
One-click scans. No signup required.
#1 Best Overall
import sys
import platform
from pathlib import Path
import pyautogui
from PIL import Image
print("Python:", sys.version)
print("OS:", platform.platform())
print("PyAutoGUI screen size:", pyautogui.size())
image = pyautogui.screenshot("screen-test.png")
print("Captured image size:", image.size)
print("Mode:", image.mode)
print("File exists:", Path("screen-test.png").exists())
print("Top-left pixel:", image.getpixel((0, 0)))
region = pyautogui.screenshot(region=(0, 0, 400, 300))
region.save("region-test.png")
print("Region size:", region.size)
# Re-open the file to verify that writing and reading work.
with Image.open("screen-test.png") as saved:
print("Saved file reads as:", saved.size, saved.format)
A normal result is an image file whose dimensions and visible content correspond to the display you are using. PyAutoGUI documentation describes roughly 100 milliseconds for a 1,920 × 1,080 full-screen screenshot and about one to two seconds for a locate call; these are documentation estimates, not performance guarantees.
Fix import and dependency errors
Confirm the interpreter and Pillow
Use the interpreter that launches the script:
python -c "import sys, pyautogui, PIL; print(sys.executable); print(pyautogui.__version__); print(PIL.__version__)"
If import PIL fails, install Pillow into that exact environment:
python -m pip install --upgrade Pillow PyAutoGUI
Do not install into one Python installation and run the script with another. In an IDE, compare the selected interpreter with sys.executable.
Linux capture packages
PyAutoGUI’s installation documentation lists scrot, Tkinter, and Python development headers for Linux. Install the packages appropriate to your distribution, then verify the executable is visible to the same user:
which scrot
python -c "import tkinter; print('Tkinter OK')"
Package names vary by distribution, so follow the installation instructions for your release. A successful Python import does not prove that the operating-system capture utility or display connection is available.
macOS and Windows backends
On macOS, PyAutoGUI invokes the system screencapture command. On Windows, the project description says it uses Windows APIs through Python’s built-in ctypes; Pillow remains a screenshot dependency. Check that the script runs in an interactive desktop session rather than a service or disconnected remote session.
Rank #2
When the screenshot is black, blank, or transparent
Check for a real desktop session
A headless process, locked workstation, disconnected remote desktop, virtual machine without a graphical session, or container without display access may have no pixels to capture. Run the diagnostic while logged into the desktop locally, then compare the result with the same script launched by your scheduler or service. Record the operating system and version, Python, PyAutoGUI and Pillow versions, Linux display server/session, and whether the process is local, remote, or headless.
Inspect the image before changing matching code
Open screen-test.png in an image viewer and inspect several pixels. If it is uniformly black or blank, locateOnScreen() is not the problem. Test a small visible region and a full-screen image separately. If both are blank, investigate the display session and platform backend; if only one is blank, check the region coordinates and monitor arrangement.
Linux display differences
Pillow’s current ImageGrab documentation describes X11 capture and says that, when the default X11 display returns no snapshot, it may fall back to gnome-screenshot, grim, or spectacle when installed. This is Pillow behavior for the documented versions, not a guarantee that every PyAutoGUI release or desktop environment will handle Wayland, permissions, or privacy restrictions identically. Identify the active display session and test the installed stack rather than assuming one universal Linux fix.
macOS permissions
PyAutoGUI’s documented backend is screencapture. If a capture is blank or fails on a current macOS release, check the system’s privacy and screen-capture settings for the application that actually launches Python (Terminal, IDE, agent, or service), then retest the minimal script. The cited documentation does not establish one permission procedure for every macOS version.
When the screenshot has the wrong size
Compare logical and actual dimensions
Print both values:
import pyautogui
logical = pyautogui.size()
shot = pyautogui.screenshot()
print("logical:", logical)
print("image:", shot.size)
print("scale:", shot.width / logical.width, shot.height / logical.height)
A saved image with a different size is not automatically a failed write. Multiple monitors, display scaling, remote-desktop settings, and Retina rendering can produce different coordinate spaces.
Retina and high-density displays
Pillow documents macOS Retina captures at twice the logical dimensions by default. Its scale_down=True option was added in Pillow 12.3.0, but you should not assume that a PyAutoGUI screenshot call exposes that Pillow option. Instead, make the screenshot and template use the same scale, or resize one deliberately after capture. Keep region coordinates consistent with the coordinate convention used by the API.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →Historical Windows DPI reports
A PyAutoGUI issue opened December 21, 2016 reports undersized screenshots on Windows 10 with Python 3.5.2, PyAutoGUI 0.9.33, and PIL 3.4.2; the reporter described a DPI-scaling compatibility workaround. Those versions and the date matter. Treat it as a troubleshooting clue, not a current blanket prescription. Confirm dimensions and the process’s DPI context on the Windows, Python, PyAutoGUI, and Pillow versions you actually support.
Test a known region
Use a region whose coordinates are known to be visible:
shot = pyautogui.screenshot(region=(100, 100, 800, 600))
print(shot.size) # expected: (800, 600)
shot.save("known-region.png")
If the region is the requested size but contains the wrong area, your origin, monitor layout, scaling, or window position is wrong. If it is not the requested size, inspect the backend and version combination.
When locateOnScreen() cannot find the image
Prove the target is in the current capture
Save a fresh full-screen image and visually confirm that the target appears at the same rendered size, theme, zoom, and state as the template. A template copied from a Retina display, browser zoom level, dark theme, or different font rendering may not match the current screen.
Recommended Free Tools
import pyautogui
try:
box = pyautogui.locateOnScreen("button-template.png")
print("Found:", box)
except pyautogui.ImageNotFoundException:
print("Template was not found in the current screenshot")
Current PyAutoGUI documentation says a failed locate raises ImageNotFoundException. Handle that exception explicitly instead of treating a missing match as a capture failure.
Match scale and appearance
- Crop the template from the same display scale used at runtime.
- Use the same browser zoom, OS scaling, application theme, and window state.
- Remove transient badges, animations, cursor changes, and dynamic text from the template.
- Capture a smaller, distinctive control rather than a large area containing changing pixels.
- Use a region to reduce unrelated content and speed the search.
Use confidence only with OpenCV
The optional confidence argument requires OpenCV. Install it in the active interpreter before using it:
python -m pip install opencv-python
box = pyautogui.locateOnScreen(
"button-template.png",
confidence=0.85,
region=(0, 0, 1200, 900)
)
print(box)
A lower confidence can increase false positives; it cannot correct an incorrectly scaled or absent target. If matching remains unreliable, log the screenshot, template dimensions, display scale, and search region for each failed run.
A repeatable troubleshooting workflow
- Record the environment. Note OS/version, Python, PyAutoGUI, Pillow, desktop/display session, monitor scaling, and whether execution is local, remote, scheduled, or headless.
- Verify imports. Run
import pyautoguiandimport PILwith the production interpreter. - Check platform dependencies. On Linux, verify the documented packages and capture utility; on macOS, verify the system backend; on Windows, check the actual DPI and desktop context.
- Capture full screen. Save and inspect the image and dimensions before any locate call.
- Capture a region. Confirm that a known rectangle returns the requested dimensions and expected pixels.
- Resolve scale. Compare
pyautogui.size(), image size, monitor scaling, and template size. - Debug matching separately. Confirm the target is present, then adjust template, region, appearance, or OpenCV confidence.
- Retest in the real launcher. A script that works in an interactive terminal may fail under a service, CI runner, remote session, or different user account.
Performance, reliability, and design choices
Full-screen captures and locate calls are not instantaneous. The documentation’s approximate 100-millisecond capture and one-to-two-second locate figures are for a 1,920 × 1,080 screen and should be treated as rough guidance. Prefer a small region, avoid repeated full-screen searches, and wait for a stable UI state before capturing.
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchFor reliable automation, log the capture path, image dimensions, region, display scale, and exception type. Keep a diagnostic screenshot for failures, but protect sensitive screen contents. Do not use a screenshot match as the only confirmation for a destructive action; combine it with application state or a second check.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Or skip the browser setup
If your goal is a clean website image rather than an interactive desktop capture, ScreenshotNeo provides a website screenshot API and MCP server. One GET request returns PNG, JPEG, WebP, or PDF. Before capture it accepts cookie/consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing status.
Here is the cURL call (the ScreenshotNeo docs cover all options):
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
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)
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 buffer = Buffer.from(await res.arrayBuffer());
require('fs').writeFileSync('shot.webp', buffer);
ScreenshotNeo also offers full-page captures with lazy images loaded, CSS-selector element shots, dark mode, device presets and custom viewports, retina scale, PDF paper and page controls, custom CSS and JavaScript, click-before-capture, selector hiding, waits for selectors/delays/network idle, request and resource blocking, headers/cookies/user agents/Authorization, timezone and geolocation, transparent backgrounds, resizing, chosen-TTL caching, signed image links, asynchronous jobs with signed webhooks, bulk capture for up to 100 URLs per call, a usage API, an OpenAPI specification, and compatible parameter names used by other screenshot APIs.
An MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients, so AI agents can capture pages without your own browser setup. Every plan includes every feature: 1,000 shots/month free with no card; Starter is $5 for 3,000, Growth $15 for 15,000, Pro $39 for 60,000, Scale $99 for 250,000, and Business $249 for 1,000,000. Yearly billing gives two months free.
Best Value
Create a free ScreenshotNeo account to use the 1,000 monthly screenshots without a card.
Frequently asked questions
Does saving a PNG prove the screenshot is correct?
No. It proves that an image was produced and written. Inspect its pixels, dimensions, and visible content in the same execution environment.
Why does a template work on one monitor but not another?
Rendered size, DPI scaling, browser zoom, fonts, theme, and monitor coordinates can differ. Capture the template at the runtime scale or normalize both images.
Can PyAutoGUI capture a browser page without the browser being visible?
PyAutoGUI captures the desktop, so the browser must be rendered in an accessible graphical session. For a server-side website image, use an API such as ScreenshotNeo instead.
What should I include in a bug report?
Include OS and display session, Python/PyAutoGUI/Pillow versions, interpreter path, monitor scaling, whether the run is remote or headless, the minimal script, reported and actual image sizes, and a sanitized sample image or pixel inspection.
Frequently Asked Questions
Does saving a PNG prove the screenshot is correct?
No. It proves that an image was produced and written. Inspect its pixels, dimensions, and visible content in the same execution environment.
Why does a template work on one monitor but not another?
Rendered size, DPI scaling, browser zoom, fonts, theme, and monitor coordinates can differ. Capture the template at the runtime scale or normalize both images.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Can PyAutoGUI capture a browser page without the browser being visible?
PyAutoGUI captures the desktop, so the browser must be rendered in an accessible graphical session. For a server-side website image, use an API such as ScreenshotNeo instead.
What should I include in a bug report?
Include OS and display session, Python/PyAutoGUI/Pillow versions, interpreter path, monitor scaling, whether the run is remote or headless, the minimal script, reported and actual image sizes, and a sanitized sample image or pixel inspection.
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.

