CMHeadphoneMotionManager: head motion from AirPods
Last verified October 3, 2026 · 4 min read
A person doing a plank, a neck mobility routine or a run with AirPods in is wearing a motion sensor on their head. This class reads it. Sources are Apple's CMHeadphoneMotionManager documentation and the Core Motion updates page, read 2026-10-03.
What you get#
Updates arrive as CMDeviceMotion, the same type the phone's own device-motion service uses. Apple's article on processed device motion lists what that service provides: attitude, unbiased rotation rate, the gravity vector, user acceleration without gravity, and the magnetic field vector, and names CMHeadphoneMotionManager as one of three classes that offer it. Two ways to receive it:
startDeviceMotionUpdates(to:withHandler:)pushes each update to a handler on the queue you pass.startDeviceMotionUpdates()starts the service and leaves you to readdeviceMotion, which Apple says "is nil when there is no device-motion data."
The axes are the headphones', not the phone's. Apple's class page includes a diagram of "the positive x-axis, positive y-axis, and positive z-axis for motion-capable Apple headphones", and you need it before interpreting pitch or roll.
Which headphones#
This is what Apple's pages say, and no more:
- The class page refers to "motion-capable Apple headphones" and lists no models.
- The sample for the separate headphone activity manager requires "Headphones that support motion updates, such as AirPods Pro 2 or AirPods 4", plus a device on iOS 18 or later.
"Such as" is an example, not a compatibility list. Gate the feature on the API rather than on a model name.
Availability is not connection#
isDeviceMotionAvailable is documented as "A Boolean value that indicates whether the current device supports the headphone motion manager." That is the phone, Mac or watch running your code. It does not say headphones are in the user's ears. For that, adopt CMHeadphoneMotionManagerDelegate: headphoneMotionManagerDidConnect(_:) "Performs a callback to the delegate after you connect headphones", with a matching disconnect callback. Apple's June 2024 update note adds: "Enable connect or disconnect monitoring outside of a motion session with the CMHeadphoneMotionManager class." The methods behind that, startConnectionStatusUpdates() and isConnectionStatusActive, carry no description on Apple's pages.
import CoreMotion
final class HeadTracker: NSObject, CMHeadphoneMotionManagerDelegate {
private let manager = CMHeadphoneMotionManager()
func start(onPitch: @escaping (Double) -> Void) {
guard manager.isDeviceMotionAvailable else { return } // this device, not the AirPods
manager.delegate = self
manager.startDeviceMotionUpdates(to: .main) { [weak self] motion, error in
if error != nil { self?.manager.stopDeviceMotionUpdates(); return }
guard let motion else { return }
onPitch(motion.attitude.pitch) // radians, headphone axes
}
}
func headphoneMotionManagerDidConnect(_ manager: CMHeadphoneMotionManager) { /* show live state */ }
func headphoneMotionManagerDidDisconnect(_ manager: CMHeadphoneMotionManager) { /* pause the set */ }
}
Stopping on error follows Apple's handler documentation, which says "If an error occurs, you should stop gyroscope updates and inform the user of the problem." The word gyroscope is Apple's, on a headphone-motion page.
Apple Watch: two answers#
The class page stamps watchOS 7.0. Apple's Core Motion updates page lists under June 2024: "You can also use CMHeadphoneMotionManager to support AirPods device motion data on watchOS." We could not reconcile the two from Apple's pages alone. If watch support matters, test on the oldest watchOS you ship.
Activity from the headphones#
CMHeadphoneActivityManager, from iOS 18.0 and watchOS 11.0, is a different class. Apple: it "provides similar information to CMMotionActivityManager, except the activity information comes from headphone motion, rather than from device motion." It delivers the same CMMotionActivity objects covered on the CMMotionActivityManager page, and Apple says to check isActivityAvailable and isStatusAvailable before using it.
Permission#
Apple: "In iOS and macOS, include the NSMotionUsageDescription key in your app's Info.plist file. If this key is absent, the system crashes your app when you start device-motion updates." authorizationStatus() returns the same CMAuthorizationStatus as the rest of Core Motion.
Pitfalls#
- Reading
isDeviceMotionAvailableas a connection signal. It describes the host device. Use the delegate. - Hard-coding model names. Apple publishes examples, not a list.
- Using phone axes. The headphones have their own coordinate frame.
- Leaving updates running. Apple's processed device-motion article tells you to stop the service when you no longer need it, because the hardware "consumes additional power"; it is written for
CMMotionManager, and the same discipline applies here. - Promising rep counting from head motion. Apple documents the data, not any exercise algorithm. How rep counters are built is on how rep counting works.
The camera-based alternative, which sees the whole body rather than the head, is the subject of tracking workouts without a wearable.
Frequently asked questions
- Which AirPods work with CMHeadphoneMotionManager?
- Apple does not publish a list on the class page. CMHeadphoneMotionManager's documentation refers only to motion-capable Apple headphones. Apple's sample for the related CMHeadphoneActivityManager requires headphones that support motion updates, such as AirPods Pro 2 or AirPods 4, which is an example rather than a full list. Gate the feature on isDeviceMotionAvailable and on the delegate's connect callback instead of checking model names.
- Does CMHeadphoneMotionManager work on Apple Watch?
- Apple's pages give two signals. The class documentation lists watchOS 7.0 as its introduction. Apple's Core Motion updates page, under June 2024, says you can also use CMHeadphoneMotionManager to support AirPods device motion data on watchOS, which reads as watch support arriving later. We could not reconcile the two from Apple's documentation, so test on the oldest watchOS version you intend to support before promising the feature.
- How do I know when AirPods connect for head tracking?
- Adopt CMHeadphoneMotionManagerDelegate and set it as the manager's delegate. Apple documents headphoneMotionManagerDidConnect(_:) as a callback after you connect headphones, with a matching disconnect callback. Do not rely on isDeviceMotionAvailable for this: Apple defines it as whether the current device supports the headphone motion manager, which says nothing about whether headphones are in the user's ears.
- What is the difference between CMHeadphoneMotionManager and CMHeadphoneActivityManager?
- CMHeadphoneMotionManager streams raw head motion as CMDeviceMotion: attitude, rotation rate, gravity and user acceleration, from iOS 14.0. CMHeadphoneActivityManager, from iOS 18.0 and watchOS 11.0, classifies activity instead; Apple says it provides similar information to CMMotionActivityManager, except the activity information comes from headphone motion rather than device motion. Use the first for posture or head-movement features, the second for knowing whether the wearer is walking or running.
Keep reading
Elsewhere on the site
Pages that share this one’s concepts and sources, from other sections.
Next steps
Was this page useful?
Independent comparison, last reviewed October 3, 2026. Pricing, rate limits, and feature availability change often — confirm current details in each provider’s official documentation before you commit. Product and company names are trademarks of their respective owners; AIFitnessAPI is not affiliated with, endorsed by, or sponsored by any product listed here.
← All phone sensors · by AIFitnessAPI