Findphone: Locate a nearby Bluetooth device by signal strength

helsinkiandrew1 pts0 comments

GitHub - ben-z/findphone: Locate a nearby Bluetooth device by signal strength, from the macOS command line — for when Find My isn't available · GitHub

/" data-turbo-transient="true" />

Skip to content

Type / to search

Sign in<br>Sign upAppearance settings

You signed in with another tab or window. Reload to refresh your session.<br>You signed out in another tab or window. Reload to refresh your session.<br>You switched accounts on another tab or window. Reload to refresh your session.

Dismiss alert

{{ message }}

ben-z

findphone

Public

Notifications<br>You must be signed in to change notification settings

Fork<br>40

Star<br>262

main

BranchesTags

Go to file

CodeOpen more actions menu

Folders and files<br>NameNameLast commit message<br>Last commit date<br>Latest commit

History<br>13 Commits<br>13 Commits

.github/workflows

.github/workflows

Sources/findphone

Sources/findphone

scripts

scripts

.gitignore

.gitignore

Package.swift

Package.swift

README.md

README.md

View all files

Repository files navigation

findphone

Locate a nearby Bluetooth device by signal strength, from the command line.

Built for the case where Find My is unavailable — for example when a device is<br>enrolled in MDM that disables it — but the device is still within Bluetooth<br>range and you just need to know which corner of the room it is in.

Install

Grab the universal binary from Releases:

tar -xzf findphone-macos-universal.tar.gz<br>xattr -dr com.apple.quarantine findphone<br>./findphone --help

It is unsigned, so macOS quarantines it on download; the xattr line clears<br>that. Requires macOS 13 or later.

Build

swift build -c release<br>cp .build/release/findphone ~/bin/findphone

Requires the Swift toolchain from Xcode Command Line Tools. No dependencies.<br>For a universal arm64 + x86_64 binary, which is what CI ships:

./scripts/build-universal.sh dist

Use

findphone # survey mode: every nearby Apple handheld, by signal<br>findphone iphone # hunt mode: track one device by name (case-insensitive)<br>findphone --list # paired devices and their addresses

Add --sound in hunt mode for clicks that speed up as you close in, the way a<br>parking sensor does — about one a second across a room, rising to a buzz once<br>the signal reaches roughly -50 dBm, which is about where a laptop sits on top<br>of the phone. It lets you sweep a room by ear instead of watching the screen.<br>Clicks stop when contact goes stale, so silence means no signal rather than no<br>device.

This is not a Geiger counter, despite sounding a little like one. A counter<br>clicks once per detected particle and its rate is the measurement; here the<br>rate is computed from the smoothed signal. Packets arrive on a fixed 0.3s<br>polling timer, so their arrival rate says almost nothing about distance.

Add --redact if you are recording the screen. It masks Bluetooth addresses,<br>and in survey mode replaces discovered device names with the device kind,<br>since those names are not always yours. A public address is a stable hardware<br>identifier and, unlike a BLE advertising address, does not rotate, so it is<br>worth keeping out of a video.

Two things stay visible deliberately: the name you typed in hunt mode, and the<br>names in --list, because picking a target means reading them. --list is<br>not safe to film even with --redact.

Walk slowly and watch the bar. The reading is signal strength in dBm, which is<br>negative and closer to zero when nearer:

dBm<br>Rough meaning

-45 up<br>arm's reach

-60<br>same table

-72<br>same room

-85<br>far, or behind cover

below<br>very far, or shielded

Signal strength is a coarse proxy for distance. Metal, walls and human bodies<br>attenuate it heavily, so a device in a filing cabinet two metres away can read<br>the same as one fifteen metres away in open air. Trust the trend as you move,<br>not any single number.

How it works

Three sources feed one reading, in descending order of quality:

GATT link — once connected to the device over BLE, readRSSI() returns<br>a fresh measurement about three times a second. This is the good one.

BLE advertisements — passively observed. Apple devices rotate their<br>advertising addresses roughly every fifteen minutes and only include the<br>device name on occasional packets, so this source is sparse.

Classic link RSSI — read from system_profiler SPBluetoothDataType,<br>keyed by the stable public address of a paired device.

Source 3 has a trap worth knowing about: macOS refreshes that value only every<br>three to twelve seconds and serves a cached number in between. Polling it<br>faster does not yield more information. Measured over 112 polls at 0.4s, every<br>poll returned a value but the same value repeated for runs of 8 to 31 polls.<br>The tool therefore counts a measurement only when the value actually changes,<br>which is why the reported measurement count is far lower than the poll rate —<br>and honest.

Permissions

Needs Bluetooth access for whichever terminal runs it, under<br>System Settings > Privacy & Security > Bluetooth. It will say so if missing.

Limitations

Cannot make a device ring. There is no path...

findphone device signal bluetooth from strength

Related Articles