Skip to content

The Notification interface: constructing and reading a single notification

Published

In one line: Notification is the interface behind a single displayed notification — new Notification(title, options) creates and immediately shows one from a page, its read-only properties (title, body, data, …) mirror the options it was constructed with, and it fires click, close, and error events you can listen for.

if ('Notification' in window && Notification.permission === 'granted') {
const n = new Notification('Order shipped', {
body: 'Your order #1234 is on its way.',
icon: '/icons/parcel.png',
tag: 'order-1234',
data: { orderId: '1234' },
});
n.addEventListener('click', () => {
window.focus();
n.close();
});
}

Per MDN, obtain permission with Notification.requestPermission() before constructing — see the Notifications API entry for the full permission flow.

  • body — the secondary text shown below the title.
  • icon — a URL for the icon image shown with the notification.
  • tag — per MDN, an identifying string for the notification; can be combined with renotify (which requires a non-empty tag) to alert the user again on replacement.
  • data — per MDN, arbitrary structured-clonable data, read back via notification.data.
  • requireInteraction — a boolean; when true, per MDN the notification stays visible until the user interacts with it or dismisses it, rather than closing automatically.
  • click — fires when the user clicks the notification.
  • close — per MDN, fires when the user closes the notification.
  • error — fires if something goes wrong displaying the notification.

The mobile limitation: use the service worker instead

Section titled “The mobile limitation: use the service worker instead”

Per MDN, calling the Notification() constructor directly throws a TypeError on nearly all mobile browsers, because a page’s script normally is not running in the background on mobile — the exact scenario a notification is meant to reach. The mobile-safe path is to register a service worker and call ServiceWorkerRegistration.showNotification() instead, which supports the same options plus action buttons and works without an open page:

async function notifyFromServiceWorker(title, options) {
if (
!('serviceWorker' in navigator) ||
!('Notification' in window) ||
Notification.permission !== 'granted'
) {
// Fallback: no service worker support, no Notification API, or no permission —
// do nothing rather than call the constructor and risk the mobile TypeError.
return;
}
const registration = await navigator.serviceWorker.ready;
if (typeof registration.showNotification !== 'function') {
// Fallback: the registration exists but showNotification is unavailable —
// nothing more to do without the mobile-safe API.
return;
}
await registration.showNotification(title, options);
}

See Web Push and iOS and Safari Web Push for how this applies to push-delivered notifications.

Per MDN, Notification has limited availability and is not Baseline, because it does not work the same way in every widely-used browser — the constructor’s mobile-browser TypeError above is one instance of that gap. See The Notifications API for the broader per-platform permission and availability notes.

  • Per MDN, call Notification.requestPermission() and check for granted before constructing.
  • Set a tag on related notifications and pair it with renotify when you want the user alerted again on replacement.
  • Read notification.data in the click handler for any payload the notification needs to act on.
  • Call notification.close() yourself on click if you don’t want it to linger.
  • On mobile, or anywhere push-driven notifications are needed, use ServiceWorkerRegistration.showNotification() instead of the page constructor.