# Badging API: app icon badges for installed PWAs

> How to set and clear numeric or presence badges on a PWA's app icon using the Badging API, with per-platform support notes for Android, iOS, and desktop.

**In one line:** The Badging API (`navigator.setAppBadge` / `navigator.clearAppBadge`)
lets an installed PWA place a numeric count or a presence dot on its home-screen or
taskbar icon — the same badge indicator native apps have used for years.

## Basic usage

```js
// Set a numeric badge (e.g. unread message count).
// The OS decides exactly how the number is rendered.
await navigator.setAppBadge(3);

// Set a presence badge (dot, no number) when you have activity
// but no meaningful count.
await navigator.setAppBadge();

// Clear the badge.
await navigator.clearAppBadge();
```

Both methods return Promises. You do not need a permission prompt to set a badge.
The API is designed to be called from a **service worker** (ideal for push
notifications) or from a page script.

### Calling from a service worker

```js
// In service-worker.js — update badge when a push arrives.
self.addEventListener('push', (event) => {
  const count = event.data?.json()?.unread ?? 0;
  event.waitUntil(
    self.navigator.setAppBadge(count)
  );
});
```

`self.navigator` is available in service worker scope in supporting browsers.
This allows badges to be updated even when the app's pages are not open.

## Platform support

### Android

Chrome for Android does **not** support the Badging API (`navigator.setAppBadge`
is not exposed). Android may display an automatic notification badge on the app
icon when a notification is received, but this is controlled entirely by the
Android OS and cannot be set or cleared programmatically via the Badging API.

### iOS / Safari

Safari on iOS supports the Badging API **for home-screen web apps from iOS 16.4+**.
The badge is tied to the notification permission: the user must have granted notification
access before `navigator.setAppBadge` takes effect. Key constraints:

- The PWA **must be installed** to the home screen — the API is not available in a regular
  Safari tab.
- The user must have granted **notification permission** to the PWA.
- When a push notification is delivered the OS updates the badge automatically; explicit
  `navigator.setAppBadge` calls also work from page or service worker scope in supporting
  versions.
- In Regular Safari tabs (non-installed context) the method is not exposed.

### Desktop (Chrome / Edge)

Chrome and Edge on Windows, macOS, Linux, and ChromeOS support the Badging API for
installed PWAs. The badge renders as an overlay on the taskbar or dock icon,
matching the OS convention:

- **Windows:** small colored circle on the taskbar icon.
- **macOS:** red dot with a number on the Dock icon.
- **Linux / ChromeOS:** platform-specific rendering; Chrome uses a dot.

### Firefox

Firefox does not currently support the Badging API on any platform.

## Feature detection

```js
if ('setAppBadge' in navigator) {
  // Badging API is available.
  await navigator.setAppBadge(newCount);
} else {
  // Fall back to a notification or in-app indicator.
}
```

Always guard with feature detection; silently skip badge updates on unsupported
platforms rather than throwing.

## Number rendering

Browsers/OSes impose their own rendering rules:

- Values of 0 are treated as "clear" (equivalent to `clearAppBadge()`).
- Very large values are capped at a display maximum (often 99 or 999+).
- Passing `Infinity` or `NaN` clears the badge.
- The badge number is a hint, not a guarantee of exact display.

## Privacy considerations

Badges are visible to anyone who can see the device's home screen or taskbar.
Avoid encoding sensitive information (message content, account numbers) in a
badge count. A generic unread count is appropriate; personally identifiable
content is not.

## Compatibility

For current browser support figures, see [/compatibility/](/compatibility/).

## Try it

The companion demo at [/demo/#badging](/demo/#badging) calls `navigator.setAppBadge()` with a counter and `clearAppBadge()` to reset it. Install the demo first: the call resolves in a tab as well, but the badge is only drawn on an installed app icon.

## Practical checklist

- [ ] Feature-detect `'setAppBadge' in navigator` before calling the API.
- [ ] Call from a service worker push handler to update the badge when the page is closed.
- [ ] Call `clearAppBadge()` when the user opens and reads the relevant content.
- [ ] Treat badge updates as a hint; do not depend on exact number rendering.
- [ ] On iOS: ensure the PWA is installed to the home screen and notification permission is granted before calling the Badging API (iOS 16.4+).
- [ ] Provide an in-app unread indicator as a fallback for platforms without badge support (Android Chrome, Firefox, older iOS).
- [ ] Do not put sensitive content in a badge count.