An Overview of the Web Storage API

Web developers have long yearned for a way to store data long term. Cookies are an option, but they can only store 4KB of data.  Additionally, cookies are sent to the server with each HTTP request. This means that cookies, especially large ones, can consume considerable network bandwidth.  There have been other attempts to implement storage techniques, but for the most part they have been hacks.  Then, along came HTML5 and the Web Storage API to the rescue.

The Web Storage API defines two types of storage areas ― local storage and session storage.  Local storage is persistent data which remains until it is explicitly deleted, or until the browser’s cache is cleared.  According to the specification, browsers should allocate at least 5MB of local storage per domain.  The second storage type, session storage, is also persistent data, however the data is tied to a “top-level browsing context” (i.e. a browser tab or window).  Session data remains until it is either deleted or the browsing context is closed.  Session storage is particularly useful when a user is interacting with multiple instances of the same website.  In such a situation, using local storage could result in the different instances overwriting each others data.

The two types of storage areas are accessed through global objects named “localStorage” and “sessionStorage”.  Both storage areas implement the exact same API.  Data is stored as key/value pairs, and all data is stored in string form.  When adding data to storage, it is implicitly converted to a string.  However, when the string data is retrieved from storage it needs to be explicitly converted to the appropriate data type using functions such as parseInt().  When dealing with objects, the JSON.parse() and JSON.stringify() methods should be used for serialization and deserialization.

Detecting Storage Support

The Web Storage API, like many other HTML5 features, is not supported by all browsers.  To check if a browser supports storage, use the function shown below.  The function checks for the existence of the global “localStorage” object.  A similar function could be created to check for session storage, but it can be safely assumed that if one storage area exists, then so does the other.

function localStorageSupported() {
 try {
  return "localStorage" in window && window["localStorage"] !== null;
 } catch (e) {
  return false;
 }
}

Storing Data

Data is added to storage using the setItem() method.  setItem() takes a key and value as arguments.  If the key does not already exist in storage, then the key/value pair is added.  If the key is already present, then the value is updated.  Several example setItem() usages are shown below.  The examples show how to add data of various types to local and session storage.  Notice that the “key” argument must always be a string, while the type of “value” can vary.

localStorage.setItem("key", "value");
sessionStorage.setItem("foo", 3.14);
localStorage.setItem("bar", true);
sessionStorage.setItem("baz", JSON.stringify(object));

Data can also be added to storage using object property assignment statements.  The previous setItem() examples have been rewritten below using assignment statements. Note that the assignment to “key” on the first line will fail silently.  This is because the storage areas have a built in function named key() that will be covered later.  For this reason, the API methods are the preferred way to access storage.

localStorage.key = "value"; // this fails silently
sessionStorage.foo = 3.14;
localStorage["bar"] = true;
sessionStorage["baz"] = JSON.stringify(object);

If a site attempts to store too much data, eventually the browser’s storage quota will be exceeded and an exception will be thrown.  To handle this case, try-catch blocks should be used when storing data.  An example of this is shown below.

try {
 localStorage.setItem("key", "value");
} catch (e) {
 alert("Exceeded Storage Quota!");
}

Reading Stored Data

To read data from storage, the getItem() method is used.  getItem() takes a lookup key as its sole argument.  If the key exists in storage, then the corresponding value is returned.  If the key does not exist, then null is returned.  The following examples use the getItem() method to retrieve the data stored in the setItem() examples.

var string = localStorage.getItem("key");
var number = sessionStorage.getItem("foo");
var boolean = localStorage.getItem("bar");
var object = JSON.parse(sessionStorage.getItem("baz"));

Stored data can also be accessed by reading properties of the “localStorage” and “sessionStorage” objects.  The previous getItem() examples have been rewritten below using object property syntax.

var string = localStorage.key;
var number = sessionStorage.foo;
var boolean = localStorage["bar"];
var object = JSON.parse(sessionStorage["baz"]);

Iterating Over Stored Data

Often times, it is necessary to programmatically loop over all of the items in storage.  The loop’s upper bound is determined by the “length” property of the particular storage area.  The stored keys can be retrieved one at a time using the key() method.  key() takes a single integer parameter that acts as an index to the storage area.  An example of looping over each key/value pair in “localStorage” is shown below.  Of course, session storage can be processed in a similar fashion by substituting “sessionStorage” for “localStorage”.

for (var i = 0; i < localStorage.length; i++) {
 var key = localStorage.key(i);
 var value = localStorage.getItem(key);

 // do something with the key and value
}

Deleting Stored Data

When data is no longer needed, it should be explicitly removed.  This is especially true for local storage, as it will persist even after the browser is closed.  To delete individual key/value pairs from storage, the removeItem() method is used.  The removeItem() method takes the key to be deleted as its only parameter.  If the key is not present then nothing will happen.  Examples of the removeItem() method are shown below.

localStorage.removeItem("key");
sessionStorage.removeItem("foo");
localStorage.removeItem("bar");
sessionStorage.removeItem("baz");

