Skip to content

milouk/whatsapp-tracker

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

WhatsApp Activity Monitor

Python CLI that monitors a WhatsApp user's device activity using RTT-based side-channel analysis. Sends desktop notifications when the target is detected as online, typing, recording, on a call, or reading your chat. Logs all activity to CSV and can generate visual reports.

Based on the Careless Whisper research paper (USENIX Security '24).

demo

How It Works

  1. Connects to WhatsApp Web multi-device protocol via neonize (Python bindings for whatsmeow)
  2. Sends silent "delete" probes (revoke requests for non-existent message IDs) to the target every ~1–3 seconds
  3. Measures Round-Trip Time (RTT) from the delivery acknowledgment
  4. Auto-calibrates a threshold from the running median RTT (or accepts a manual value via --threshold)
  5. Classifies device state per-device:
    • Online — moving average of last 3 RTTs is below threshold
    • Standby — moving average is above threshold
    • OFFLINE — no ACK received within 10 seconds
  6. Subscribes to WhatsApp presence events to detect composing, recording, and calls
  7. Monitors read receipts to detect when the target opens your chat
  8. Logs every state change to a CSV file for later analysis
  9. Renders a live RTT chart in the terminal using Unicode block characters

Requirements

  • Python >= 3.10
  • libmagic system library (required by neonize)

Install

# macOS
brew install libmagic

# Debian/Ubuntu
sudo apt-get install libmagic1
# Clone and set up
git clone https://github.com/milouk/whatsapp-tracker.git
cd whatsapp-tracker
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt

Optional — for rendering profile pictures in the terminal (half-block mode):

pip install Pillow

Usage

Monitoring

# First run — shows a QR code in the terminal, scan it with WhatsApp on your phone
python3 -m wa_tracker --phone 3069XXXXXXXX

# Subsequent runs reuse the saved session (no QR needed)
python3 -m wa_tracker --phone 3069XXXXXXXX

# Set a manual RTT threshold (ms) instead of auto-calibration
python3 -m wa_tracker --phone 3069XXXXXXXX --threshold 1000

# Only get notified on typing, recording, and calls (skip RTT-based online detection)
python3 -m wa_tracker --phone 3069XXXXXXXX --presence-only

# Silent operation (no sounds, no desktop notifications — terminal output only)
python3 -m wa_tracker --phone 3069XXXXXXXX --no-notify

Generating Activity Graphs

After collecting data, generate a 3-panel activity report from the CSV log:

# Open graph in an interactive window
python3 -m wa_tracker --graph 3069XXXXXXXX

# Save to a file
python3 -m wa_tracker --graph 3069XXXXXXXX --graph-output report.png

The graph includes:

  1. Activity Timeline — color-coded bar (green = Online, yellow = Standby, red = Offline) with typing/recording markers
  2. Hourly Distribution — minutes spent online per hour of day
  3. Session Durations — bar chart of each online session length with average line

Data is read from wa_activity_<phone>.csv which is created automatically during monitoring.

CLI Reference

Flag Default Description
--phone (required for monitoring) Target phone number with country code (e.g. 3069XXXXXXXX)
--threshold auto (median × 0.9) RTT threshold in ms — below = Online, above = Standby
--method delete Probe method: delete (completely silent) or reaction (low visibility)
--db wa_tracker.sqlite3 Path to the session database file
--debug off Print verbose debug output (event codes, probe IDs, RTT per-ACK)
--no-sound off Disable notification sounds (still shows desktop notifications)
--no-notify off Disable all desktop notifications and sounds
--presence-only off Only notify on typing, recording, calls, and read receipts — skip RTT-based online detection
--mask off Mask phone number in all output (e.g. 3069XXXXXXXX) — useful for screenshots and recordings
--graph PHONE Generate an activity graph from CSV and exit (does not start monitoring)
--graph-output FILE Save graph to file instead of opening an interactive window

Notifications

On macOS: native Notification Center alerts + system sound (Ping.aiff). On Linux/Windows: terminal bell (\a) + printed message.

Notification triggers:

  • Target device goes online (RTT drops below threshold)
  • Target starts typing
  • Target starts recording audio
  • Target starts a voice or video call
  • Target opens your chat (read receipt detected)

Cross-type deduplication ensures you aren't spammed — e.g. an "online" notification clears when the target goes to standby, so you'll be notified again next time they come online.

Live Terminal Output

The monitor redraws a status box in-place showing real-time metrics, per-device state, and an RTT sparkline chart:

╔════════════════════════════════════════════════════════════════╗
║ 🟢 Active — 14:32:15                                         ║
╠════════════════════════════════════════════════════════════════╣
║ Target:     3069XXXXXXXX                                      ║
║ Median:     412ms                                             ║
║ Threshold:  371ms  (auto)                                     ║
║ Activity:   Typing                                            ║
║ ──────────────────────────────────────────────────────────────║
║ 🟢 Phone             RTT:  234ms  EMA:  287ms  Active        ║
║ 🟡 Companion #1      RTT:  890ms  EMA:  756ms  Idle          ║
║ ──────────────────────────────────────────────────────────────║
║  480│┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄       ║
║     │                                                         ║
║  371│┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄▃▃┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄       ║
║     │          ▅▆▇█▆▅▃▂▁                                      ║
║  200│▁▂▃▄▅▆▇█                                                 ║
║     └─────────────────────────────────────────────────────     ║
╚════════════════════════════════════════════════════════════════╝
  • Header — overall state icon + label + timestamp
  • Metrics — target number, running median, auto/manual threshold, current activity
  • Per-device rows — each linked device (Phone, Companion #1, etc.) with its own RTT, EMA, and state
  • RTT chart — auto-scaled sparkline with dashed threshold line; green bars = below threshold, yellow = above

On first connect the monitor also fetches and displays the target's profile info (name, about, business name, profile picture, linked devices).

Probe Methods

Method Flag Visibility How
Delete --method delete Completely silent Sends a "revoke" for a non-existent message ID. Target sees nothing.
Reaction --method reaction Low visibility Sends a reaction to a non-existent message. May briefly flash on the target's device.

The delete method is the default and recommended — it produces zero visible artifacts on the target's device.

Docker

# Build the image
docker build -t wa-tracker .

# First run — interactive for QR code scanning, persist session via a named volume
docker run -it -v wa_tracker_data:/app/data wa-tracker --phone 3069XXXXXXXX

# Subsequent runs — detached, session is already saved in the volume
docker run -d -v wa_tracker_data:/app/data wa-tracker --phone 3069XXXXXXXX

# With additional flags
docker run -d -v wa_tracker_data:/app/data wa-tracker \
  --phone 3069XXXXXXXX --threshold 1000 --presence-only

# Follow live output
docker logs -f <container_id>

Note: Desktop notifications are not available inside Docker. The container still prints all status updates to stdout — use docker logs -f to follow along.

Activity Logging

During monitoring, all state transitions are appended to wa_activity_<phone>.csv:

timestamp,state,presence_event
2025-02-13T14:32:15.123,Online,
2025-02-13T14:32:18.456,Online,composing
2025-02-13T14:35:02.789,Standby,
2025-02-13T14:40:11.012,OFFLINE,
Column Description
timestamp ISO 8601 with milliseconds
state Online, Standby, or OFFLINE (RTT-based)
presence_event composing, recording, on_call, reading, or empty

The file is created automatically on first run and appended to on subsequent runs. Use --graph to visualize it.

Project Structure

whatsapp-tracker/
├── wa_tracker/              # Python package
│   ├── __init__.py          # Package docstring
│   ├── __main__.py          # Entry point (python -m wa_tracker)
│   ├── cli.py               # Argument parser
│   ├── main.py              # Client setup, event wiring, banner
│   ├── monitor.py           # Core WAMonitor (probes, state, events, calls)
│   ├── constants.py         # Timing, thresholds, protocol enums
│   ├── models.py            # DeviceState dataclass
│   ├── notify.py            # OS notifications and sound
│   ├── logger.py            # CSV activity logger
│   ├── graph.py             # Matplotlib activity report (3-panel)
│   ├── chart.py             # Live terminal RTT chart (Unicode blocks)
│   └── rendering.py         # Profile picture rendering (iTerm2 / half-blocks)
├── requirements.txt         # Python dependencies
├── Dockerfile               # Container image definition
├── .gitignore
└── .dockerignore

Auto-generated files (gitignored):

File Description
wa_tracker.sqlite3 WhatsApp session database — delete to re-scan QR
wa_activity_*.csv Per-target activity logs