Requesting Desktop Notification Permissions in JS
Learn the correct way to request notification permission in JavaScript, handle user denial, and build a permission-aware notification flow.
Browsers block desktop notifications by default. Before your web app can display a notification, the user must explicitly grant permission through a browser dialog. How you ask for that permission determines whether the user accepts or permanently blocks your app.
The permission model is simple: check the current state first, then ask at the right moment on a user action.
if (Notification.permission === "granted") {
console.log("Permission already granted");
} else if (Notification.permission === "denied") {
console.log("Permission was denied, cannot ask again");
} else {
console.log("Permission is default, ready to ask");
}The three permission states are "granted", "denied", and "default". The default state means the user has not made a decision yet, and this is your one opportunity to ask.
The permission request flow
The flow from no permission to granted permission follows a clear path. Understanding each step helps you build a user experience that maximizes acceptance:
The flow starts by checking the current permission. If already granted, you can send notifications immediately, and if denied, there is nothing more you can do.
If the state is default, show your own opt-in prompt before triggering the browser dialog.
Asking at the right time
Never call requestPermission on page load. Modern browsers silently ignore it. The call must come from a user gesture like a click:
document.querySelector("#enableNotifications").addEventListener("click", () => {
Notification.requestPermission().then((permission) => {
if (permission === "granted") {
console.log("Notifications enabled");
} else {
console.log("User declined notifications");
}
});
});The button click satisfies the user gesture requirement. The browser shows its native permission dialog, and the promise resolves with the user's choice. The best time to show your enable button is after the user has experienced value from your app, not on the first page load where they have no reason to say yes.
Building a custom opt-in prompt
The most effective pattern uses a two-step approach: show a custom prompt explaining why notifications are useful, then call requestPermission only after the user agrees. Start with a function that builds and inserts the prompt element:
function createOptInPrompt() {
const prompt = document.createElement("div");
prompt.innerHTML = `
<p>Get notified when your builds finish.</p>
<button id="allowBtn">Enable notifications</button>
<button id="dismissBtn">Not now</button>
`;
document.body.appendChild(prompt);
return prompt;
}This function only builds and displays the prompt, it does not wire up any behavior yet. A second function creates the prompt and attaches the click handlers that respond to the user's choice:
function showOptInPrompt() {
const prompt = createOptInPrompt();
document.querySelector("#allowBtn").addEventListener("click", () => {
prompt.remove();
Notification.requestPermission();
});
document.querySelector("#dismissBtn").addEventListener("click", () => {
prompt.remove();
});
}This separates your messaging from the browser's native prompt. Users who click Enable in your UI are far more likely to click Allow in the browser dialog than users who see the browser dialog with no context.
Handling the denied state
Once the user denies permission, you cannot ask again from code. The only way to reset it is for the user to manually change the site settings in their browser preferences. Your app must handle this state gracefully:
function setupNotifications() {
if (Notification.permission === "granted") {
return;
}
if (Notification.permission === "denied") {
console.log("Notifications are blocked. The user can re-enable them in browser settings.");
return;
}
showOptInPrompt();
}Do not show the opt-in prompt when the permission is already denied. It wastes the user's time and creates frustration. Instead, show a message explaining how to re-enable notifications through browser settings if your app critically depends on them.
Checking permission on page load
The permission state persists across page reloads and browser restarts. Check it every time your page loads to know whether you can send notifications:
document.addEventListener("DOMContentLoaded", () => {
if (Notification.permission === "granted") {
console.log("Ready to send notifications");
} else if (Notification.permission === "default") {
console.log("Show opt-in prompt after user engagement");
}
});This lets you show the opt-in prompt at the right moment without repeatedly calling requestPermission. Once the user decides, the state sticks.
Common mistakes
- Calling requestPermission immediately on page load. Browsers require a user gesture and silently ignore the call.
- Showing the opt-in prompt when permission is already denied. The user cannot change their decision from your code.
- Assuming the user will grant permission. Design your app so notifications are an enhancement, not a requirement.
- Not providing a way to disable notifications after the user enables them. Respect user preference changes.
Related articles
- JavaScript Notifications API: Complete Tutorial -- sending and configuring notifications after permission is granted
- How to Add Event Listeners in JS: Complete Guide -- event handling for the opt-in button
- Handling Click Events in JavaScript: Full Guide -- click handling patterns
Quick reference
| Scenario | Code |
|---|---|
| Check permission | Notification.permission |
| Request permission | Notification.requestPermission() |
| Only ask on gesture | Wrap in a click event listener |
| Denied is permanent | Cannot re-request from code |
| Build double opt-in | Show custom prompt, then call requestPermission |
| Check on page load | Read Notification.permission in DOMContentLoaded |
Rune AI
Key Insights
- Check Notification.permission before calling requestPermission.
- Only call requestPermission from a user gesture like a button click.
- Build a custom opt-in UI that explains the value before the browser prompt appears.
- A denied permission is permanent for that origin. Design your UX for the denied state.
- The permission state persists across page reloads and browser restarts.
Frequently Asked Questions
Why does Notification.requestPermission do nothing on page load?
Can I ask for permission again after the user denies it?
How do I show a custom prompt before the browser permission dialog?
Does the permission persist across page reloads?
Conclusion
Requesting notification permission the right way means checking the current state first, asking only on a user gesture, and respecting the user's decision whether they grant or deny. A custom opt-in step before the browser prompt dramatically improves the chance the user says yes.
More in this topic
Using Decorators for Logging in JS Architecture
Learn how JavaScript decorators wrap class methods to add logging without touching the original code, including setup with Babel and how execution order works.
JavaScript While Loop Explained: A Complete Guide
A while loop repeats code as long as a condition stays true. Learn the syntax, see practical examples, and understand when a while loop is the right choice over a for loop.
JavaScript Loops Tutorial: for, while, do while
Loops let JavaScript repeat code without writing it twice. Learn the three core loop types, what each one does, and when to choose one over another.