Badging API

W3C First Public Working Draft

More details about this document
This version:
Latest published version:
Latest editor's draft:
History: Commit history
Marcos Cáceres (Apple Inc.)
Diego González (Microsoft)
Former editors:
Matt Giuca (Google Inc.) - Until
Jay Harris (Google Inc.) - Until
GitHub w3c/badging (pull requests, new issue, open issues)


This specification defines an API that allows installed web applications to set an application badge, which is usually shown alongside the application's icon on the device's home screen or application dock.

Status of This Document

This section describes the status of this document at the time of its publication. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at

This is a work in progress.

This document was published by the Web Applications Working Group as a First Public Working Draft using the Recommendation track.

Publication as a First Public Working Draft does not imply endorsement by W3C and its Members.

This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.

This document was produced by a group operating under the W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.

This document is governed by the 2 November 2021 W3C Process Document.

1. Usage examples

This section is non-normative.

Example 1: Showing unread count on the app icon
async function updateMailBadge() {
  // Check if the API is supported.
  if (!navigator.setAppBadge) return;

  const unreadCount = await getUnreadMailCount();

  // Try to set the app badge.
  try {
    await navigator.setAppBadge(unreadCount);
  } catch (e) {
    // The badge is not supported, or the user has prevented the app
    // from setting a badge.

The badge might show up on the application's icon in the operating system. If multiple API calls within the same application set or clear a badge, the most recent one takes effect, and may continue being seen even after an application is closed.

Example 2: Showing ready status on the app icon
async function showPlayerTurn(playerTurnId) {
  if (playerTurnId === localPlayerId)
    await navigator.setAppBadge();
    await navigator.clearAppBadge();

On some operating systems setting a badge can require permission from the user. In this case, a developer need to query the "notifications" permissions status before setting a badge. If the permission is not granted, the developer will need to prompt for permission via the Notification.requestPermission().

Example 3: Checking for permission
async function checkPermission() {
  permission = await navigator.permissions.query({
    name: "notifications",
  const button = document.getElementById("permission-button");
  if (permission.state === "prompt") {
    // Prompt the user to grant permission.
    button.hidden = false;
    button.addEventListener("click", async () => {
      await Notification.requestPermission();
    }, { once: true });
  button.hidden = true;

2. Model

A badge is intended as a mechanism for installed web applications to notify the user that there is some new activity that might require their attention, or as a way of indicating a small amount of information, such as an unread count.

A badge can have one of the following values:

The special value "nothing":
Indicates that there is no badge currently set.
The special value "flag":
Indicates that the badge is set, but contains no specific value.
A number value:
Indicates that the badge is set to a numerical value greater than 0.

An installed web application has an associated badge, which is initialized to "nothing".

The user agent MAY (re)set an application's badge to "nothing" at its discretion (for example, following system conventions).

3. Displaying a badge

When the application's badge is set, the user agent or operating system SHOULD display the application's badge alongside the primary iconic representation of the application in the user's operating system (for example, as a small overlay on top of the application's icon on the home screen on a device).

A user agent MAY require express permission from the user to set the badge. When a user agent requires such permission, it SHOULD tie the permission grant to the "notifications" permission.

When the badge is set to "flag", the user agent or operating system SHOULD display an indicator with a non-specific symbol (for example, a colored circle).

When a badge's value is set to "nothing", the user agent or operating system SHOULD clear the badge by no longer displaying it.

When the badge is set to a number, the user agent or operating system:

4. Extensions to the Navigator and WorkerNavigator interfaces

interface mixin NavigatorBadge {
  Promise<undefined> setAppBadge(
    optional [EnforceRange] unsigned long long contents
  Promise<undefined> clearAppBadge();

Navigator includes NavigatorBadge;
WorkerNavigator includes NavigatorBadge;

User agents that never display application badges SHOULD NOT include NavigatorBadge.

4.1 setAppBadge() method

When the setAppBadge() method is called, the user agent MUST set the application badge of this to value of the contents argument.

4.2 clearAppBadge() method

When the clearAppBadge() method is called, the user agent MUST set the application badge of this to 0.

5. Setting the application badge

To set the application badge of platform object context to an optional unsigned long long contents value:

  1. Let global be context's relevant global object.
  2. If global is a Window object, then:
    1. Let document be global's associated Document.
    2. If document is not fully active, return a promise rejected with a InvalidStateError.
  3. Let promise be a new promise.
  4. In parallel:
    1. If this's relevant settings object's origin is not same origin with this's relevant settings object's top-level origin, queue a global task on the DOM manipulation task source given global to reject promise with a "SecurityError" and terminate this algorithm.
    2. If the user agent requires express permission to set the application badge, then:
      1. Let permissionState be the result of getting the current permission state with "notifications".
      2. If permissionState is not "granted", queue a global task on the user interaction task source given global to reject promise with a NotAllowedError and terminate this algorithm.
    3. Switching on contents, if it happens to be the case that:
      contents was not passed:
      Set badge to "flag".
      contents is 0:
      Set badge to "nothing".
      Set badge to contents.
    4. Queue a global task on the DOM manipulation task source given global to resolve promise with undefined.
  5. Return promise.

6. Privacy considerations

The API is write-only by design. There is no way for a site to read back the value of a badge that was previously set, to ensure that the application badge cannot be used as a storage or fingerprinting mechanism.

7. Security considerations

The user agent or operating system MAY clear a badge at its discretion, and to follow any system conventions (for example, when the system is reset).

Issue 68: Rate limiting the ability to set a badge

Raised by @grorg on webkit-dev:

I'd also like to see some specification text describing how the browser should ignore multiple set/clear operations executed in rapid succession (e.g. to create a blinking badge) - maybe the limit is one badge operation per minute or something?

We should address this; it might be a recommendation rather than a requirement, since it relates to the UI of the user agent.

I'd like to see some sort of "eventual consistency" guarantee which says that the final value you write to the badge will eventually be the one displayed to the user. This prevents a situation where you set "3" then 10 seconds later set "12", and due to rate limiting, the "12" never gets set, so the user just sees "3" forever. Instead, the rule should be "If the UI hasn't been updated in > N seconds, update it to the new value. Otherwise, set a timer to update the UI to the new value in N - (however long it has been since the last update) seconds."

8. Accessibility considerations

This section is non-normative.

Issue 24: Add accessibility section

If the browser is in the control of presenting the badge, it should be possible to define some accessibility guidelines.

9. Conformance

As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.

The key words MAY, MUST, SHOULD, and SHOULD NOT in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.

A. References

A.1 Normative references

Web Application Manifest. Marcos Caceres; Kenneth Christiansen; Matt Giuca; Aaron Gustafson; Daniel Murphy; Anssi Kostiainen. W3C. 29 March 2023. W3C Working Draft. URL:
HTML Standard. Anne van Kesteren; Domenic Denicola; Ian Hickson; Philip Jägenstedt; Simon Pieters. WHATWG. Living Standard. URL:
Infra Standard. Anne van Kesteren; Domenic Denicola. WHATWG. Living Standard. URL:
Notifications API Standard. Anne van Kesteren. WHATWG. Living Standard. URL:
Permissions. Marcos Caceres; Mike Taylor. W3C. 20 December 2022. W3C Working Draft. URL:
Key words for use in RFCs to Indicate Requirement Levels. S. Bradner. IETF. March 1997. Best Current Practice. URL:
Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words. B. Leiba. IETF. May 2017. Best Current Practice. URL:
Web IDL Standard. Edgar Chen; Timothy Gu. WHATWG. Living Standard. URL: