PushManager.hasPermission() is a deprecated, non-standard instance method that returned push permission as granted, denied, or default. Learn what it did, why MDN replaced it with permissionState(), how to feature-detect it, and modern alternatives—with five examples and try-it labs.
01
Kind
Instance method
02
Returns
Promise
03
Values
granted / denied
04
Status
Deprecated
05
Replace
permissionState
06
Spec
Non-standard
Fundamentals
Introduction
Before subscribing to push, your app needs to know whether the user granted permission. Early Push API drafts exposed hasPermission() on PushManager for that check.
MDN now marks it deprecated and non-standard. The standardized replacement is permissionState(), which returns "prompt", "denied", or "granted". This tutorial explains the legacy method so you can read old code and migrate safely.
⚠️
Do not use in new code
For new push features, call registration.pushManager.permissionState({ userVisibleOnly: true }) or read Notification.permission when notifications cover your use case.
Concept
Understanding hasPermission()
A legacy instance method on PushManager that queried push permission state asynchronously.
Parameters — none.
Returns — Promise<PushPermissionStatus>.
granted — push permission allowed.
denied — push permission blocked.
default — user has not decided yet.
Superseded by — permissionState() (Baseline Widely available).
Available in Web Workers per MDN (where still supported).
Foundation
📝 Syntax
JavaScript
pushManager.hasPermission()
Return value
A Promise resolving to "granted", "denied", or "default".
Legacy pattern
JavaScript
// Legacy — do not use in new code
const registration = await navigator.serviceWorker.ready;
if (registration.pushManager.hasPermission) {
const status = await registration.pushManager.hasPermission();
console.log(status); // "granted" | "denied" | "default"
}
PushManager.hasPermission() is Deprecated and Non-standard on MDN. It may be missing in modern browsers. Use permissionState() instead. Logos use the shared browser-image-sprite.png sprite from this project.
✓ Deprecated · Non-standard
PushManager.hasPermission()
Legacy push permission check — avoid in new code.
LegacyDeprecated API
Google ChromeMay be removed — use permissionState()
Legacy only
Mozilla FirefoxLegacy support may vary
Legacy only
Apple SafariUnlikely — use permissionState()
Not supported
Microsoft EdgeFollow Chromium — prefer permissionState()
Legacy only
OperaFollow Chromium
Legacy only
Internet ExplorerNo Push API
Not supported
hasPermission()Limited
Bottom line: Feature-detect before calling. Prefer permissionState() for new push permission checks.
Wrap Up
Conclusion
pushManager.hasPermission() was an early way to read push permission as granted, denied, or default. MDN deprecates it in favor of permissionState(). Learn it for legacy code; build new features with the modern API or Notification.permission.
Fall back to Notification.permission when appropriate
Separate permission checks from subscribe()
Update UI for denied vs prompt states
❌ Don’t
Call hasPermission() in new production code
Assume it exists on all PushManager instances
Confuse permission with an existing subscription
Ignore MDN’s deprecated warning
Ship tutorials that teach hasPermission as current API
Summary
Key Takeaways
Knowledge Unlocked
Five things to remember about hasPermission()
Legacy push permission—and what to use instead.
5
Core concepts
⚠️01
Deprecated
avoid new use
Status
🔄02
Promise
async
Returns
🔒03
3 states
granted/denied
Values
🚀04
Replace
permissionState
Modern
🚫05
Non-standard
off spec
Spec
❓ Frequently Asked Questions
It returns a Promise that resolves to a PushPermissionStatus string: "granted", "denied", or "default"—indicating whether the web app has push permission.
MDN marks it Deprecated and Non-standard. It is not Experimental, but it is no longer recommended and has been superseded by permissionState(). Do not use it in new code.
Use PushManager.permissionState() for the modern Push API permission check. For simple notification permission, Notification.permission may also suffice.
No. MDN documents hasPermission() with no parameters. Call it on a PushManager instance: registration.pushManager.hasPermission().
granted means push is allowed; denied means blocked; default means the user has not decided yet (prompt may appear on subscribe).
You may encounter it in legacy tutorials or old codebases. Understanding it helps you migrate safely to permissionState() or Notification.permission.
Did you know?
MDN maps legacy default from hasPermission() to prompt in permissionState()—both mean the user has not made a permission choice yet.