Why Push Notifications Fail When Browser Is Closed and How to Fix Them
This article explains why web push notifications stop working when the browser is closed, how Android and desktop browsers handle push messages, how to open added‑to‑desktop web apps in full‑screen, the evolution from GCM to FCM, and provides detailed troubleshooting steps for authorization, payload encryption, connection issues, HTTP status codes, and error reporting.
FAQ
Why push notifications stop working when the browser is closed
On Android the system wakes the app when a push message arrives, even if the app is closed, and the browser is similarly awakened to trigger the service worker. On desktop operating systems the behavior depends on whether the browser process is still running; on macOS you can see a dock icon marker indicating a running app. If the browser is completely closed (no marker), push messages cannot be delivered. The same applies to Windows, though detecting background Chrome is more complex.
How to open a Web App added to the desktop in full‑screen when a push is clicked
On Android Chrome, a Web App added to the home screen can be launched without an address bar in full‑screen mode. Developers want the same experience when a user clicks a notification. Chrome attempts to open the app in standalone mode, but only if the site has been launched from the desktop within the last ten days; otherwise the notification opens a normal browser UI.
Thus, unless users frequently launch the site from the desktop, notifications will open a regular browser window. This behavior will be improved in future Chrome versions.
On Android, a site added to the desktop should be allowed to open in standalone mode. However, because Chromium cannot detect whether the site is on the desktop, it heuristically opens sites that have been launched from the desktop in the last ten days in standalone mode. – Chrome Issue
Why is this better than WebSockets?
Service workers can run even when the browser window is closed, whereas WebSockets require the page to stay open.
What are GCM, FCM, Web Push and Chrome?
December 2014
Chrome initially used Google Cloud Messaging (GCM) for push, which required a Google Developers Console account, a special sender ID shared by the web app, and a custom API that was not a true Web Push implementation.
GCM required developers to register an account on the Google Developers Console.
Chrome and GCM needed a special sender ID shared by the web app.
GCM used a custom API request format rather than a web standard.
July 2016
Chrome introduced Application Server Keys (VAPID) and switched to Firebase Cloud Messaging (FCM), which does not require a Google or Firebase project and follows the standard Web Push protocol.
Chrome and Application Server Keys no longer need a Google/Firebase project.
FCM supports the Web Push protocol, allowing the same request format across browsers.
Why is it confusing now?
Many existing articles still reference GCM, which is now outdated. Treat Web Push as a browser feature that uses a push service conforming to the Web Push protocol, ignoring the specifics of the underlying service.
Web Push: Common Issues and Bug Reporting
When troubleshooting Web Push, first verify that the service worker is correctly registered and updated. Common problems arise during sending messages, receiving messages, authorization, payload encryption, and connection issues.
Authorization issues
Most developers encounter authorization errors when configuring the VAPID (application server) key. In Chrome with FCM, errors such as UnauthorizedRegistration occur when the Authorization header is missing, the key used for subscription differs from the one used to sign the header, or the JWT is expired or malformed.
<code><HTML>
<HEAD>
<TITLE>UnauthorizedRegistration</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000">
<H1>UnauthorizedRegistration</H1>
<H2>Error 400</H2>
</BODY>
</HTML>
</code>Firefox and Mozilla autopush provide clearer error messages for missing Authorization headers, returning Unauthorized .
<code>{
"errno": 109,
"message": "Request did not validate missing authorization header",
"code": 401,
"more_info": "http://autopush.readthedocs.io/en/latest/http.html#error-codes",
"error": "Unauthorized"
}
</code>HTTP status codes
429 – Too many requests; the push service has hit a rate limit and includes a Retry‑After header.
400 – Bad request; an invalid or malformed header.
404 – Not found; the subscription has expired and should be removed.
410 – Gone; the subscription is no longer valid and should be unsubscribed.
413 – Payload too large; the message exceeds the minimum 4 KB size limit.
Payload encryption problems
If a push is sent successfully (201 response) but the service worker does not receive the event, the browser likely failed to decrypt the payload. Chrome’s chrome://gcm-internals can be used to record and view “Message decryption failed” logs.
Tools such as Peter Beverloo’s push encryption validator and Mozilla’s data encryption test page can help debug encryption issues.
Connection problems
If no push event is received and there are no decryption errors, the browser may not be connected to the push service. In Chrome, chrome://gcm-internals shows a “CONNECTED” status; otherwise, recreate the profile or file a bug report.
Error reporting
If the above steps do not resolve the issue, file a bug with the appropriate browser (Chrome or Firefox), providing the browser version, a reproducible example, full request and response details, and any relevant source code.
Yuewen Frontend Team
Click follow to learn the latest frontend insights in the cultural content industry. We welcome you to join us.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.