On legacy Debian 11 (Bullseye) and older X11 desktops, taking a screenshot of an active desktop session remotely over SSH was straightforward using scrot:
DISPLAY=:0.0 scrot -o screenshot.jpg
In Python:
import os
os.environ["DISPLAY"] = ":0.0"
os.system("scrot -o screenshot.jpg")
Wayland on Debian 12 (Bookworm)
On Debian 12 (and Raspberry Pi OS Bookworm with Wayfire or labwc), Wayland is the default compositor. Because Wayland enforces strict security isolation between graphical clients and display sockets, scrot will fail with the error:
failed to create display
To take screenshots under Wayland, use the native grim utility (pre-installed on Raspberry Pi OS). When calling grim over SSH from a non-interactive TTY, you must explicitly export both WAYLAND_DISPLAY and XDG_RUNTIME_DIR:
WAYLAND_DISPLAY=wayland-1 XDG_RUNTIME_DIR=/run/user/1000 grim screenshot.png
Python Automation Script
To capture screenshots programmatically in Python over SSH:
import os
pngfile = "/tmp/screenshot.png"
os.environ["WAYLAND_DISPLAY"] = "wayland-1"
os.environ["XDG_RUNTIME_DIR"] = "/run/user/1000"
os.system(f"grim {pngfile}")
echo $WAYLAND_DISPLAY and echo $XDG_RUNTIME_DIR from a terminal inside the active desktop session, or check the socket files in /run/user/$(id -u)/.