How Safari Web Apps Use the Badging API for Notifications
This article explains how the Badging API enables web applications installed through the Safari browser to display unread notification counts directly on their Home Screen or macOS Dock icons. It covers the system and permission prerequisites for using the API on Apple devices, the specific JavaScript methods required to set and clear badges, and how the API integrates with Service Workers to update counts even when the web app is closed.
Prerequisites for Safari Web Apps
Before a web app can display an icon badge via Safari, it must meet specific installation and permission criteria enforced by WebKit:
- Installation: The web app cannot display badges inside a standard Safari browser tab. On iOS and iPadOS (16.4 or later), the user must install the app using the "Add to Home Screen" option in the Share menu. On macOS Sonoma (Safari 17 or later), the user must install it using the "Add to Dock" option.
- Notification Permission: For privacy reasons,
Safari requires the user to explicitly grant notification permissions
before allowing a web app to display a badge. The app must call
Notification.requestPermission()and receive a"granted"status before the Badging API will function.
Setting the Unread Count
The Badging API is exposed on the global navigator
object. This allows developers to update the badge both from the main
application window and from a background Service Worker.
To display an unread count, you use the setAppBadge()
method and pass an integer representing the number of unread items:
// Sets the badge on the Home Screen or Dock icon to 5
if ('setAppBadge' in navigator) {
navigator.setAppBadge(5).catch((error) => {
console.error('Failed to set app badge:', error);
});
}The method returns a Promise, allowing developers to handle any potential errors if the platform fails to apply the badge.
Clearing the Badge
Once a user opens the web app and views their messages or notifications, the badge should be removed. There are two ways to clear the badge using the API:
- Call the dedicated
clearAppBadge()method. - Pass the number
0into thesetAppBadge()method.
// Removes the badge from the app icon
if ('clearAppBadge' in navigator) {
navigator.clearAppBadge().catch((error) => {
console.error('Failed to clear app badge:', error);
});
}Updating Badges in the Background
For an unread count to be useful, it must update even when the user does not have the web app actively open. Safari supports this by allowing the Badging API to run inside a Service Worker alongside the Push API.
When a backend server sends a push notification to the user's device,
the web app's Service Worker wakes up in the background to handle the
push event. Within this event listener, the Service Worker
parses the incoming data to determine the new unread count and updates
the icon immediately:
// Inside sw.js (Service Worker)
self.addEventListener('push', (event) => {
const data = event.data.json();
const unreadCount = data.unreadCount;
// Update the badge count
if ('setAppBadge' in navigator) {
event.waitUntil(navigator.setAppBadge(unreadCount));
}
// Display the standard push notification to the user
event.waitUntil(
self.registration.showNotification(data.title, {
body: data.message
})
);
});By tying navigator.setAppBadge() to the
push event using event.waitUntil(), the
Service Worker ensures the operating system does not terminate the
background process before the Home Screen or Dock icon badge is
successfully updated.