The Notifications API lets a web page or app send notifications that are displayed outside the page at the system level; this lets web apps send information to a user even if the application is idle or in the background. This article looks at the basics of using this API in your own apps.

Note: This feature is available in Web Workers.

Typically, system notifications refer to the operating system's standard notification mechanism: think for example of how a typical desktop system or mobile device broadcasts notifications.

The system notification system will vary of course by platform and browser, but this is ok, and the Notifications API is written to be general enough for compatibility with most system notification systems.

Examples

One of the most obvious use cases for web notifications is a web-based mail or IRC application that needs to notify the user when a new message is received, even if the user is doing something else with another application. Many real examples of this now exist, such as Slack.

We've written a real world demo to give more of an idea of how web notifications can be used:

.

Requesting permission

Before an app can send a notification, the user must grant the application the right to do so. This is a common requirement when an API tries to interact with something outside a web page — at least once, the user needs to specifically grant that application permission to present notifications, thereby letting the user control which apps/sites are allowed to display notifications.

Checking current permission status

You can check to see if you already have permission by checking the value of the Notification.permission read only property. It can have one of three possible values:

default
The user hasn't been asked for permission yet, so notifications won't be displayed.
granted
The user has granted permission to display notifications, after having been asked previously.
denied
The user has explicitly declined permission to show notifications.

Getting permission

If permission to display notifications hasn't been granted yet, the application needs to use the Notification.requestPermission() method to request this from the user. In its simplest form, we just include the following:

Notification.requestPermission().then(function(result) {
  console.log(result);
});

This uses the promise-version of the method, as supported in recent implementations (Firefox 47, for example.) If you want to support older versions, you might have to use the older callback version, which looks like this:

Notification.requestPermission();

The callback version optionally accepts a callback function that is called once the user has responded to the request to display permissions (as seen in the second else ... if block below.) Commonly, you'll ask for permission to display notifications when your app is first initialized, and before trying to instantiate any. If you wanted to be really thorough, you could use a construct like the following (see To-do List Notifications):

function notifyMe() {
  // Let's check if the browser supports notifications
  if (!("Notification" in window)) {
    alert("This browser does not support system notifications");
  }

  // Let's check whether notification permissions have already been granted
  else if (Notification.permission === "granted") {
    // If it's okay let's create a notification
    var notification = new Notification("Hi there!");
  }

  // Otherwise, we need to ask the user for permission
  else if (Notification.permission !== 'denied') {
    Notification.requestPermission(function (permission) {
      // If the user accepts, let's create a notification
      if (permission === "granted") {
        var notification = new Notification("Hi there!");
      }
    });
  }

  // Finally, if the user has denied notifications and you 
  // want to be respectful there is no need to bother them any more.
}

Note: Before version 37, Chrome doesn't let you call Notification.requestPermission() in the load event handler (see issue 274284).

In Chrome 62 and newer you cannot request notification api at all unless the site is https:// secured. (see issue 779612) If you do have https on the site you should be able to use notifications and background push notifications.

Creating a notification

Creating a notification is easy; just use the Notification constructor. This constructor expects a title to display within the notification and some options to enhance the notification such as an icon or a text body.

For example, in the to-do-list example we use the following snippet to create a notification when required (found inside the createNotification() function):

var img = '/to-do-notifications/img/icon-128.png';
var text = 'HEY! Your task "' + title + '" is now overdue.';
var notification = new Notification('To do list', { body: text, icon: img });

Closing notifications

Firefox and Safari close notifications automatically after a few moments (around four seconds). This may also happen at the operating system level. Some browsers don't however, such as Chrome. To make sure that the notifications close in all browsers, you can call the Notification.close function inside a setTimeout() function to close the notification after 4 seconds. Also note the use of bind() to make sure the close() call is associated with the notification.

setTimeout(notification.close.bind(notification), 4000);

Note: When you receive a "close" event, there is no guarantee that it's the user who closed the notification. This is in line with the specification, which states: "When a notification is closed, either by the underlying notifications platform or by the user, the close steps for it must be run."

Notification events

The notifications API spec lists four events that are triggered on the Notification instance:

click
Triggered when the user clicks on the notification.
close
Triggered once the notification is closed.
error
Triggered if something goes wrong with the notification; this is usually because the notification couldn't be displayed for some reason.
show
Triggered when the notification is displayed to the user.

These events can be tracked using the onclickoncloseonerror, and onshow handlers. Because Notification also inherits from EventTarget, it's possible to use the addEventListener() method on it.

Replacing existing notifications

It is usually undesirable for a user to receive a lot of notifications in a short space of time — for example, what if a messenger application notified a user for each incoming message, and they were being sent a lot? To avoid spamming the user with too many notifications, it's possible to modify the pending notifications queue, replacing single or multiple pending notifications with a new one.

To do this, it's possible to add a tag to any new notification. If a notification already has the same tag and has not been displayed yet, the new notification replaces that previous notification. If the notification with the same tag has already been displayed, the previous notification is closed and the new one is displayed.

Tag example

Assume the following basic HTML:

<button>Notify me!</button>

It's possible to handle multiple notifications this way:

window.addEventListener('load', function () {
  // At first, let's check if we have permission for notification
  // If not, let's ask for it
  if (window.Notification && Notification.permission !== "granted") {
    Notification.requestPermission(function (status) {
      if (Notification.permission !== status) {
        Notification.permission = status;
      }
    });
  }

  var button = document.getElementsByTagName('button')[0];

  button.addEventListener('click', function () {
    // If the user agreed to get notified
    // Let's try to send ten notifications
    if (window.Notification && Notification.permission === "granted") {
      var i = 0;
      // Using an interval cause some browsers (including Firefox) are blocking notifications if there are too much in a certain time.
      var interval = window.setInterval(function () {
        // Thanks to the tag, we should only see the "Hi! 9" notification 
        var n = new Notification("Hi! " + i, {tag: 'soManyNotification'});
        if (i++ == 9) {
          window.clearInterval(interval);
        }
      }, 200);
    }

    // If the user hasn't told if he wants to be notified or not
    // Note: because of Chrome, we are not sure the permission property
    // is set, therefore it's unsafe to check for the "default" value.
    else if (window.Notification && Notification.permission !== "denied") {
      Notification.requestPermission(function (status) {
        // If the user said okay
        if (status === "granted") {
          var i = 0;
          // Using an interval cause some browsers (including Firefox) are blocking notifications if there are too much in a certain time.
          var interval = window.setInterval(function () {
            // Thanks to the tag, we should only see the "Hi! 9" notification 
            var n = new Notification("Hi! " + i, {tag: 'soManyNotification'});
            if (i++ == 9) {
              window.clearInterval(interval);
            }
          }, 200);
        }

        // Otherwise, we can fallback to a regular modal alert
        else {
          alert("Hi!");
        }
      });
    }

    // If the user refuses to get notified
    else {
      // We can fallback to a regular modal alert
      alert("Hi!");
    }
  });
});

See the live result below:

Receiving notification of clicks on app notifications

When a user clicks on a notification generated by an app, you will be notified of this event in two different ways, depending on the circumstance:

  1. A click event if your app has not closed or been put in the background between the time you create the notification and the time the user clicks on it.
  2. A system message otherwise.

See this code snippet for an example of how to deal with this.

Specifications

Specification Status Comment
Notifications API Living Standard Living standard

Browser compatibility

Update compatibility data on GitHub
DesktopMobile
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome for AndroidEdge MobileFirefox for AndroidOpera for AndroidiOS SafariSamsung Internet
Basic supportChrome Full support 22
Notes
Full support 22
Notes
Notes Before Chrome 22, the support for notification followed an old prefixed version of the specification and used the navigator.webkitNotifications object to instantiate a new notification. Before Chrome 32, Notification.permission was not supported. Before Chrome 42, service worker additions were not supported. Starting in Chrome 49, notifications do not work in incognito mode.
Full support 5
Prefixed
Prefixed Requires the vendor prefix: -webkit-
Edge Full support YesFirefox Full support 22
Full support 22
Full support 4
Prefixed
Prefixed Requires the vendor prefix: -moz-
IE No support NoOpera Full support 25Safari Full support 6WebView Android No support NoChrome Android Full support YesEdge Mobile ? Firefox Android Full support 22
Full support 22
Full support 4
Prefixed
Prefixed Requires the vendor prefix: -webkit-
Opera Android Full support YesSafari iOS No support NoSamsung Internet Android ?
Available in workersChrome Full support 45Edge Full support YesFirefox Full support 41IE No support NoOpera Full support 32Safari ? WebView Android No support NoChrome Android Full support 45Edge Mobile Full support YesFirefox Android Full support 41Opera Android Full support 32Safari iOS No support NoSamsung Internet Android ?
Secure contexts onlyChrome Full support 62Edge ? Firefox ? IE No support NoOpera Full support 49Safari ? WebView Android No support NoChrome Android Full support 62Edge Mobile ? Firefox Android ? Opera Android Full support 49Safari iOS No support NoSamsung Internet Android ?
Notification() constructorChrome Full support 22
Full support 22
Full support 5
Prefixed
Prefixed Requires the vendor prefix: webkit
Edge Full support YesFirefox Full support 22
Full support 22
Full support 4
Prefixed
Prefixed Requires the vendor prefix: moz
IE No support NoOpera Full support 25Safari Full support 6WebView Android No support NoChrome Android Full support YesEdge Mobile ? Firefox Android Full support 22
Full support 22
Full support 4
Prefixed
Prefixed Requires the vendor prefix: moz
Opera Android Full support YesSafari iOS No support NoSamsung Internet Android ?
actionsChrome Full support 53Edge Full support 18Firefox No support NoIE No support NoOpera Full support 39Safari ? WebView Android No support NoChrome Android Full support 53Edge Mobile No support NoFirefox Android No support NoOpera Android Full support 39Safari iOS No support NoSamsung Internet Android ?
badgeChrome Full support 53Edge Full support 18Firefox No support NoIE No support NoOpera Full support 39Safari ? WebView Android No support NoChrome Android Full support 53Edge Mobile No support NoFirefox Android No support NoOpera Android Full support 39Safari iOS No support NoSamsung Internet Android ?
bodyChrome Full support YesEdge ? Firefox Full support YesIE No support NoOpera ? Safari ? WebView Android No support NoChrome Android Full support YesEdge Mobile ? Firefox Android Full support YesOpera Android ? Safari iOS No support NoSamsung Internet Android ?
dataChrome Full support YesEdge ? Firefox Full support YesIE No support NoOpera ? Safari ? WebView Android No support NoChrome Android Full support YesEdge Mobile ? Firefox Android Full support YesOpera Android ? Safari iOS No support NoSamsung Internet Android ?
dirChrome Full support YesEdge ? Firefox Full support YesIE No support NoOpera ? Safari ? WebView Android No support NoChrome Android Full support YesEdge Mobile ? Firefox Android Full support YesOpera Android ? Safari iOS No support NoSamsung Internet Android ?
iconChrome Full support 22
Full support 22
Full support 5
Prefixed
Prefixed Requires the vendor prefix: -webkit-
Edge ? Firefox Full support 22
Full support 22
Full support 4
Prefixed
Prefixed Requires the vendor prefix: -moz-
IE No support NoOpera Full support 25Safari No support NoWebView Android No support NoChrome Android Full support YesEdge Mobile ? Firefox Android Full support 22
Full support 22
Full support 4
Prefixed
Prefixed Requires the vendor prefix: -moz-
Opera Android Full support YesSafari iOS No support NoSamsung Internet Android ?
imageChrome Full support 53Edge Full support 18Firefox No support NoIE No support NoOpera Full support 40Safari ? WebView Android No support NoChrome Android Full support 53Edge Mobile ? Firefox Android No support NoOpera Android Full support 40Safari iOS No support NoSamsung Internet Android ?
langChrome Full support YesEdge ? Firefox Full support YesIE No support NoOpera ? Safari ? WebView Android No support NoChrome Android Full support YesEdge Mobile ? Firefox Android Full support YesOpera Android ? Safari iOS No support NoSamsung Internet Android ?
maxActionsChrome Full support YesEdge Full support 18Firefox No support NoIE No support NoOpera ? Safari ? WebView Android No support NoChrome Android Full support YesEdge Mobile ? Firefox Android No support NoOpera Android ? Safari iOS No support NoSamsung Internet Android ?
onclickChrome Full support YesEdge ? Firefox No support NoIE No support NoOpera ? Safari ? WebView Android No support NoChrome Android Full support YesEdge Mobile ? Firefox Android No support NoOpera Android ? Safari iOS No support NoSamsung Internet Android ?
oncloseChrome Full support YesEdge ? Firefox Full support YesIE No support NoOpera ? Safari ? WebView Android No support NoChrome Android Full support YesEdge Mobile ? Firefox Android Full support YesOpera Android ? Safari iOS No support NoSamsung Internet Android ?
onerrorChrome Full support YesEdge ? Firefox No support NoIE No support NoOpera ? Safari ? WebView Android No support NoChrome Android Full support YesEdge Mobile ? Firefox Android No support NoOpera Android ? Safari iOS No support NoSamsung Internet Android ?
onshowChrome Full support YesEdge ? Firefox Full support YesIE No support NoOpera ? Safari ? WebView Android No support NoChrome Android Full support YesEdge Mobile ? Firefox Android Full support YesOpera Android ? Safari iOS No support NoSamsung Internet Android ?
permissionChrome Full support YesEdge ? Firefox Full support YesIE No support NoOpera ? Safari ? WebView Android No support NoChrome Android Full support YesEdge Mobile ? Firefox Android Full support YesOpera Android ? Safari iOS No support NoSamsung Internet Android ?
renotifyChrome Full support 50Edge No support NoFirefox No support NoIE No support NoOpera Full support 37Safari No support NoWebView Android No support NoChrome Android Full support 50Edge Mobile No support NoFirefox Android No support NoOpera Android Full support 37Safari iOS No support NoSamsung Internet Android ?
requireInteractionChrome Full support YesEdge Full support 17Firefox No support NoIE No support NoOpera ? Safari ? WebView Android No support NoChrome Android Full support YesEdge Mobile Full support 17Firefox Android No support NoOpera Android ? Safari iOS No support NoSamsung Internet Android ?
silentChrome Full support 43Edge Full support 17Firefox No support NoIE No support NoOpera Full support 30Safari No support NoWebView Android No support NoChrome Android Full support 43Edge Mobile Full support 17Firefox Android No support NoOpera Android Full support 30Safari iOS No support NoSamsung Internet Android ?
tagChrome Full support YesEdge ? Firefox Full support YesIE No support NoOpera ? Safari ? WebView Android No support NoChrome Android Full support YesEdge Mobile ? Firefox Android Full support YesOpera Android ? Safari iOS No support NoSamsung Internet Android ?
timestampChrome Full support YesEdge Full support 17Firefox No support NoIE No support NoOpera ? Safari ? WebView Android No support NoChrome Android Full support YesEdge Mobile Full support 17Firefox Android No support NoOpera Android ? Safari iOS No support NoSamsung Internet Android ?
titleChrome Full support YesEdge ? Firefox No support NoIE No support NoOpera ? Safari ? WebView Android No support NoChrome Android Full support YesEdge Mobile ? Firefox Android No support NoOpera Android ? Safari iOS No support NoSamsung Internet Android ?
vibrateChrome Full support 53Edge No support NoFirefox No support NoIE No support NoOpera Full support 39Safari ? WebView Android No support NoChrome Android Full support 53Edge Mobile No support NoFirefox Android No support NoOpera Android Full support 39Safari iOS No support NoSamsung Internet Android ?
closeChrome Full support YesEdge ? Firefox Full support YesIE No support NoOpera ? Safari ? WebView Android No support NoChrome Android Full support YesEdge Mobile ? Firefox Android Full support YesOpera Android ? Safari iOS No support NoSamsung Internet Android ?
requestPermissionChrome Full support 46Edge ? Firefox Full support 47IE No support NoOpera Full support 40Safari ? WebView Android No support NoChrome Android Full support 46Edge Mobile ? Firefox Android Full support YesOpera Android Full support 40Safari iOS No support NoSamsung Internet Android ?

Legend

Full support  
Full support
No support  
No support
Compatibility unknown  
Compatibility unknown
See implementation notes.
See implementation notes.
Requires a vendor prefix or different name for use.
Requires a vendor prefix or different name for use.

See also