Step lab: a step counter you can watch think
Two step counters can disagree about the same walk because a step is not something an accelerometer reports: each counter decides what counts as one, with its own smoothing, its own threshold and its own rule for how soon the next step may come. This page runs a deliberately simple detector on your phone’s accelerometer in the browser, marks every step it counts on the live trace, and gives you sliders for the threshold and the minimum interval so you can watch the count change for a walk that has already happened. Motion data never leaves your device. Without a motion sensor, it replays a synthetic, labeled walk.
Motion data never leaves your device: samples stay in this tab’s memory, nothing is uploaded, and reloading the page discards them.
Tap Start on a phone and walk, or replay the synthetic walk.
Steps counted
0
0 samples
raw magnitude, m/s² low-pass filtered baseline + threshold counted step
Share the result
What the detector does
This detector is ours, written for this page, and it is not a copy of any phone’s. It exists to make visible the choices every step counter makes somewhere. For each sample:
- Magnitude. It takes the length of the acceleration vector, √(x² + y² + z²), so it does not matter which way the phone is held.
- Low-pass filter. An exponential filter with a 3 Hz cutoff smooths away hand tremor and vibration faster than a walking rhythm. This is the green line.
- Baseline. A much slower average (a 1.5 s time constant) tracks the resting level, gravity included, so the threshold is measured from wherever the signal sits.
- Peak and threshold. A local maximum of the filtered signal is a candidate step if it rises at least the threshold above the baseline (default 1.2 m/s²). The dashed line is baseline plus threshold: a peak has to cross it.
- Minimum interval. A candidate sooner than the minimum interval (default 300 ms) after the last counted step is ignored, so one footfall that rings twice counts once.
Every one of those numbers is a judgment. Raise the threshold and soft steps (a shuffle, a step on carpet, a phone in a loose bag) disappear; lower it and bumps that are not steps get counted. Lengthen the interval and a double impact merges into one step, until it passes your step period and every other step vanishes. The synthetic replay has 50 steps built in, three of them soft and one with a double impact, so you can see each failure on a trace whose true count is known.
Why your phone’s own count is different
The step counts your phone keeps do not come from a page like this. On Android, Google’s motion sensors guide says the step counter and step detector sensors are either hardware-based or software-based
, and that the step counter has more latency, up to 10 seconds, but more accuracy than the step detector; both are covered, with Google’s wording, in TYPE_STEP_COUNTER vs TYPE_STEP_DETECTOR. On iOS, Apple describes what CMPedometer returns as system-generated live walking data: the step counts arrive already counted, as CMPedometer covers. Those pages quote what Apple and Google document about the APIs: what they return, when, and with what permission. They do not describe how the platforms turn motion into steps, and this page does not guess.
What follows from that is the practical point of the step counting API page: a step count is an algorithmic estimate from motion sensors, not a literal record of footfalls, so treat it as close rather than exact, prefer the platform’s aggregated total over summing sources yourself, and do not quote an accuracy percentage. Two apps that read different sources, a phone and a watch, or one counter that waits seconds to report and another that reports at once, will disagree for reasons this lab makes visible. A “today” total can also disagree for a reason that has nothing to do with motion: where the day starts, which is the bug in why “today’s steps” is a bug. Every phone motion API is indexed at phone motion sensors.
What the browser gives this page
- The
devicemotionevent, which MDN describes asfired at a regular interval
; itsintervalproperty is the time between samples in milliseconds, which the page shows when the browser reports it. - Acceleration in meters per second squared. The page reads
accelerationIncludingGravity, which MDN saysrepresents the raw data measured by an accelerometer
andmay be the only value available on devices that aren't able to remove gravity
, and falls back toaccelerationwhen that is missing. The baseline makes either work. - On iOS Safari, a permission prompt. The page calls
DeviceMotionEvent.requestPermission()inside the Start tap because, per MDN, it needs transient activation, meaningit must be triggered by a UI event such as a button click
, and it resolves to"granted"or"denied". Browsers without the method need no prompt. - Rounded values, on purpose. The W3C Device Orientation and Motion draft tells browsers to limit each acceleration value’s precision to no more than 0.1 m/s² and to expose the interfaces only in secure contexts, as fingerprinting defenses. This detector’s default threshold is 1.2 m/s², so the rounding does not hide a step from it.
On a desktop, or a browser that never delivers a sample, Start reports that nothing arrived within three seconds and the synthetic replay is the way to see the detector work.
How this works, and what it sends
Motion data never leaves your device. Samples go from the browser’s devicemotion event into an array in this tab’s memory and onto the canvas; they are not stored, sent or logged, and this page has no server code behind it. Reloading discards the recording. The share card is drawn on a canvas in your browser and saved by your browser; nothing is uploaded to make it.
The replay is synthetic: a generated trace of 50 steps at 1.8 per second with seeded noise, three soft steps, one double impact and a burst of 9 Hz hand jitter. It is not a recording of anyone walking and says nothing about how accurate any real counter is. The detector and the trace generator are one module, tested in scripts/step-detector.test.mjs against a regular walk, jitter and a hop.
The browser-API statements were read on 2026-10-31. MDN’s site and the W3C hosts could not be reached from where this page was written, so the text was read from the sources they publish: MDN’s content repository and the W3C draft’s source file. Sources: MDN: DeviceMotionEvent; MDN: DeviceMotionEvent.accelerationIncludingGravity; MDN: DeviceMotionEvent.requestPermission(); MDN: Window devicemotion event; W3C: Device Orientation and Motion (editor's draft).
A free tool from AIFitnessAPI. Every phone motion API is at phone motion sensors. More at free tools for health-app builders.
Next step
Turning this into a choice of API: