
Monitor your local neighbourhood's bluetooth activity
Bluetooth Neighborhood - Track BLE devices in your area and analyze traffic patterns.
WARNING: Alpha Software
This project is in early development and is not ready for production use. Features may change, break, or be removed without notice. Use at your own risk. Data collected should be treated as experimental.
Main dashboard showing device list with filtering, search, and real-time statistics
Tabbed configuration page — Alerts, Operations, Groups, and Security
Intel page with project information and capabilities overview
This project was inspired by the WhisperPair vulnerability (CVE-2025-36911), which highlighted privacy risks in Bluetooth devices.
Thousands of Bluetooth devices surround us at all times: phones, cars, TVs, headphones, hearing aids, delivery vehicles, and more. Bluehood demonstrates how simple it is to passively detect these devices and observe patterns in their presence.
With enough data, you could potentially:
This metadata can reveal surprisingly personal information without any active interaction with the devices.
Bluehood is an educational tool to raise awareness about Bluetooth privacy. It's a weekend project, but the implications are worth thinking about.
Bluehood is a Bluetooth scanner that:
? to view)Prerequisites — Linux hosts only
Bluehood communicates with your Bluetooth adapter via BlueZ, the Linux Bluetooth stack. BlueZ must be installed and running on the host before starting the container — the Docker image itself does not include it.
# Debian / Ubuntu (including Ubuntu Server) sudo apt install bluez sudo systemctl enable --now bluetooth # Arch Linux sudo pacman -S bluez bluez-utils sudo systemctl enable --now bluetoothWithout BlueZ on the host you'll see an error like:
BLE scan error: [org.freedesktop.DBus.Error.ServiceUnknown] The name org.bluez was not provided by any .service files
# Create a docker-compose.yml or download the one from this repo
# Then start with Docker Compose
docker compose up -d
# View logs
docker compose logs -f
The Docker image is available on GitHub Container Registry:
ghcr.io/dannymcc/bluehood:latest
The web dashboard will be available at http://localhost:8080
sudo apt install bluez && sudo systemctl enable --now bluetooth)Note: Older adapters (Bluetooth 2.x/3.x) do not support BLE scanning. If your adapter lacks BLE Central role support, you will see:
No Bluetooth adapters with BLE 'central' role found.
Note: Docker runs in privileged mode with host networking for Bluetooth access. This is required for BLE scanning.
Bluehood requires a BLE-capable Bluetooth adapter (Bluetooth 4.0 or later) with Central role support. Older Bluetooth 2.x/3.x adapters do not support BLE scanning and will not work.
If your adapter does not support the BLE Central role, Bluehood will exit with:
No Bluetooth adapters with BLE 'central' role found
You can check your adapter's capabilities with bluetoothctl show and look for central in the supported roles.
# Install system dependencies (Arch Linux)
sudo pacman -S bluez bluez-utils python-pip
# Install system dependencies (Debian/Ubuntu)
sudo apt install bluez python3-pip
# Clone and install
git clone https://github.com/dannymcc/bluehood.git
cd bluehood
pip install -e .
Bluetooth scanning requires elevated privileges. Choose one:
Run as root (simplest):
sudo bluehood
Grant capabilities to Python:
sudo setcap 'cap_net_admin,cap_net_raw+eip' $(readlink -f $(which python))
bluehood
Use systemd service (recommended for always-on):
sudo cp bluehood.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now bluehood
Bluehood works natively on macOS without Docker. macOS uses CoreBluetooth instead of BlueZ, which is handled automatically by the bleak library.
# Clone the repository
git clone https://github.com/dannymcc/bluehood.git
cd bluehood
# Create a virtual environment
python3 -m venv .venv
source .venv/bin/activate
# Install
pip install -e .
# Run
python -m bluehood.daemon
The web dashboard will be available at http://localhost:8080
Note: On first run, macOS will prompt you to allow Bluetooth access. You must grant this permission for scanning to work.
# Start with web dashboard (default port 8080)
bluehood
# Specify a different port
bluehood --port 9000
# Use a specific Bluetooth adapter
bluehood --adapter hci1
# Use separate adapters for BLE and classic scanning (concurrent)
bluehood --adapter hci0 --classic-adapter hci1
# List available adapters
bluehood --list-adapters
# Disable web dashboard (scanning only)
bluehood --no-web
# Enable Prometheus metrics exporter on port 9199
bluehood --metrics-port 9199
The dashboard provides:
/settings#operations)Enable screenshot mode from the sidebar to obfuscate sensitive data before sharing screenshots:
AA:BB:XX:XX:XX:XX)Da********)Bluehood can send push notifications via ntfy.sh, a free, open-source notification service.
bluehood-myname-alerts)Data is stored in ~/.local/share/bluehood/bluehood.db (SQLite).
Override location with environment variables:
BLUEHOOD_DATA_DIR - Directory for data filesBLUEHOOD_DB_PATH - Direct path to database fileNote: Heartbeat and pruning settings can be configured from the web UI (Settings > Operations) or via environment variables. GUI values take priority over env vars.
Bluehood classifies devices using multiple signals (in priority order):
Modern devices randomize their MAC addresses for privacy. Bluehood:
Bluehood analyzes sighting timestamps to detect patterns:
Example patterns: "Daily, evenings (5PM-9PM)", "Weekdays, morning (8AM-12PM)"
Bluehood detects devices that frequently appear together within a configurable time window. This can reveal:
Based on RSSI signal strength, devices are classified into proximity zones:
Tracks how long devices spend in range by analyzing gaps between sightings. A configurable gap threshold (default 15 minutes) determines when a new "session" begins.
Bluehood can expose metrics for Prometheus scraping. Enable by setting the BLUEHOOD_METRICS_PORT environment variable or the --metrics-port CLI flag.
# Via environment variable
export BLUEHOOD_METRICS_PORT=9199
# Via CLI
bluehood --metrics-port 9199
Metrics are served at http://host:9199/metrics.
A ready-to-import Grafana dashboard is included at grafana/bluehood-dashboard.json. Import it via the Grafana UI (Dashboards > Import) or the API:
curl -X POST "http://localhost:3000/api/dashboards/db" \
-H "Authorization: Bearer <your-api-key>" \
-H "Content-Type: application/json" \
-d "{\"dashboard\": $(cat grafana/bluehood-dashboard.json), \"overwrite\": true}"
bluetoothctl power onbluehood --list-adaptersBLE scan error: org.freedesktop.DBus.Error.ServiceUnknown / The name org.bluez was not provided
BlueZ is not installed or not running on the host. Fix:
sudo apt install bluez # Debian/Ubuntu
sudo systemctl enable --now bluetooth
docker compose restart
General checklist:
systemctl status bluetoothbluetoothctl listContributions welcome! Please open an issue or PR on GitHub.
MIT License - See LICENSE for details.
This tool is for educational purposes only. Be mindful of privacy laws in your jurisdiction when monitoring Bluetooth devices. The author is not responsible for any misuse of this software.
Created by Danny McClelland
| Variable | Default | Description |
|---|
PUID | 1000 | UID for the container user — set to match your host user (id -u) when using bind mounts |
PGID | 1000 | GID for the container user — set to match your host group (id -g) when using bind mounts |
TZ | UTC | Container timezone (e.g., Europe/London) |
BLUEHOOD_ADAPTER | auto | Bluetooth adapter for BLE scanning (e.g., hci0) |
BLUEHOOD_CLASSIC_ADAPTER | same as BLUEHOOD_ADAPTER | Separate adapter for classic Bluetooth scanning (e.g., hci1). When set to a different adapter, BLE and classic scans run concurrently. |
BLUEHOOD_DATA_DIR | /data | Database storage directory |
BLUEHOOD_METRICS_PORT | disabled | Prometheus metrics port (e.g., 9199) |
BLUEHOOD_HEARTBEAT_URL | disabled | URL to POST heartbeat check-ins (e.g., a healthchecks.io or uptime-kuma push URL) |
BLUEHOOD_HEARTBEAT_INTERVAL | 300 | Seconds between heartbeat check-ins |
BLUEHOOD_PRUNE_DAYS | 0 (disabled) | Auto-delete sightings older than N days to free storage |
| Key | Action |
|---|
/ | Focus search bar |
r | Refresh device list |
c | Toggle compact view |
w | Toggle watch on selected device |
Esc | Close modal |
? | Show keyboard shortcuts |
| Metric | Type | Description |
|---|
bluehood_scans_total | Counter | Total scan cycles completed |
bluehood_scan_errors_total | Counter | Scan errors (label: scan_type) |
bluehood_sightings_total | Counter | Total device sightings recorded |
bluehood_new_devices_total | Counter | New unique devices discovered |
bluehood_last_scan_devices | Gauge | Devices in last scan (label: scan_type) |
bluehood_devices_total | Gauge | Unique devices in DB (label: bt_type) |
bluehood_devices_active | Gauge | Devices seen in last 5 minutes |
bluehood_devices_watched | Gauge | Watched device count |
bluehood_devices_ignored | Gauge | Ignored device count |
bluehood_scan_duration_seconds | Histogram | Scan cycle duration |
bluehood_device_rssi_dbm | Histogram | RSSI distribution of BLE devices |
bluehood_build_info | Info | Version information |