[javascript] Communication between tabs or windows

I was searching for a way how to communicate between multiple tabs or windows in a browser (on the same domain, not CORS) without leaving traces. There were several solutions:

  1. using window object
  2. postMessage
  3. cookies
  4. localStorage

The first is probably the worst solution - you need to open a window from your current window and then you can communicate only as long as you keep the windows open. If you reload the page in any of the windows, you most likely lost the communication.

Second approach, using postMessage, probably enables cross-origin communication, but suffers the same problem as the first approach. You need to maintain a window object.

Third way, using cookies, store some data in the browser, which can effectively look like sending a message to all windows on the same domain, but the problem is that you can never know if all tabs read the "message" already or not before cleaning up. You have to implement some sort of timeout to read the cookie periodically. Furthermore you are limited by maximum cookie length, which is 4KB.

Fourth solution, using localStorage, seemed to overcome the limitations of cookies, and it can be even listen-to using events. How to use it is described in the accepted answer.

Edit 2018: the accepted answer still works, but there is a newer solution for modern browsers, to use BroadcastChannel. See the other answer for a simple example describing how to easily transmit message between tabs by using BroadcastChannel.

This question is related to javascript html browser broadcast-channel

The answer is


Another method that people should consider using is Shared Workers. I know it's a cutting edge concept, but you can create a relay on a Shared Worker that is MUCH faster than localstorage, and doesn't require a relationship between the parent/child window, as long as you're on the same origin.

See my answer here for some discussion I made about this.


I've created a library sysend.js, it's very small, you can check its source code. The library don't have any external dependencies.

You can use it for communication between tabs/windows in same browser and domain. The library use BroadcastChannel, if supported, or storage event from localStorage.

API is very simple:

sysend.on('foo', function(message) {
    console.log(message);
});
sysend.broadcast('foo', {message: 'Hello'});
sysend.broadcast('foo', "hello");
sysend.broadcast('foo'); // empty notification

when your brower support BroadcastChannel it sent literal object (but it's in fact auto-serialized by browser) and if not it's serialized to JSON first and deserialized on other end.

Recent version also have helper API to create proxy for Cross-Domain communication. (it require single html file on target domain).

Here is demo.

EDIT:

New version also support Cross-Domain communication, if you include special proxy.html file on target domain and call proxy function from source domain:

sysend.proxy('https://target.com');

(proxy.html it's very simple html file, that only have one script tag with the library).

If you want two way communication you need to do the same on other domain.

NOTE: If you will implement same functionality using localStorage, there is issue in IE. Storage event is sent to the same window, which triggered the event and for other browsers it's only invoked for other tabs/windows.


I created a module that works equal to the official Broadcastchannel but has fallbacks based on localstorage, indexeddb and unix-sockets. This makes sure it always works even with Webworkers or NodeJS. See pubkey:BroadcastChannel


There is a modern API dedicated for this purpose - Broadcast Channel

It is as easy as:

var bc = new BroadcastChannel('test_channel');

bc.postMessage('This is a test message.'); /* send */

bc.onmessage = function (ev) { console.log(ev); } /* receive */

There is no need for the message to be just a DOMString, any kind of object can be sent.

Probably, apart from API cleanness, it is the main benefit of this API - no object stringification.

Currently supported only in Chrome and Firefox, but you can find a polyfill that uses localStorage.


Checkout AcrossTabs - Easy communication between cross-origin browser tabs. It uses a combination of postMessage and sessionStorage API to make communication much easier and reliable.


There are different approaches and each one has its own advantages and disadvantages. Lets discuss each:

  1. LocalStorage

    Pros:

    1. Web storage can be viewed simplistically as an improvement on cookies, providing much greater storage capacity. If you look at the Mozilla source code we can see that 5120KB (5MB which equals 2.5 Million chars on Chrome) is the default storage size for an entire domain. This gives you considerably more space to work with than a typical 4KB cookie.
    2. The data is not sent back to the server for every HTTP request (HTML, images, JavaScript, CSS, etc) - reducing the amount of traffic between client and server.
    3. The data stored in localStorage persists until explicitly deleted. Changes made are saved and available for all current and future visits to the site.

    Cons:

    1. It works on same-origin policy. So, data stored will only be able available on the same origin.
  2. Cookies

    Pros:

    1. Compared to others, there's nothing AFAIK.

    Cons:

    1. The 4K limit is for the entire cookie, including name, value, expiry date etc. To support most browsers, keep the name under 4000 bytes, and the overall cookie size under 4093 bytes.
    2. The data is sent back to the server for every HTTP request (HTML, images, JavaScript, CSS, etc) - increasing the amount of traffic between client and server.

      Typically, the following are allowed:

      • 300 cookies in total
      • 4096 bytes per cookie
      • 20 cookies per domain
      • 81920 bytes per domain(Given 20 cookies of max size 4096 = 81920 bytes.)
  3. sessionStorage

    Pros:

    1. It is similar to localStorage.
    2. Changes are only available per window (or tab in browsers like Chrome and Firefox). Changes made are saved and available for the current page, as well as future visits to the site on the same window. Once the window is closed, the storage is deleted

    Cons:

    1. The data is available only inside the window/tab in which it was set.
    2. The data is not persistent i.e. it will be lost once the window/tab is closed.
    3. Like localStorage, tt works on same-origin policy. So, data stored will only be able available on the same origin.
  4. PostMessage

    Pros:

    1. Safely enables cross-origin communication.
    2. As a data point, the WebKit implementation (used by Safari and Chrome) doesn't currently enforce any limits (other than those imposed by running out of memory).

    Cons:

    1. Need to open a window from the current window and then can communicate only as long as you keep the windows open.
    2. Security concerns - Sending strings via postMessage is that you will pick up other postMessage events published by other JavaScript plugins, so be sure to implement a targetOrigin and a sanity check for the data being passed on to the messages listener.
  5. A combination of PostMessage + SessionStorage

    Using postMessage to communicate between multiple tabs and at the same time using sessionStorage in all the newly opened tabs/windows to persist data being passed. Data will be persisted as long as the tabs/windows remain opened. So, even if the opener tab/window gets closed, the opened tabs/windows will have the entire data even after getting refreshed.

I have written a JavaScript library for this, named AcrossTabs which uses postMessage API to communicate between cross-origin tabs/windows and sessionStorage to persist the opened tabs/windows identity as long as they live.


I wrote an article on this on my blog: http://www.ebenmonney.com/blog/how-to-implement-remember-me-functionality-using-token-based-authentication-and-localstorage-in-a-web-application .

Using a library I created storageManager you can achieve this as follows:

storageManager.savePermanentData('data', 'key'): //saves permanent data
storageManager.saveSyncedSessionData('data', 'key'); //saves session data to all opened tabs
storageManager.saveSessionData('data', 'key'); //saves session data to current tab only
storageManager.getData('key'); //retrieves data

There are other convenient methods as well to handle other scenarios as well


There's a tiny open-source component to sync/communicate between tabs/windows of the same origin (disclaimer - I'm one of the contributors!) based around localStorage.

TabUtils.BroadcastMessageToAllTabs("eventName", eventDataString);

TabUtils.OnBroadcastMessage("eventName", function (eventDataString) {
    DoSomething();
});

TabUtils.CallOnce("lockname", function () {
    alert("I run only once across multiple tabs");
});

https://github.com/jitbit/TabUtils

P.S. I took the liberty to recommend it here since most of the "lock/mutex/sync" components fail on websocket connections when events happen almost simultaneously


For those searching for a solution not based on jQuery, this is a plain JavaScript version of the solution provided by Thomas M:

window.addEventListener("storage", message_receive);

function message_broadcast(message) {
    localStorage.setItem('message',JSON.stringify(message));
}

function message_receive(ev) {
    if (ev.key == 'message') {
        var message=JSON.parse(ev.newValue);
    }
}

This is a development storage part of Tomas M answer for Chrome. We must add listener

window.addEventListener("storage", (e)=> { console.log(e) } );

Load/save item in storage not runt this event - we MUST trigger it manually by

window.dispatchEvent( new Event('storage') ); // THIS IS IMPORTANT ON CHROME

and now, all open tab-s will receive event


Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to html

Embed ruby within URL : Middleman Blog Please help me convert this script to a simple image slider Generating a list of pages (not posts) without the index file Why there is this "clear" class before footer? Is it possible to change the content HTML5 alert messages? Getting all files in directory with ajax DevTools failed to load SourceMap: Could not load content for chrome-extension How to set width of mat-table column in angular? How to open a link in new tab using angular? ERROR Error: Uncaught (in promise), Cannot match any routes. URL Segment

Examples related to browser

How to force reloading a page when using browser back button? How do we download a blob url video How to prevent a browser from storing passwords How to Identify Microsoft Edge browser via CSS? Edit and replay XHR chrome/firefox etc? Communication between tabs or windows How do I render a Word document (.doc, .docx) in the browser using JavaScript? "Proxy server connection failed" in google chrome Chrome - ERR_CACHE_MISS How to check View Source in Mobile Browsers (Both Android && Feature Phone)

Examples related to broadcast-channel

Communication between tabs or windows