Skip to main content

The unload event

unload is an event that fires when the document is being unloaded from the browser's memory. It runs at the very last moment of the page's life, when the navigation can no longer be stopped and all you can do is clean up quickly.

Theory

TL;DR

  • unload fires when the user closes the tab, reloads the page (F5), follows a link, or navigates to another page with a full reload.
  • You cannot stop the navigation or show a dialog from an unload handler; that is what beforeunload is for.
  • Asynchronous work (fetch, setTimeout) does not get a chance to finish: the browser does not wait for it.
  • Only synchronous actions work, for example writing to localStorage, plus navigator.sendBeacon().
  • In some browsers (Safari, iOS) unload may not fire at all; the modern replacement is pagehide.
  • Typical jobs: logging the exit, saving state, closing WebSocket connections.

Quick example

javascript
window.addEventListener('unload', () => { // runs at the very last moment, when the page is already leaving memory console.log('The page is unloading...'); });

When unload fires

The event happens when the document leaves the browser's memory. In practice that means the user:

  • closes the tab;
  • reloads the page (F5);
  • follows another link;
  • or moves to another page in an SPA with a full reload.

Typical use cases:

  • sending statistics or logs "before the user leaves";
  • saving data to localStorage / sessionStorage;
  • closing connections, WebSockets, releasing resources.

For example, storing the time of the last visit:

javascript
window.addEventListener('unload', () => { localStorage.setItem('lastVisited', new Date().toISOString()); });

unload is not beforeunload

The two events are easy to confuse, but they solve different problems: beforeunload fires before the unload and can still stop it, while unload fires during the unload, when it is already too late to decide anything.

Propertybeforeunloadunload
When it firesBefore unloadingDuring unloading
Can the exit be stoppedYes (preventDefault())No
Can a warning be shownYesNo
Can code be executedYes, but with limitsVery limited
Typical jobsWarn about unsaved dataCleanup, logging

Limits and caveats

Modern browsers restrict unload heavily so that closing pages is not slowed down:

  • Asynchronous actions (fetch, setTimeout) do not work, the browser does not wait for them to complete.
  • You cannot show a dialog or a modal window.
  • Only synchronous operations work, for example writing to localStorage, or navigator.sendBeacon().
  • In some browsers (Safari, iOS) unload is not fired at all, they use pagehide instead.

One more downside: merely having an unload handler (same for beforeunload) makes the page ineligible for the bfcache, the back/forward cache, so returning to it becomes slower.

pagehide is a more modern and more reliable event, especially in mobile browsers:

javascript
window.addEventListener('pagehide', (event) => { // event.persisted === true means the page is going into the bfcache console.log('The page was hidden or unloaded'); });

It works even when the user switches to another tab and fires more reliably than unload. For analytics people often add visibilitychange with the hidden state as well, because on mobile that is the only moment guaranteed to happen.

Sending analytics when the page closes

The only safe way to send data to the server at closing time is navigator.sendBeacon(): the request is queued by the browser and delivered even after the page is gone.

javascript
window.addEventListener('unload', () => { navigator.sendBeacon('/analytics', JSON.stringify({ event: 'exit' })); });

Formally the call is asynchronous, but the browser takes delivery upon itself, so the data is not lost the way it would be with a plain fetch.

A summary of the event:

What it doesThe unload event
When it firesWhen the user leaves the page
Can the navigation be stoppedNo
Good forCleanup, logs, saving state
Does it work asynchronouslyNo (synchronous only, or via sendBeacon)
Modern alternativepagehide
Common useAnalytics, saving state

An easy way to remember: beforeunload means "warn before leaving", unload means "clean up after leaving".

Common mistakes

  • Calling fetch in unload. The browser aborts the request together with the page; use navigator.sendBeacon().
  • Counting on setTimeout or promises. Micro- and macrotasks will not run any more, the document is leaving memory.
  • Trying to cancel the navigation in unload. preventDefault() has no effect here, that is the job of beforeunload.
  • Relying on unload in mobile Safari. The event may never fire and the state is lost; listen to pagehide or visibilitychange.
  • Forgetting that the handler breaks the bfcache. The page stops being cached, so going "back" becomes slower.
  • Doing heavy work in the handler. Long synchronous code visibly delays closing the tab for the user.

Short Answer

Interview ready
Premium

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