Own your screen time data.
Collect, analyze, and visualize your Mac and iOS device usage — without Apple's restrictions.
Quick Start • Features • Configuration • Dashboard • Troubleshooting
- Mac Data — Reads directly from Apple's
knowledgeC.dbScreen Time database - iOS Data — Syncs iPhone and iPad via iCloud using aw-import-screentime
- Multi-Device — Track multiple iPhones, iPads with custom names
- Home Assistant — Creates sensors for dashboards and automations
- InfluxDB + Grafana — Long-term storage with beautiful visualizations
- Deduplication — Run as often as you want, no duplicate entries
- Automation — Built-in launchd support for scheduled collection
flowchart LR
subgraph Sources
iPhone[iPhone]
iPad[iPad]
Mac[Mac]
end
subgraph Collection
Biome[(iCloud Biome)]
KnowledgeDB[(knowledgeC.db)]
Collector[collector.py]
end
subgraph Export
CSV[(screentime.csv)]
Exporter[exporter.py]
end
subgraph Destinations
HA[Home Assistant]
Influx[InfluxDB]
Grafana[Grafana]
end
iPhone --> Biome --> Collector
iPad --> Biome
Mac --> KnowledgeDB --> Collector
Collector --> CSV --> Exporter
Exporter --> HA
Exporter --> Influx --> Grafana
- macOS Ventura, Sonoma, or Sequoia
- Python 3.10+
- iOS devices synced via iCloud
- Terminal with Full Disk Access
# Clone the repository
git clone https://github.com/nichtlegacy/screentime.git
cd screentime
# Install aw-import-screentime (for iOS data)
git clone https://github.com/ActivityWatch/aw-import-screentime.git
cd aw-import-screentime && python3 -m venv .venv && .venv/bin/pip install -e . && cd ..
# Install Python dependencies
pip3 install python-dotenv pandas requests
# Configure
cp .env.example .env- Open System Settings → Privacy & Security → Full Disk Access
- Add Terminal.app (from
/Applications/Utilities/) - Restart Terminal
python3 run.pyExample Output
=== Screen Time Collection - 2026-02-08T14:30:00 ===
First run - extracting all available data
[14:30:01] Extracting iPhone 15 Pro data...
[iPhone 15 Pro] 847 new entries found
[14:30:03] Extracting Mac data...
[Mac] 1203 new entries found
iPhone 15 Pro: 847 Events
Mac: 1203 Events
Success: 2050 NEW entries added.
=== Screen Time Export - 2026-02-08T14:30:05 ===
--- InfluxDB Export ---
[InfluxDB] 2050 data points written
--- Home Assistant Export ---
[HA] sensor.screentime_total = 245.5
[HA] sensor.screentime_iphone_15_pro = 180.0
[HA] sensor.screentime_mac = 65.5
Export completed.
cd aw-import-screentime && .venv/bin/aw-import-screentime devicesTest each device to identify it:
.venv/bin/aw-import-screentime events preview --device DEVICE-ID-HERE --since 1dDEVICE_ID=CA06AED8-XXXX-XXXX-XXXX-XXXXXXXXXXXX# Format: Name:UUID,Name:UUID
DEVICES=iPhone 15 Pro:CA06AED8-...,iPad Pro:51FBF7C3-...,iPhone Work:7B2A9F1C-...Each device appears separately in the dashboard and Home Assistant.
# === iOS Devices ===
DEVICE_ID=CA06AED8-XXXX-XXXX-XXXX-XXXXXXXXXXXX
# Or for multiple: DEVICES=iPhone 15 Pro:UUID1,iPad:UUID2
# === Home Assistant ===
HA_URL=http://homeassistant.local:8123
HA_TOKEN=your-long-lived-access-token
# === InfluxDB ===
INFLUX_URL=http://localhost:8086
INFLUX_TOKEN=your-influx-token
INFLUX_ORG=home
INFLUX_BUCKET=screentimeSensors are created dynamically based on your configured devices:
| Sensor | Description |
|---|---|
sensor.screentime_total |
Total screen time today (minutes) |
sensor.screentime_<device> |
Per-device usage (e.g., screentime_iphone_15_pro) |
sensor.screentime_top_app |
Most used app today |
sensor.screentime_by_category |
Breakdown by category |
sensor.screentime_top_apps |
Top 10 apps |
Creating a Home Assistant Token
- Open Home Assistant → Profile → Security
- Under Long-lived access tokens, click Create Token
- Name it and copy the token to your
.env
Setting up InfluxDB 2.x
- Install InfluxDB 2.x (Docker, Unraid, or native)
- Create a bucket named
screentime - Generate an API token with read/write access
- Add credentials to
.env
- Open Grafana → Dashboards → Import
- Upload
grafana/screentime-dashboard.json - Select your InfluxDB datasource
| Panel | Description |
|---|---|
| Total / Per-Device | Screen time stats for each device |
| Top Apps | Top 10 apps overall and per device |
| By Category | Social, Productivity, Media, etc. |
| Timeline | Hourly usage with device stacking |
The Source filter dynamically loads all devices from your data.
Run automatically every 6 hours with launchd:
cp examples/launchd.plist ~/Library/LaunchAgents/com.apple-screentime-exporter.plist
# Edit paths in the plist file
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.apple-screentime-exporter.plist| Action | Command |
|---|---|
| Run manually | python3 run.py |
| Trigger now | launchctl kickstart gui/$(id -u)/com.apple-screentime-exporter |
| Stop | launchctl bootout gui/$(id -u)/com.apple-screentime-exporter |
| View logs | tail -f logs/launchd.log |
Note: Add your Python binary to Full Disk Access for launchd to work.
timestamp,app,title,duration,source
2026-02-08T14:30:00+01:00,com.google.Chrome,Chrome,45.5,Mac
2026-02-08T14:35:00+01:00,com.zhiliaoapp.musically,TikTok,120.0,iPhone 15 ProMeasurement: screentime
Tags: source, app, title, category
Fields: duration (seconds)
Categories: Social, Productivity, Browser, Communication, Media, Utilities, Shopping, Finance, System, Other
apple-screentime-exporter/
├── grafana/
│ └── screentime-dashboard.json
├── src/
│ ├── config.py # App mappings & categories
│ ├── collector.py # Data collection
│ └── exporter.py # HA + InfluxDB export
├── examples/
│ └── launchd.plist
├── run.py
└── .env.example
| Problem | Solution |
|---|---|
knowledgeC.db not readable |
Grant Full Disk Access to Terminal |
Device not found |
Ensure device is synced with iCloud |
| No iOS data | Check if ~/Library/Biome/ exists |
| launchd not working | Add Python to Full Disk Access |
| No devices configured | Set DEVICE_ID or DEVICES in .env |
- Inspired by Boaz Sobrado's blog post
- iOS data via aw-import-screentime
MIT License © 2026
