Hook: Stop Copy‑Pasting Numbers from a Dashboard with No API
You stare at a web‑based dashboard, manually copy‑pasting a handful of numbers every hour. The page has no API, no export button, and the data changes fast enough that a manual workflow becomes a bottleneck. What if you could let your Linux box watch a specific region of the screen, turn the pixels into text, and trigger an alert the moment a value changes?
In this post I walk through the exact setup I use on my home server: a PipeWire screen capture, a tiny grim script to grab a region, Tesseract OCR to read the numbers, and a Bash loop that notifies me via notify-send when the value differs from the previous run.
1. Prerequisites
| Tool | Why you need it |
|---|---|
pipewire (with pw-cli and pw-top) | Modern screen‑capture backend on Wayland |
grim | Simple command‑line screenshot utility that works with PipeWire |
tesseract-ocr | OCR engine that can read the captured image |
imagemagick (optional) | Pre‑process the image for better OCR accuracy |
jq (optional) | Parse JSON if you decide to log results |
notify-send (or any other notifier) | Show a desktop notification when the value changes |
All of these packages are available in the default repositories of most distros:
# Debian/Ubuntu sudo apt install pipewire grim tesseract-ocr imagemagick jq libnotify-bin # Fedora sudo dnf install pipewire grim tesseract imagemagick jq libnotify 2. Capture a Fixed Region with grim
grim can capture the whole screen or a rectangle defined by geometry. I store the geometry in a variable so I can tweak it without editing the script.
# Geometry: X,Y,W,H (pixels) REGION="1200,300,250,80" # Adjust to the exact location of the number on your dashboard IMG_PATH="/tmp/dashboard.png" capture_region() { grim -g "$REGION" "$IMG_PATH" } Run grim -g "$REGION" - to preview the region in a viewer like feh if you need to fine‑tune the coordinates.
3. Pre‑process the Image (Optional but Recommended)
Tesseract works best with high‑contrast, binarized images. A quick ImageMagick pipeline removes noise and boosts contrast.
preprocess_image() { convert "$IMG_PATH" \ -colorspace Gray \ -level 20%,80% \ -type Bilevel \ "$IMG_PATH" } If the dashboard already uses a clean font on a solid background you can skip this step.
4. Run Tesseract and Extract the Number
We only need the plain text output, so we tell Tesseract to write to stdout (-). The --psm 7 mode treats the image as a single line of text, which speeds up processing.
extract_number() { tesseract "$IMG_PATH" stdout --psm 7 2>/dev/null | tr -d '\n' | tr -d ' ' } The tr commands strip newlines and spaces, leaving a compact string like 42.7.
5. Detect Changes and Notify
The core loop stores the previous reading in a temporary file. When the new reading differs, we fire a notification.
STATE_FILE="/tmp/dashboard_last.txt" check_change() { local current=$(extract_number) local previous="" [ -f "$STATE_FILE" ] && previous=$(cat "$STATE_FILE") if [[ "$current" != "$previous" ]]; then notify-send "Dashboard Update" "Value changed: $previous → $current" echo "$current" > "$STATE_FILE" fi } 6. Glue It All Together
A simple infinite loop with a sleep interval does the job. I run this as a systemd user service so it survives reboots and logs to journalctl.
#!/usr/bin/env bash while true; do capture_region preprocess_image # comment out if you skipped pre‑processing check_change sleep 60 # check once per minute; adjust as needed done Save the script as ~/bin/dashboard-watcher.sh, make it executable (chmod +x), and test it manually before creating the service.
7. Optional: Systemd User Service
Create ~/.config/systemd/user/dashboard-watcher.service:
[Unit] Description=Watch dashboard region and alert on change After=network.target [Service] ExecStart=%h/bin/dashboard-watcher.sh Restart=on-failure [Install] WantedBy=default.target Enable and start it:
systemctl --user daemon-reload systemctl --user enable --now dashboard-watcher.service You can view logs with journalctl --user -u dashboard-watcher.service.
8. Tweaking for Accuracy
- Font size & DPI – Larger fonts and higher DPI screenshots improve OCR confidence.
- Whitelist characters – If you only expect numbers and a decimal point, add
tesseractconfigtessedit_char_whitelist 0123456789. - Language data – Use
tesseract-ocr-eng(default) unless the dashboard uses a different script.
9. What This Solves
- Zero manual copying – The script runs unattended.
- Immediate alerts – Get a desktop pop‑up (or replace
notify-sendwith an email/SMS hook) the moment a KPI shifts. - Low overhead – Each cycle consumes < 0.2 s of CPU on a modest VM.
You can extend the pattern to multiple regions, feed the numbers into a time‑series database, or trigger a Home Assistant automation.
I build sites and automations for small businesses at dreamfuturestech.com.