---
title: "Reading the battery in the browser"
description: "The Battery Status API gives you charge level, charging state, and time-to-full from JavaScript, and pushes events when they change. Here's a battery widget built on it, with a fallback for the browsers that dropped it."
date: "2026-05-29"
tags: ["javascript", "web-api", "battery", "frontend"]
---

I didn't know the browser would just tell you the battery level until
[Bilal Hussain](https://x.com/BilliCodes/status/1837356812338594066) posted it.
One call, and you get charge, charging state, and time-to-full:

## The API

`navigator.getBattery()` resolves to a battery object with four live
properties:

```ts
const battery = await navigator.getBattery();

battery.level;            // 0..1  (0.22 = 22%)
battery.charging;         // boolean
battery.chargingTime;     // seconds until full, or Infinity
battery.dischargingTime;  // seconds until empty, or Infinity
```

The nice part is you don't poll. The object fires events when anything changes,
so you read once and re-read on each event:

```ts
const read = () => render(battery);
read();
battery.addEventListener("levelchange", read);
battery.addEventListener("chargingchange", read);
```

Plug `battery.level` into the width of a fill bar, swap the color by charge
(green, amber, red), drop in a bolt when `charging` is true, and the raw number
turns into something you'd actually ship.

## The catch: it's Chromium-only

This is where it gets interesting. The Battery Status API only exists in
Chromium now. Firefox and Safari both removed it, and for a good reason: a
precise charge level combined with the discharge-time estimate is a
surprisingly strong fingerprint. Two visits a few seconds apart share a battery
reading almost no other device has at that exact moment, which is enough to
re-link a user who cleared their cookies. Researchers showed this in practice,
and the feature got pulled.

So treat it as progressive enhancement. Feature-detect `getBattery`, and have a
real plan for when it's absent rather than rendering a broken empty state. The
widget above animates a simulated battery on those browsers, labelled as
simulated, so it still reads as a battery instead of an error.

```ts
if ("getBattery" in navigator) {
  // live readout
} else {
  // simulate, or hide the widget entirely
}
```

Inspired by [Bilal Hussain](https://x.com/BilliCodes/status/1837356812338594066).
Grab the component on the [Battery Status](/components/battery-status) page.
