Use the motion sensors already inside compatible Sony headphones and earbuds as a real-time head tracker on Windows.
Unofficial open-source Windows bridge. Not affiliated with or endorsed by Sony.
2026-07-05.12-09-44.mp4
Sony Head Tracker connects to the Android Head Tracker sensor exposed by supported Sony Bluetooth devices, reads live orientation and gyroscope data, and sends yaw, pitch, and roll to OpenTrack or your own applications.
No webcam, infrared tracker, additional hardware, firmware modification, or custom kernel driver is required.
Originally developed and tested for the Sony WH-1000XM5, the project now supports any compatible Sony headset that exposes the standard Android Head Tracker HID protocol.
If you arrived searching for Sony WH-1000XM5 head tracking on Windows, how to use WH-1000XM5 with OpenTrack, or an XM5 head tracker for Assetto Corsa or other sims, you are in the right place: the WH-1000XM5 is the reference device, and the same bridge now works across the wider Sony range.
- Use compatible Sony headphones for head tracking in racing and flight simulators.
- Send live yaw, pitch, and roll to OpenTrack.
- Read orientation, quaternion, and gyroscope data through a local JSON stream.
- Inspect sensor activity through the included Windows diagnostics interface.
- Test additional Sony models with the read-only compatibility probe.
- Tom's Hardware — You can now use your Sony headphones as a free real-time head tracker for race and flight simulators on PC
- Hackaday — Flight Sim Tracking From Spatial Audio
- SoundGuys — This free app turns Sony WH-1000XM5 into head trackers for PC gaming
- Download
sony-head-tracker.exefrom the latest release (or build it yourself, it is oneclcommand). - Pair your compatible Sony headphones or earbuds through Windows 11.
- Open the application. It automatically discovers compatible head-tracking sensors, displays live orientation data, and streams tracking output while it is open.
- Starting the app for the first time on a fresh boot? Press Repair Tracker first. Windows very often pairs a Sony headset but does not create the head-tracker sensor node until something nudges it, so on a cold boot the app frequently shows nothing at first. Press the Repair Tracker button and approve the single administrator prompt. This is the normal first step, not a sign that anything is broken, and it is exactly what the button is for. After the app reopens, your headset should appear.
- For games: in OpenTrack, select UDP over network as the input and use
port
4242, then press Start. See OpenTrack. - For your own code: read one JSON object per sample from port
4243. Seedocs/PROTOCOL.md. - Press Recenter (or Ctrl+Alt+C) while facing forward.
Hardware status: changing orientation reports have been received and parsed from a physical WH-1000XM5. Behaviour varies with Sony firmware and the Windows Bluetooth stack. This project never spoofs another headset, changes Bluetooth identities, or modifies firmware.
- Quick start
- Compatibility
- Where the data goes (ports)
- Gyroscope and accelerometer
- Default orientation
- Build
- Pair the headphones
- Usage
- The GUI
- OpenTrack
- When the sensor won't show up
- Protocol and security notes
- Contributing
- License
Compatibility is determined by the protocol exposed by the headset, not simply by
the Sony model name. A device is compatible when it exposes an Android Head
Tracker HID sensor with the expected #AndroidHeadTracker# descriptor (usage
0x0020:0x00E1).
The underlying engine is protocol-based, although the project is currently focused on testing and supporting Sony headphones. In practice that means compatible Sony headphones, with experimental support for other devices using the same protocol.
You can check any device in seconds, with zero risk. Pair the headphones, then run:
sony-head-tracker.exe probeprobe is read-only. It never writes to the device, changes drivers, or touches
firmware. If it finds a verified Android head tracker it prints the descriptor
and exits 0. If not, it lists what it saw and exits 2.
Reports for both working and non-working devices are welcome. Please
open an issue
with the probe output and your Windows and firmware versions, and the table
below will be updated.
| Device | Reported by |
|---|---|
| Sony WH-1000XM5 | maintainer, tested |
| Sony WF-1000XM5 | community confirmed |
| Sony WH-1000XM6 | community confirmed |
| Sony WF-1000XM6 | community confirmed |
| Sony ULT WEAR (WH-ULT900N) | community confirmed |
Sony lists these models as supporting head tracking, but they still require community testing with this Windows implementation. Please do not assume they are already validated.
- Sony LinkBuds Open (WF-L910)
- Sony LinkBuds Fit (WF-LS910N)
- Sony LinkBuds (WF-L900)
- Sony LinkBuds S (WF-LS900N)
A candidate model may still need the latest firmware before the sensor appears. Install Sony's Sound Connect app, connect the headphones, and update before probing.
| Device | Status | Reported by |
|---|---|---|
| Sony WH-1000XM4 | Does not work | community confirmed |
| Sony WH-1000XM3 | Not expected to work | not on Sony's head-tracking list |
| Apple AirPods (all models, including AirPods Pro) | Not possible on Windows | see Why AirPods can't work |
Models that are not on Sony's head-tracking list almost certainly carry no usable sensor. Bose QuietComfort Ultra models do head-tracked spatial audio and might one day expose a compatible protocol, but that is unverified and out of scope for now.
AirPods have the motion sensors, but Apple does not implement the Android Head
Tracker HID protocol. Head tracking (and ANC control, ear detection, and so on)
travels over Apple's proprietary accessory protocol (AAP) on a raw Bluetooth
Classic L2CAP channel (PSM 0x1001). On Windows that leaves one hard blocker:
Windows has no user-mode API for that channel. Desktop Windows exposes RFCOMM sockets to applications, but custom Bluetooth Classic L2CAP channels can only be opened by a kernel-mode profile driver (Microsoft's docs). That is how MagicPods does it on Windows: it ships a custom driver. This project's hard rule is that it never installs a custom kernel driver, so that path is out of scope here.
The payload itself is not unknown. The AAP head-orientation packets are
covered by pabloaul's rtbuddy Wireshark dissector,
linked from the LibrePods README,
so the only thing standing in the way on Windows is the L2CAP access.
What this bridge does instead: it recognises paired AirPods and tells you
exactly this, in probe, in bridge, and in the GUI, instead of failing
silently.
In bridge mode (and while the GUI is open) head-tracking data is streamed over
UDP to loopback (127.0.0.1) on two adjacent ports:
| Port | Format | Consumer |
|---|---|---|
4242 (--port) |
Six little-endian doubles (x, y, z, yaw, pitch, roll) |
OpenTrack "UDP over network" |
4243 (--port + 1) |
UTF-8 JSON object (see below) | Your own apps and scripts |
Change the base port with --port N. The JSON port is always N + 1. The bridge
prints both destinations on startup, and the GUI shows them along the bottom edge.
Translation axes (x, y, z) are always zero, because this protocol reports
orientation only.
The JSON datagram (one per sample, version: 2):
Security: UDP output is loopback-only by default and has no authentication. Do not bind or forward it to an untrusted network.
A full wire-format reference lives in docs/PROTOCOL.md.
Both inertial streams are exposed in full, in addition to orientation:
-
Gyroscope: angular velocity in rad/s, emitted as the JSON
gyroscopearray (and shown live in the GUI). This is the connected headset's on-board gyro as carried by the Android Head Tracker protocol. -
Accelerometer: linear acceleration in m/s^2, emitted as the JSON
accelerometerarray when the device reports it.The Android Head Tracker HID profile that supported Sony firmware advertises defines only orientation and gyro fields, so on current firmware
accelerometeris typicallynull. The bridge nonetheless parses the standard HID sensor-page acceleration usages (0x0453to0x0455, plus the vector form0x0452) from every input report, so if your firmware exposes them they are surfaced automatically, with no code change needed. Gyro is likewise parsed from both the head-tracker custom field (0x0545) and the standard sensor-page usages.
The default axis convention is YXZ order with the X and Z axes inverted, the mapping that produces correct head tracking on the WH-1000XM5. It is fully overridable:
- CLI:
--axis-map XYZ(any permutation) and--invert X(any axes). The--invertflag is a complete override:--invert xzreproduces the default,--invert zinverts Z only, and--invert noneclears all inversions. - GUI: the axis-order dropdown (defaults to YXZ) and the Invert X/Y/Z checkboxes (Invert X and Z start checked).
The same axis convention is applied to the gyroscope and accelerometer vectors so all streams share one coordinate frame.
Requires a C++20-capable MSVC and a current Windows 11 SDK (install Desktop development with C++ in the Visual Studio Installer).
build.cmdbuild.cmd locates the Visual Studio C++ tools automatically. Or build by hand
from a x64 Native Tools Command Prompt for VS:
rc /nologo app.rc
cl /std:c++latest /EHsc /permissive- /utf-8 /O2 /W4 /DUNICODE /D_UNICODE /I include src\*.cpp app.res /Fe:sony-head-tracker.exeThe code is split into a hardware-independent core under
include/sony_head_tracker/ +
src/ (quaternion maths, HID descriptor decoding, the orientation
filter, and protocol serialisation — all Windows-free) and a platform layer (HID
and Sensor API backends, Bluetooth repair, UDP output, and the GUI). Every backend
produces a normalized MotionSample, so recenter, smoothing, axis mapping, Euler
conversion, and serialisation are all unit-testable without a headset — see
tests/ and run them with build-tests.cmd. A small resource bundle
(app.rc: icon, version info, and the Common Controls manifest) is
embedded at build time; the icon is generated by
tools/make-icon.ps1 and committed as app.ico. All
required import libraries are pulled in via #pragma comment(lib, ...), so the
executable stays dependency-free with no extra linker arguments. The build is
warning-clean at /W4. Every push is built and unit-tested in CI on
windows-latest, and pushing a v* tag publishes the exe as a GitHub Release.
See .github/workflows/build.yml.
- Update the headset with Sony's app and enable its spatial-audio or head-tracking feature if available, then put the headset in pairing mode.
- In Windows 11: Settings > Bluetooth & devices > Add device > Bluetooth, and pair your Sony headset.
- Run
sony-head-tracker.exe probe. A usable collection shows usage0x0020:0x00E1and a feature description beginning with#AndroidHeadTracker#.
sony-head-tracker.exe (no args -> diagnostics GUI)
sony-head-tracker.exe probe [--include-disabled]
sony-head-tracker.exe dump [--seconds N]
sony-head-tracker.exe repair
sony-head-tracker.exe bluetooth-probe [--all-le] [--name FILTER]
sony-head-tracker.exe bluetooth-rebind [--name FILTER] (default: auto-detect)
sony-head-tracker.exe bluetooth-generic-hid (run from an elevated prompt)
sony-head-tracker.exe bridge [--port 4242] [--seconds N]
[--axis-map YXZ] [--invert XZ] [--smoothing 0.18]
sony-head-tracker.exe help | version
bridgeis the main headless mode. It prints which headset it is tracking, reconnects automatically, and streams to the ports described in Where the data goes.probeprints discovered HID collections and Sensor API custom sensors, names the headset a verified tracker belongs to, and explains why nothing was found (including the AirPods case).bluetooth-rebind(andrepair) auto-detect the headset by checking which paired device's SDP record carries the Android Head Tracker descriptor, so no other Bluetooth device's services are ever touched. Pass--name "<device name>"to select one explicitly.dumpprints untouched HID input reports (--seconds Nfor a bounded run).diagnosticsprints a redacted support bundle (app/Windows version, backend, model, HID usage, descriptor, settings, and recent log) with Bluetooth addresses, your Windows username, computer name, and device names removed — safe to paste into an issue. The GUI has the same thing under Tools → Export diagnostics….repairis the one-click recovery (see below).
Launch with no arguments. The window opens in Simple Mode by default. Use the mode button at the upper right to switch views:
- Header band with the app icon, title, version, an Unofficial tag, and a live status line: green "Tracking " while connected, or amber guidance while not. The guidance includes the one that matters most: if you see nothing, press Repair Tracker (it needs one administrator approval). If AirPods are your only paired headphones, it says so and explains why they can't work.
- Shared controls in both modes include Refresh (re-enumerate and reconnect), Repair Tracker (one-click recovery, marked with the Windows UAC shield because it asks for a single administrator prompt), Recenter (set the current pose as forward; global hotkey Ctrl+Alt+C), and live axis tuning: axis order, Invert X/Y/Z, and a DPI-aware Smoothing slider with its live percentage (defaults to YXZ plus invert X and Z).
- Simple Mode shows concise OpenTrack setup help, large yaw/pitch/roll values, samples per second, packet age, backend, and the live orientation graph. It hides device paths, raw packets, protocol internals, and long logs.
- Advanced Mode adds the device list, Show all devices, descriptor and activity details, raw packet and motion readouts, full connection health, and the Tools menu for diagnostics and configuration import/export.
- Output panel shows OpenTrack on
UDP 127.0.0.1:4242and JSON telemetry on4243. Simple Mode gives only the setup instruction; Advanced Mode adds the technical destination details. - Live orientation graph, flicker-free (double-buffered) yaw/pitch/roll with a degree grid and a legend showing the current values in both modes. Visible readouts use fixed-width values and refresh at a comfortable visual rate while every sample is still streamed.
Settings (axis mapping, inversion, smoothing, port, UI mode, and window placement) are saved
to %LOCALAPPDATA%\SonyHeadTracker\config.json and restored on the next launch. If
the headset drops (sleep, output-device change, phone reconnect), the app
reconnects on its own with an increasing back-off (1, 2, 5, 10, 30 s); Refresh
or Tools → Reconnect now retries immediately.
The connected headset's name is shown in the title bar, and the GUI streams to UDP
4242 (plus JSON on 4243) the whole time it is open.
Choose UDP over network as the input, set its port to 4242, start
sony-head-tracker.exe bridge --port 4242 (or just leave the GUI open), then press
Start in OpenTrack. The application uses yaw, pitch, and roll in degrees.
Windows sometimes pairs the headset but never creates the head-tracker HID node, or parks it with Device Manager Code 10. This is especially common on a fresh boot, which is why Repair Tracker is the recommended first step when you open the app. The bridge has read-only diagnostics and a targeted, driver-only recovery (it never installs a custom kernel driver):
- Repair Tracker in the GUI, or
sony-head-tracker.exe repair. This closes stale instances, auto-detects which paired headset advertises the head tracker, re-enables only that device's standard HID service, binds the failed node to Microsoft's inbox generic HID driver, verifies the#AndroidHeadTracker#marker, and reopens. - If
bluetooth-probefinds the Android descriptor butprobedoesn't, runbluetooth-rebind, wait for reconnection, and probe again. - If Device Manager shows the HID Custom Sensor with Code 10, open an
elevated prompt and run
bluetooth-generic-hidonce.
Other tips:
- Close Sony utilities, spatial-audio tools, and anything else that may hold the device with exclusive access, then Refresh.
- If reports stay still, confirm Full Power, All Events, and a nonzero supported interval were accepted in the log. The tested WH-1000XM5 advertises 40 ms and produces about 25 packets per second.
The implementation follows the official Android Head Tracker HID protocol: it
accepts compatible version strings, reads report IDs and lengths from HIDP_CAPS,
accesses fields through HidP_*, and honours each value capability's logical and
physical ranges and HID unit exponent.
UDP output is loopback-only by default and has no authentication. Do not bind or forward it to an untrusted network.
Sony Head Tracker is free and open source.
If this project saved you from buying a TrackIR, Tobii, webcam tracker, phone-tracking app, or other head-tracking hardware, consider supporting development:
Support helps fund:
- testing more Sony headphones and earbuds
- OpenTrack setup improvements
- compatibility fixes for more devices
- continued free and open-source development
There is no paid version required. Donations are optional and help keep the project easier to install, test, and maintain.
Contributions are welcome. See CONTRIBUTING.md for build, style, and PR guidance, and CODE_OF_CONDUCT.md for community expectations. Notable changes are tracked in CHANGELOG.md.
MIT.
{ "version": 2, "device": "WH-1000XM5", // connected headset's Bluetooth name, or null "rotationVector": [x, y, z], // axis-angle, radians "quaternion": [w, x, y, z], // recentered orientation "yprDegrees": [yaw, pitch, roll], // degrees "gyroscope": [x, y, z], // rad/s, or null if unavailable "accelerometer": [x, y, z], // m/s^2, or null if the device doesn't report it "angularVelocity": [x, y, z], // deprecated alias of "gyroscope" "resetCounter": 0, "packetsPerSecond": 25.0, "receiveLatencyMs": -1.0 // -1 when the device provides no timestamp }