Copyright © 2025 World Wide Web Consortium . W3C ® liability , trademark and permissive document license rules apply.
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.
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 standards and drafts index .
This is a work in progress.
This document was published by the Web Applications Working Group as an Editor's Draft.
Publication as an Editor's 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 a 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 that 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 18 August 2025 W3C Process Document .
This section is non-normative.
async function updateMailBadge() {
// Check if the API is supported.
if (!navigator.setAppBadge) return;
const unreadCount = await getUnreadMailCount();
// Set the app badge - this will always succeed if the API is supported.
// The operating system controls whether the badge is actually displayed.
try {
await navigator.setAppBadge(unreadCount);
} catch (e) {
// Errors are rare and typically indicate API unavailability
// or security restrictions, not permission issues.
}
}
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.
async function showPlayerTurn(playerTurnId) {
if (playerTurnId === localPlayerId)
await navigator.setAppBadge();
else
await navigator.clearAppBadge();
}
On
some
operating
systems
systems,
the
actual
display
of
a
badge
to
the
user
may
depend
on
notification
permissions,
even
though
setting
a
badge
can
require
permission
from
will
always
succeed
(even
if
the
user.
In
this
case,
a
developer
need
badge
value
is
not
displayed
to
query
the
user).
Developers
can
optionally
check
the
"
notifications
"
permissions
status
before
setting
a
badge.
If
the
permission
is
not
granted,
the
developer
will
need
to
status
and
prompt
for
permission
via
the
Notification
.
requestPermission
()
.
to
help
ensure
badge
visibility
on
platforms
where
this
is
relevant.
async function checkNotificationPermissionForBadge() {
// Always set the badge first - this will succeed regardless of permissions
await navigator.setAppBadge(5);
// Check if notification permission might affect badge visibility const permission = await navigator.permissions.query({
name: "notifications",
});
const button = document.getElementById("permission-button");
if (permission.state === "prompt") {
// Show option to grant permission for badge visibility
button.hidden = false;
button.addEventListener("click", async () => {
await Notification.requestPermission();
();
checkNotificationPermissionForBadge();
}, { once: true });
return;
}
button.hidden = true;
}
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 :
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).
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
The
operating
system
ultimately
controls
whether
a
badge
from
is
displayed
to
the
user
user,
typically
through
system-level
application
settings.
On
some
platforms,
calling
Notification
.
requestPermission
()
can
be
necessary
for
a
badge
to
become
visible
to
the
user,
even
though
the
badge
itself
can
be
successfully
set
by
the
badge.
When
a
application
.
The
user
agent
requires
such
permission
,
it
SHOULD
tie
the
permission
grant
allow
applications
to
the
"
notifications
set
"
permission.
badges
regardless
of
permission
state,
with
the
understanding
that
the
operating
system
will
control
the
actual
display
behavior.
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:
To
set
the
application
badge
of
platform
object
context
to
an
optional
unsigned
long
long
contents
value:
Window
object,
then:
Document
.
InvalidStateError
"
DOMException
.
SecurityError
"
DOMException
.
undefined
.
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.
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).
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."
This section is non-normative.
If the browser is in the control of presenting the badge, it should be possible to define some accessibility guidelines.
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.
Referenced in:
Referenced in: