jsguides

Broadcast Channel API

The Broadcast Channel API lets tabs, windows, iframes, and web workers on the same origin send messages to each other. It is a simple alternative to postMessage when you do not need to target a specific window — any context listening on the same channel receives the message.

Basic Usage

Create a channel and start sending messages:

const channel = new BroadcastChannel("app-state");

// Listen for messages
channel.onmessage = (event) => {
  console.log("Received:", event.data);
};

// Send a message to all other contexts on this channel
channel.postMessage({ type: "user-login", userId: 12345 });

Every context that creates a BroadcastChannel("app-state") with the same name joins the same channel. Messages sent from one context reach all other contexts on that channel.

Closing a Channel

const channel = new BroadcastChannel("sync");
channel.postMessage({ type: "data-update", payload: { count: 42 } });
channel.close();  // stop receiving messages

After close(), the channel is disconnected. It cannot be reopened — create a new instance if needed.

Cross-Tab State Synchronization

Use a broadcast channel to keep multiple tabs in sync:

// In each tab
const stateChannel = new BroadcastChannel("app-state");

// Store current state
let appState = { theme: "light", sidebar: true };

// When state changes, broadcast to other tabs
function updateState(patch) {
  appState = { ...appState, ...patch };
  stateChannel.postMessage({
    type: "state-update",
    state: appState,
    timestamp: Date.now()
  });
}

// Receive state updates from other tabs
stateChannel.onmessage = (event) => {
  if (event.data.type === "state-update") {
    appState = event.data.state;
    renderApp();
  }
};

When the user changes theme in tab A, tab B and tab C receive the update and re-render automatically.

Communicating with Web Workers

// main.js — in the main thread
const workerChannel = new BroadcastChannel("worker-messages");

workerChannel.onmessage = (event) => {
  console.log("Worker says:", event.data);
};

// Send work to the worker
const worker = new Worker("processor.js");

worker.onmessage = (event) => {
  // This is standard postMessage
  workerChannel.postMessage({ result: event.data });
};
// processor.js — in the worker
self.onmessage = (event) => {
  // Send result back via standard postMessage
  // The main thread broadcasts it to other contexts
  self.postMessage({ processed: event.data.value * 2 });
};

Note: the Broadcast Channel and postMessage between main thread and workers are separate APIs. Messages from workers arrive via onmessage on the worker, not via BroadcastChannel. Use the broadcast channel to redistribute those messages to other contexts.

Message Format

Any structured-cloneable value works as the message payload:

channel.postMessage("simple string");
channel.postMessage({ key: "value", numbers: [1, 2, 3] });
channel.postMessage(new Uint8Array([0x68, 0x69]));  // ArrayBuffer views
channel.postMessage(null);  // works too

Comparing Communication APIs

APIUse when
BroadcastChannelBroadcasting to all contexts on the same origin
postMessageSending to a specific window or worker
MessageChannelPoint-to-point communication between two specific contexts
localStorage eventReacting to storage changes across tabs

BroadcastChannel is simpler than postMessage when you need fan-out: one message reaches everyone listening. postMessage requires keeping a reference to the target window.

Authentication State Sync Example

Keep authentication state consistent across tabs:

const authChannel = new BroadcastChannel("auth-events");

// Simulated auth check
let currentUser = null;

function login(user) {
  currentUser = user;
  authChannel.postMessage({
    type: "login",
    user: user,
    at: Date.now()
  });
}

function logout() {
  currentUser = null;
  authChannel.postMessage({
    type: "logout",
    at: Date.now()
  });
}

// React to auth events from other tabs
authChannel.onmessage = (event) => {
  const { type, user } = event.data;

  if (type === "login") {
    currentUser = user;
    updateUI();
  } else if (type === "logout") {
    currentUser = null;
    showLoginScreen();
  }
};

When a user logs out in tab A, all other open tabs receive the broadcast and update their UI accordingly.

Limitations

Same origin only. Channels cannot communicate across origins. If you need cross-origin messaging, postMessage with a target origin is the correct tool.

No delivery confirmation. postMessage delivers asynchronously with no acknowledgment. If you need confirmation of delivery, implement a reply protocol yourself.

Browser support. BroadcastChannel is supported in all modern browsers. Internet Explorer does not support it. For IE support, use a localStorage-based fallback or a library.

See Also