Suggest an editImprove this articleRefine the answer for “The beforeunload event”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**`beforeunload` fires right before the current page is unloaded: when the user closes the tab, reloads the page, or follows a link.** If the handler calls `event.preventDefault()` and assigns `event.returnValue = ''`, the browser shows its standard confirmation dialog; you cannot supply your own text, modern browsers ignore it for security and UX reasons. It is also the last point where something can be written synchronously to `localStorage`, because asynchronous `fetch` requests will not finish in time. ```javascript window.addEventListener('beforeunload', (event) => { if (formChanged) { event.preventDefault(); event.returnValue = ''; // required } }); ``` **Key point:** `beforeunload` is the last chance to warn that the user has unsaved data.Shown above the full answer for quick recall.Answer (EN)Image**`beforeunload` is an event that fires before the current page is unloaded from the browser's memory.** It happens when the user closes the tab or window, reloads the page, or follows a link or types a new URL. ## Theory ### TL;DR - Listened for on `window`, it fires before the page is unloaded. - `event.preventDefault()` together with `event.returnValue = ''` shows the standard leave confirmation dialog. - You cannot set your own dialog text, browsers ignore it. - Show the dialog only when there really are unsaved changes. - Asynchronous work (`fetch`, timers) does not finish here; a synchronous `localStorage` write does. - `beforeunload` can be cancelled, `unload` can no longer be. ### Quick example ```javascript window.addEventListener('beforeunload', (event) => { event.preventDefault(); event.returnValue = ''; // required! }); ``` After that the browser shows a **leave confirmation dialog**: > Do you really want to leave this page? > The data you entered may be lost. **Important:** - Modern browsers **do not let you set your own text** in that window. It used to be possible to write `event.returnValue = 'Are you sure?'`, but it is ignored now. - This was done **for security and UX**, so that sites cannot pressure the user with messages such as "stay with us". ### When to use it Use it when the user may **lose unsaved changes**, for example when they: - are editing text but have not pressed "Save"; - are filling in a form; - are writing a comment; - are doing something in an app with unsaved state. ```javascript let formChanged = false; document.querySelector('form').addEventListener('input', () => { formChanged = true; }); window.addEventListener('beforeunload', (e) => { if (formChanged) { e.preventDefault(); e.returnValue = ''; } }); ``` Now, if the user has changed the form and tries to leave, a warning appears. ### A quiet hook before leaving, without a dialog If you only need to run cleanup or some logic before unloading, with no dialog: ```javascript window.addEventListener('beforeunload', () => { localStorage.setItem('lastVisited', new Date().toISOString()); }); ``` This event is the last point where data can be saved to `localStorage` or `sessionStorage`. ### The difference between beforeunload and unload | Event | When it fires | Can it stop the exit | When to use it | | --- | --- | --- | --- | | `beforeunload` | Before unloading | Yes, via `preventDefault()` | Warning about unsaved data | | `unload` | After unloading has started | No | Cleanup, analytics, logging | ### Limitations - You **cannot** use `alert()` or `confirm()` inside `beforeunload`, browsers block them. - Do not start **asynchronous operations** (requests, `fetch`), they will not finish. For analytics there is `navigator.sendBeacon()`. - It works **only in a browser window or tab**, not in frames. - Better not to attach it without a reason, it is UX spam. Many browsers will not show the dialog at all if the user has not interacted with the page yet. ### Summary | What it does | The `beforeunload` event | | --- | --- | | When it fires | Before the user leaves the page | | What it is for | Warning about the loss of unsaved data | | How to stop the exit | `event.preventDefault()` plus `event.returnValue = ''` | | Custom text | Not possible, the browser shows its standard one | | When it does not fit | Asynchronous work, it will not have time to run | > **An easy way to remember:** > `beforeunload` is the "last chance" to tell the browser: "Stop! The user has unsaved data." ### Common mistakes - **Attaching the handler unconditionally.** A dialog on every exit is annoying and protects nothing. Keep an "unsaved changes" flag and check it inside the handler. - **Forgetting `event.returnValue = ''`.** In some browsers `preventDefault()` alone is not enough and the dialog simply never appears. - **Counting on custom text.** A string returned from the handler or assigned to `returnValue` is not displayed anywhere any more. - **Sending analytics with `fetch`.** The request is torn down with the page. That is what `navigator.sendBeacon()` exists for, and the browser delivers it after the unload. - **Not removing the handler after saving.** After a successful `submit` you have to reset the flag or call `removeEventListener`, otherwise the user sees the warning even though the data is already saved. - **Relying on `unload`.** It is not guaranteed to fire on mobile and it breaks the bfcache, so back and forward caching stops working. To persist state, listening to `visibilitychange` with the `hidden` state is more reliable.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.