NetworkInformation
Read the device's connection type, speed estimates and data-saver preference from navigator.connection - plus the universally available navigator.onLine - in a single typed snapshot.
@inject Bit.Butil.NetworkInformation networkInformationMDN reference
navigator.connection ships in Chromium-based browsers; Firefox and Safari do not expose
it, so every nullable property of the snapshot (EffectiveType, Type, Downlink, DownlinkMax, Rtt,
SaveData) comes back null there. Online is backed by navigator.onLine and
works everywhere.
Returns a one-shot snapshot of the network state: online flag, effective connection type (slow-2g, 2g, 3g, 4g), underlying type (wifi, cellular, ethernet, ...), downlink estimates in Mbps, round-trip time in milliseconds and the user's save-data preference. Try it with different throttling profiles in the DevTools Network tab.
var status = await networkInformation.GetStatus();
// status.Online -> true / false
// status.EffectiveType -> "slow-2g" | "2g" | "3g" | "4g" | null
// status.Type -> "wifi" | "cellular" | "ethernet" | ... | null
// status.Downlink -> estimated Mbps, e.g. 10.0
// status.DownlinkMax -> maximum advertised Mbps
// status.Rtt -> round-trip time in ms
// status.SaveData -> true when reduced data usage is requestedSubscribeChange delivers a fresh snapshot whenever connectivity shifts, so you never poll GetStatus. It attaches to the window's online and offline events as well as navigator.connection's change, which means it works on every browser - it just won't report quality changes where IsSupported is false. Test it by toggling the Offline checkbox in the DevTools Network tab (or by disabling your network adapter).
private ButilSubscription? subscription;
subscription = await networkInformation.SubscribeChange(status =>
{
if (status.Online)
{
// back online - refresh data, flush queued work, ...
}
else
{
// connection lost - switch the UI to offline mode
}
});
// later
await subscription.DisposeAsync();Online only means the device has a network attached - a captive portal or a
down backend still reports online. Treat a transition as a hint to retry, not as a guarantee
that your API is up.
API reference
ValueTask<NetworkConnectionStatus> GetStatus()ValueTask<ButilSubscription> SubscribeChange(Action<NetworkConnectionStatus> handler)bool Online { get; set; }string? EffectiveType { get; set; }string? Type { get; set; }double? Downlink { get; set; }double? DownlinkMax { get; set; }int? Rtt { get; set; }bool? SaveData { get; set; }