Skip to main content

The beforeunload event

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

EventWhen it firesCan it stop the exitWhen to use it
beforeunloadBefore unloadingYes, via preventDefault()Warning about unsaved data
unloadAfter unloading has startedNoCleanup, 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 doesThe beforeunload event
When it firesBefore the user leaves the page
What it is forWarning about the loss of unsaved data
How to stop the exitevent.preventDefault() plus event.returnValue = ''
Custom textNot possible, the browser shows its standard one
When it does not fitAsynchronous 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.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.