The delete operator can also be used to remove stored data.  The previous example is rewritten below using delete instead of removeItem().

delete localStorage.key;
delete sessionStorage.foo;
delete localStorage["bar"];
delete sessionStorage["baz"];

While removeItem() is used to delete individual pieces of data, the clear() method is used to delete all stored data.  Usages of the clear() method are shown below.

localStorage.clear();
sessionStorage.clear();

The storage Event

A user can potentially have several instances of the same site open at any given time.  Changes made to a storage area in one instance need to be reflected in the other instances.  The Web Storage API accomplishes this synchronization using the “storage” event.  When a storage area is changed, a “storage” event is fired for any other tabs/windows that are sharing the storage area.  Note that a “storage” event is not fired for the tab/window that changes the storage area.

Storage areas can be changed by calls to setItem(), removeItem(), and clear().  However, not all calls to these methods actually change the storage area.  For example, calling clear() on an empty storage area or removeItem() on a key that does not exist will not change the storage area, and therefore will not fire an event.

The “storage” event object has several fields of interest which are described below.  Following the description of the fields is an example “storage” event handler.

  • “key” ― This field is the key argument of setItem() or removeItem(), or null when clear() caused the event to be fired.
  • “newValue” ― The “value” argument to setItem() is reflected in this field.  Calls to removeItem() and clear() cause this field to be null.
  • “oldValue” ― This field holds the key’s value prior to a call to setItem() or removeItem().  Calls to clear() cause this field to be null.
  • “url” ― The “url” field stores the address of the page whose storage area was affected.
  • “storageArea” ― The “storageArea” field corresponds to the local or session storage area that was changed.
window.addEventListener("storage", function(event) {
 var key = event.key;
 var newValue = event.newValue;
 var oldValue = event.oldValue;
 var url = event.url;
 var storageArea = event.storageArea;

 // handle the event
});

Example Page

The following code implements a sample page for manipulating local storage.  The page is also available online here.  The example covers the entire local storage API, including the “storage” event.  In order to see the “storage” event in action, the page must be open in at least two separate tabs/windows of the same browser.  The “storage” event will also only work if the page is served over HTTP (i.e. the file:// protocol will not work).

<!DOCTYPE html>
<html>
<head>
 <title>Web Storage Example</title>
 <meta charset="UTF-8" />
 <script>
  "use strict";
  window.addEventListener("load", function(event) {
   var key = document.getElementById("key");
   var value = document.getElementById("value");
   var add = document.getElementById("add");
      var remove = document.getElementById("remove");
      var clear = document.getElementById("clear");
      var content = document.getElementById("content");

   add.addEventListener("click", function(event) {
        if (key.value !== "") {
     try {
           localStorage.setItem(key.value, value.value);
     } catch (e) {
      alert("Exceeded Storage Quota!");
     }
          refreshContents();
        }
      });

      remove.addEventListener("click", function(event) {
        if (key.value !== "") {
          localStorage.removeItem(key.value);
          refreshContents();
        }
      });

      clear.addEventListener("click", function(event) {
        localStorage.clear();
        refreshContents();
      });

      window.addEventListener("storage", function(event) {
        var k = event.key;
        var newValue = event.newValue;
        var oldValue = event.oldValue;
        var url = event.url;
        var storageArea = event.storageArea;

        alert("EVENT:n" + k + "n" + newValue + "n" + oldValue + "n" + url + "n" + storageArea);
        refreshContents();
      });

      function refreshContents() {
        var str = "";

        for (var i = 0, len = localStorage.length; i < len; i++) {
          var k = localStorage.key(i);
          var v = localStorage.getItem(k);

          str += "'" + k + "' = '" + v + "'<br />";
        }

    key.value = "";
    value.value = "";
        content.innerHTML = str;
      }

      refreshContents();
    });
  </script>
</head>
<body>
  Key:  <input type="text" id="key" /><br />
  Value: <input type="text" id="value" /><br />
  <input type="button" id="add" value="Add to Storage" />&nbsp;
  <input type="button" id="remove" value="Remove from Storage" />&nbsp;
  <input type="button" id="clear" value="Clear Storage" /><br />
  Contents of Local Storage:<br />
  <span id="content"></span>
</body>
</html>

Things to Remember

  • Local storage persists until it is explicitly deleted or the browser’s cache is cleared.
  • Session storage persists until it is explicitly deleted or the browsing context is closed.
  • Data stored by one browser is not accessible by another browser.  For example, data stored by Chrome is not seen by Firefox.
  • Objects should be stored as JSON strings.
  • For security reasons, sensitive data should not be stored, especially in local storage.
  • Changes to a storage area cause a “storage” event to be fired.
  • As with many other HTML5 features, web storage is not yet implemented consistently.

Storage image via Shutterstock

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • Damu

    cool! Never knew you could use local storage. Gr8 writeup.

  • http://www.devseo.co.uk/ Alex Hall

    Started writing a wrapper that uses localStorage if available, but falls back to a cookie implementation. http://webdesignandseo.net/scripts/localstorage/