How to Reliably Send Data When Users Close a Page: sendBeacon vs fetch keepalive

This article explains why traditional fetch or XMLHttpRequest calls often fail during page unload, and demonstrates two modern browser APIs—navigator.sendBeacon and fetch with keepalive:true—that reliably transmit analytics or draft data without blocking the user experience.

JavaScript
JavaScript
JavaScript
How to Reliably Send Data When Users Close a Page: sendBeacon vs fetch keepalive

We often need to send important data just before a user closes a page or tab.

Traditional asynchronous requests such as fetch or XMLHttpRequest are frequently aborted by the browser during unload events ( pagehide, unload) because the JavaScript environment disappears.

Why do normal requests fail?

When the unload handler fires, the browser may cancel any pending request since the page is being destroyed.

Developers used synchronous XMLHttpRequest, which blocks the main thread and freezes the UI.

Modern solution 1: navigator.sendBeacon()

navigator.sendBeacon()

is a W3C API designed to send a small amount of data asynchronously and non‑blocking, even after the page is closed.

How it works

Calling sendBeacon() queues the request internally and returns immediately; the browser ensures the request is sent later, regardless of page unload.

Features

High reliability : guaranteed delivery by the browser.

Asynchronous, non‑blocking : does not delay page close.

Simple to use : straightforward API.

Data limits : only POST, no custom headers.

Code example

Send analytics data when the user leaves the page:

// Use 'pagehide' which is more reliable than 'unload'
window.addEventListener('pagehide', (event) => {
  if (event.persisted) return;
  const analyticsData = {
    timeOnPage: Math.round(performance.now()),
    lastAction: 'close_tab',
  };
  const blob = new Blob([JSON.stringify(analyticsData)], {
    type: 'application/json; charset=UTF-8',
  });
  const success = navigator.sendBeacon('/log-analytics', blob);
  if (success) {
    console.log('Analytics log queued successfully.');
  } else {
    console.error('Failed to send analytics log.');
  }
});

Modern solution 2: fetch() with keepalive: true

Setting keepalive: true in the fetch init object tells the browser to continue the request after the page is unloaded.

How it works

The request is marked as “keep‑alive”, allowing its lifetime to outlive the page, similar to sendBeacon.

Features

High flexibility : supports various HTTP methods (POST, PUT, etc.) and limited custom headers.

Unified API : works with existing fetch code.

Cannot read response : like sendBeacon, the response cannot be processed after unload.

Code example

Automatically save a draft when the page is closed:

window.addEventListener('pagehide', (event) => {
  if (event.persisted) return;
  const draftContent = document.getElementById('editor').value;
  if (!draftContent) return;
  const draftData = {
    content: draftContent,
    timestamp: Date.now(),
  };
  // fetch with keepalive
  fetch('/api/drafts/save', {
    method: 'PUT',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(draftData),
    keepalive: true,
  });
  console.log('Draft save request submitted.');
});

How to choose?

If you only need to send simple analytics or log data, navigator.sendBeacon() is the most direct choice. For greater flexibility, such as using other HTTP methods or custom headers, fetch({ keepalive: true }) is preferable.

Both APIs let you deliver critical data without compromising user experience.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaScriptWeb APIfetch keepalivepagehidesendBeaconunload
JavaScript
Written by

JavaScript

Provides JavaScript enthusiasts with tutorials and experience sharing on web front‑end technologies, including JavaScript, Node.js, Deno, Vue.js, React, Angular, HTML5, CSS3, and more.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.