navigator.getBattery() leaked battery level and charge estimates with no prompt. Why Firefox pulled it, WebKit never shipped it, and the lesson for new APIs.
For a few years, any website could ask your laptop or phone one oddly intimate question — "how much battery do you have left, and are you charging?" — and get an answer instantly, with no permission dialog at all. The Battery Status API was built for a genuinely useful reason: let a page dim its animations or defer a background sync when the user's device is about to die. Researchers showed it could also be read as a short-lived tracking signal, and within a couple of years one major browser pulled it and another never shipped it at all. It's one of the clearest real-world examples of a well-intentioned Web API getting rolled back once its privacy cost became clear.
Key Takeaways
navigator.getBattery()exposedlevel,charging,chargingTime, anddischargingTimeto any script, with no permission prompt — a rare combination for a hardware-adjacent API.- A 2015 academic study ("The Leaking Battery," Olejnik, Acar, Castelluccia & Diaz) showed the readouts could re-identify a browser across origins for a short window, and — where a browser reported them at full precision — let a script recover the battery's actual capacity, a much longer-lived signal.
- Firefox removed web content's access to the API in version 52 (March 2017), citing privacy risk; Safari/WebKit has never shipped it, treating it as an unjustified fingerprinting surface.
- Chromium-based browsers still ship it today — Chrome, Edge, Opera, and Samsung Internet all support
navigator.getBattery(). - BrowserInsight's fingerprint check shows which of these lower-profile signals your own browser still exposes.
What navigator.getBattery() Exposed
The API attached a single promise-returning method to navigator. Where it was supported, reading it took one line and no user interaction:
navigator.getBattery().then((battery) => {
console.log(battery.level); // 0 to 1, e.g. 0.73
console.log(battery.charging); // true / false
console.log(battery.chargingTime); // seconds until full, or Infinity
console.log(battery.dischargingTime);// seconds until empty, or Infinity
});
Four values did the work: a fractional charge level, a boolean charging state, and two time estimates that the browser recalculated as it observed the battery's behavior. The API also fired levelchange, chargingchange, chargingtimechange, and dischargingtimechange events, so a script didn't even need to poll — it could just sit and watch a visitor's battery drain in real time.
The access rules were thin. The API is limited to secure contexts and is not exposed to Web Workers, but inside an ordinary HTTPS page there was no permission prompt, no user-gesture requirement, and no UI indication that anything had been read. Crucially, a third-party analytics or ad script loaded directly into the page — the usual arrangement — ran with exactly the same access as the site's own code. (The current spec has since added a battery permissions-policy feature whose default allowlist is ["self"], which at least shuts cross-origin iframes out unless the embedding page opts them in.)
The Leaking Battery Study
The privacy problem wasn't that any single reading was highly identifying — a battery at 73% is shared by a lot of people at any given moment. It was that the four values, taken together and refreshed continuously, formed a short-lived but precise state vector that two different sites (or two different trackers on the same site) could compare and match, even if the user had blocked cookies, opened a private window, or switched between tabs. Within a window of a few seconds to a couple of minutes, a matching level plus closely aligned chargingTime/dischargingTime estimates was enough to link two supposedly separate visits back to the same device.
The finding that drew the most attention came from how the numbers were rounded — or rather, weren't. On Firefox running on Linux, the level readout was handed to scripts at full double precision, straight from the operating system's power-management daemon, so a page saw a long fractional value instead of a tidy 0.73. That matters because level is computed as the current charge divided by the battery's full capacity: given enough digits, a script can work backward from the ratio to the capacity itself — a property of the physical hardware, not of the current charge, which barely changes from one browsing session to the next.
The researchers noted that this cuts hardest for exactly the users least able to notice it. A battery's capacity degrades as it ages, drifting away from the factory value in a way that is specific to that individual pack, so an old or heavily used battery yields a more unusual — and therefore more identifying — number than a new one. Their recommendation was not to delete the API but to round what it reports, which costs the feature nothing in real-world usefulness: no page dimming its animations at 20% charge needs the level to more than a couple of decimal places.
Why Firefox Removed It, and Why WebKit Never Shipped It
Firefox was one of the earliest implementers. A prefixed navigator.mozBattery was on by default from Firefox 11 in 2012, and the promise-based navigator.getBattery() arrived in Firefox 43 — Chrome had shipped getBattery() in Chrome 38 the year before. Mozilla's first response to the research was the narrow fix the researchers had asked for: cut the precision of the readouts. The broader judgement came afterwards. Firefox 52, released in March 2017, removed web content's ability to call navigator.getBattery() at all, treating the privacy cost as no longer worth the API's marginal utility for most sites. The feature stayed reachable from Firefox's own privileged code, which is why the change is described as removing web content's access rather than deleting the API outright.
Apple's WebKit engine took the more conservative route from the start: it never shipped navigator.getBattery() to Safari at all, consistent with WebKit's broader posture of declining to implement APIs it judges to carry meaningful fingerprinting risk relative to their benefit.
Chromium-based browsers are the exception. caniuse.com's compatibility table still shows the API supported in Chrome, Edge, Opera, and Samsung Internet — about 78% of tracked global browser usage at the time of writing — while Firefox and every Safari variant, including Safari on iOS, report no support. That three-way split (Chromium: yes, Firefox: removed, WebKit: never) means the mere presence of navigator.getBattery on a page is itself a coarse, hard-to-fake engine signal, in the same family as the Network Information API's Chromium-only footprint.
The Lesson for Shipping New Web APIs
The Battery Status API's rollback is a useful case study because it happened publicly, on a fairly short timeline, and for a reason that had nothing to do with malice on any implementer's part — the API shipped exactly as specified, and the risk only became clear once independent researchers looked closely at what continuous, permission-free readouts of a numeric sensor could do when combined across origins. The W3C's current working draft now carries an explicit security-and-privacy section that reflects that lesson directly, stating that a user agent "should not expose high precision readouts of battery status information as that can introduce a new fingerprinting vector," and that it "may obfuscate the exposed value" so scripts can't be certain whether they're seeing real hardware data at all.
That's the pattern worth generalizing: any API that reports a real-valued, continuously-updating measurement from hardware — battery, sensors, performance counters — needs to ask not just "is this one reading identifying?" but "does watching this value change over time let two different scripts recognize the same browser?" Bucketing and rounding, the same mitigation the Network Information API's designers applied to downlink and rtt, is now the default expectation for this class of API rather than an afterthought.
What This Means for You Today
If you're on Firefox or Safari, this particular signal is already closed — neither browser exposes it, so there's nothing to configure. If you're on a Chromium-based browser, navigator.getBattery() is still callable by any page you visit, though it contributes far less to a combined browser fingerprint than canvas or WebGL do, since level and charging state change constantly rather than staying stable across sessions. It's a good candidate for the same broad defenses that help with other minor signals: a script- or content-blocking extension that limits what pages can execute, or a privacy-focused browser that ships tighter defaults out of the box.
There's a second-order use worth knowing about, and it's why BrowserInsight's fingerprint check reads the battery API where it exists rather than ignoring it. The four values have to be consistent with each other: a device that reports itself as not charging and not full, while simultaneously claiming zero seconds to a full charge and infinite time to empty, is describing a battery that cannot physically exist. Real hardware doesn't produce that combination; a spoofed or scripted browser profile does. So the same readouts that made the API a tracking risk also make it a cheap consistency check — one more reason a browser that lies about itself tends to get caught by fingerprint inconsistencies rather than by any single value.
Frequently Asked Questions
Is the Battery Status API still available in any browser?
Yes — Chrome, Edge, Opera, and Samsung Internet still implement navigator.getBattery(). Firefox removed access to it in version 52 (2017), and Safari/WebKit has never implemented it.
Can a site tell exactly how much battery I have left?
On the browsers that still support the API, yes — level reports your charge as a fraction from 0 to 1 with no permission prompt required. On Firefox and Safari, the API simply isn't there to call.
Was the Battery Status API ever a major tracking tool in practice?
There's no evidence it saw wide abuse as a primary tracker before browsers acted — the response came from academic research surfacing the risk, not from documented large-scale exploitation. Browsers rolled it back proactively rather than reactively, which is part of why it's a useful case study.
Does blocking JavaScript stop this signal?
Yes. Since navigator.getBattery() requires script execution to call, disabling JavaScript or using a script-blocking extension prevents any page from reading it, on the browsers where it's still present.
Conclusion
The Battery Status API is a small, mostly-forgotten piece of web platform history, but it's a clean illustration of a bigger idea: a permission-free API doesn't need to expose your name or your location to become a privacy problem — a continuously-updating numeric sensor, read from enough origins, can do the job just as well. Firefox's removal and WebKit's refusal to implement were early, concrete examples of browsers treating fingerprinting surface as a first-class design constraint rather than an edge case, a posture that now shows up explicitly in how new APIs like Network Information are specified from the start. Run BrowserInsight's fingerprint check to see which lower-profile signals your own browser still exposes.
Recommended Reading:


