PyWinCtl
raw JSON → 0.4.1 verified Fri May 01 auth: no python
PyWinCtl is a cross-platform Python library (Windows, macOS, Linux with X11/Wayland) for getting information about and controlling on-screen windows. Version 0.4.1 supports Python 3.9+ and provides window enumeration, activation, resizing, moving, and property retrieval. Release cadence is irregular, with major features added every few months.
pip install pywinctl Common errors
error AttributeError: module 'pywinctl' has no attribute 'PyWinCtl' ↓
cause Attempting to import 'PyWinCtl' as a class when it is the module name.
fix
Use 'import pywinctl' and then call functions like pywinctl.getAllWindows().
error TypeError: 'NoneType' object is not iterable ↓
cause getAllWindows() returns None on unsupported platforms or if the backend fails.
fix
Check if the result is None before iterating: windows = pywinctl.getAllWindows() or []
error OSError: [WinError 5] Access is denied ↓
cause On Windows, trying to manipulate a window owned by another process (e.g., UIPI) without proper privileges.
fix
Run the script with elevated permissions (admin) or target windows that allow external control.
error ModuleNotFoundError: No module named 'pywinctl._pywinctl_osx' ↓
cause Trying to import internal submodules directly; they are platform-specific and not intended for direct use.
fix
Use the public API: 'import pywinctl' and let the library handle the backend selection.
Warnings
gotcha On Linux with Wayland, getActiveWindow() may return None unless 'unsafe mode' is enabled. Enable by setting environment variable PYWNCTL_WAYLAND_UNSAFE=1 before import. ↓
fix os.environ['PYWNCTL_WAYLAND_UNSAFE'] = '1' before importing pywinctl.
deprecated The method getDisplay() is deprecated in v0.4 and replaced by getMonitor(). ↓
fix Use getMonitor() instead of getDisplay().
breaking MacOS: MacOSNSWindow was removed in v0.4. All window operations now use AppleScript. Code that directly references MacOSNSWindow will break. ↓
fix Use the standard pywinctl API; class MacOSNSWindow no longer exists.
gotcha Window.moveTo() and resizeTo() expect integer coordinates. Passing floats may cause silent failure or unexpected behavior. ↓
fix Always convert to int: win.moveTo(int(x), int(y)).
Imports
- PyWinCtl wrong
from pywinctl import PyWinCtlcorrectimport pywinctl as pwc - Window wrong
from pywinctl import Window; win = Window()correctimport pywinctl; win = pywinctl.getAllWindows()[0] - getAllWindows wrong
import pywinctl; pywinctl.getWindows()correctimport pywinctl; pywinctl.getAllWindows()
Quickstart
import pywinctl
# Get all windows
windows = pywinctl.getAllWindows()
for win in windows:
print(f'{win.title}: {win.bbox}')
# Get active window
active = pywinctl.getActiveWindow()
if active:
print('Active window title:', active.title)
# Move and resize window
win = windows[0]
win.moveTo(100, 100)
win.resizeTo(800, 600)
# Check if window is visible
print('Visible:', win.isVisible)