loading
Warning:
Limited browser support The Battery Status API is only implemented in Chromium-based browsers - Firefox and Safari intentionally do not expose it for privacy reasons. When the API is unavailable, IsSupported returns false and GetStatus reports a charged-on-AC-power stub so your code doesn't have to special-case missing data.

Support check

IsSupported

Returns true when the runtime exposes navigator.getBattery. Because the check runs over JS interop, defer it to OnAfterRenderAsync when prerendering.

C#
@inject Bit.Butil.Battery battery

var supported = await battery.IsSupported();
Live sample
support check output
Results will appear here when you interact with the samples.

Read the battery status

GetStatus

Takes a one-shot snapshot of the battery: charge level in the [0, 1] range, whether the device is charging, and the estimated seconds until fully charged or discharged (null when the browser can't estimate).

C#
var status = await battery.GetStatus();

var level = status.Level;                     // 0.87
var charging = status.Charging;               // true / false
var untilFull = status.ChargingTime;          // seconds, or null
var untilEmpty = status.DischargingTime;      // seconds, or null
Live sample
battery status output
Results will appear here when you interact with the samples.

Formatted snapshot

GetStatus

The same snapshot rendered as UI state instead of raw values - a typical pattern for a status-bar battery indicator.

C#
var status = await battery.GetStatus();

batteryLabel = status.Charging
    ? $"{status.Level:P0} - charging"
    : $"{status.Level:P0} - on battery";
Live sample
snapshot output
Results will appear here when you interact with the samples.

React to battery changes

SubscribeChange

Polling GetStatus is the wrong shape for a battery indicator. SubscribeChange hands you a fresh snapshot every time anything moves - plugged in, unplugged, or the level ticked. The spec has no single change event, so this attaches to all four (chargingchange, levelchange, chargingtimechange, dischargingtimechange) and always reports the whole state, meaning your handler never has to work out which field changed. Returns null where the API doesn't exist, since the AC-power stub can never change.

C#
private ButilSubscription? subscription;

subscription = await battery.SubscribeChange(status =>
{
    _snapshot = status;
    InvokeAsync(StateHasChanged);
});

if (subscription is null)
{
    // No Battery Status API here - nothing to watch.
}

// later
await subscription.DisposeAsync();
Live sample
change output
Results will appear here when you interact with the samples.

API reference

Member
Signature
Description
IsSupported
ValueTask<bool> IsSupported()
True when the runtime exposes navigator.getBattery. Returns default (false) during prerender/SSR instead of throwing.
GetStatus
ValueTask<BatteryStatus> GetStatus()
One-shot snapshot of the battery state. Reports a charged-AC-power stub when the API is unsupported.
SubscribeChange
ValueTask<ButilSubscription?> SubscribeChange(Action<BatteryStatus> handler)
Calls the handler with a fresh snapshot on every battery change. Attaches to all four change events, so the handler gets the whole state each time. Null when the API is unsupported - the stub never changes.
BatteryStatus.Charging
bool Charging { get; set; }
True if the device is currently charging.
BatteryStatus.ChargingTime
double? ChargingTime { get; set; }
Seconds remaining until fully charged, or null when unknown.
BatteryStatus.DischargingTime
double? DischargingTime { get; set; }
Seconds remaining until discharged, or null when unknown.
BatteryStatus.Level
double Level { get; set; }
Battery level in the [0, 1] range.
An unhandled error has occurred. Reload 🗙