Local Storage And How To Use It On Websites

Advertisement

Storing information locally on a user’s computer is a powerful strategy for a developer who is creating something for the Web. In this article, we’ll look at how easy it is to store information on a computer to read later and explain what you can use that for.

Adding State To The Web: The “Why” Of Local Storage

The main problem with HTTP as the main transport layer of the Web is that it is stateless. This means that when you use an application and then close it, its state will be reset the next time you open it. If you close an application on your desktop and re-open it, its most recent state is restored.

This is why, as a developer, you need to store the state of your interface somewhere. Normally, this is done server-side, and you would check the user name to know which state to revert to. But what if you don’t want to force people to sign up?

This is where local storage comes in. You would keep a key on the user’s computer and read it out when the user returns.

C Is For Cookie. Is That Good Enough For Me?

The classic way to do this is by using a cookie. A cookie is a text file hosted on the user’s computer and connected to the domain that your website runs on. You can store information in them, read them out and delete them. Cookies have a few limitations though:

  • They add to the load of every document accessed on the domain.
  • They allow up to only 4 KB of data storage.
  • Because cookies have been used to spy on people’s surfing behavior, security-conscious people and companies turn them off or request to be asked every time whether a cookie should be set.

To work around the issue of local storage — with cookies being a rather dated solution to the problem — the WHATWG and W3C came up with a few local storage specs1, which were originally a part of HTML5 but then put aside because HTML5 was already big enough.

Using Local Storage In HTML5-Capable Browsers

Using local storage2 in modern browsers is ridiculously easy. All you have to do is modify the localStorage object in JavaScript. You can do that directly or (and this is probably cleaner) use the setItem() and getItem() method:

localStorage.setItem('favoriteflavor','vanilla');

If you read out the favoriteflavor key, you will get back “vanilla”:

var taste = localStorage.getItem('favoriteflavor');
// -> "vanilla"

To remove the item, you can use — can you guess? — the removeItem() method:

localStorage.removeItem('favoriteflavor');
var taste = localStorage.getItem('favoriteflavor');
// -> null

That’s it! You can also use sessionStorage instead of localStorage if you want the data to be maintained only until the browser window closes.

Working Around The “Strings Only” Issue

One annoying shortcoming of local storage is that you can only store strings in the different keys. This means that when you have an object, it will not be stored the right way.

You can see this when you try the following code:

var car = {};
car.wheels = 4;
car.doors = 2;
car.sound = 'vroom';
car.name = 'Lightning McQueen';
console.log( car );
localStorage.setItem( 'car', car );
console.log( localStorage.getItem( 'car' ) );

Trying this out in the console shows that the data is stored as [object Object] and not the real object information:

Objects get turned into a descriptive string when stored

You can work around this by using the native JSON.stringify() and JSON.parse() methods:

var car = {};
car.wheels = 4;
car.doors = 2;
car.sound = 'vroom';
car.name = 'Lightning McQueen';
console.log( car );
localStorage.setItem( 'car', JSON.stringify(car) );
console.log( JSON.parse( localStorage.getItem( 'car' ) ) );

Encoding as JSON means you keep the right format of the object in local storage

Where To Find Local Storage Data And How To Remove It

During development, you might sometimes get stuck and wonder what is going on. Of course, you can always access the data using the right methods, but sometimes you just want to clear the plate. In Opera, you can do this by going to Preferences → Advanced → Storage, where you will see which domains have local data and how much:

Local Storage in Opera3
Large view4

Doing this in Chrome is a bit more problematic, which is why we made a screencast:

Mozilla has no menu access so far, but will in future. For now, you can go to the Firebug console and delete storage manually easily enough.

So, that’s how you use local storage. But what can you use it for?

Use Case #1: Local Storage Of Web Service Data

One of the first uses for local storage that I discovered was caching data from the Web when it takes a long time to get it. My World Info5 entry for the Event Apart 10K challenge shows what I mean by that.

When you call the demo the first time, you have to wait up to 20 seconds to load the names and geographical locations of all the countries in the world from the Yahoo GeoPlanet6 Web service. If you call the demo a second time, there is no waiting whatsoever because — you guessed it — I’ve cached it on your computer using local storage.

The following code (which uses jQuery) provides the main functionality for this. If local storage is supported and there is a key called thewholefrigginworld, then call the render() method, which displays the information. Otherwise, show a loading message and make the call to the Geo API using getJSON(). Once the data has loaded, store it in thewholefrigginworld and call render() with the same data:

if(localStorage && localStorage.getItem('thewholefrigginworld')){
  render(JSON.parse(localStorage.getItem('thewholefrigginworld')));
} else {
  $('#list').html('

'+loading+'

'); var query = 'select centroid,woeid,name,boundingBox'+ ' from geo.places.children(0)'+ ' where parent_woeid=1 and placetype="country"'+ ' | sort(field="name")'; var YQL = 'http://query.yahooapis.com/v1/public/yql?q='+ encodeURIComponent(query)+'&diagnostics=false&format=json'; $.getJSON(YQL,function(data){ if(localStorage){ localStorage.setItem('thewholefrigginworld',JSON.stringify(data)); } render(data); }); }

You can see the difference in loading times in the following screencast:

The code for the world info is available on GitHub7.

This can be extremely powerful. If a Web service allows you only a certain number of calls per hour but the data doesn’t change all that often, you could store the information in local storage and thus keep users from using up your quota. A photo badge, for example, could pull new images every six hours, rather than every minute.

This is very common when using Web services server-side. Local caching keeps you from being banned from services, and it also means that when a call to the API fails for some reason, you will still have information to display.

getJSON() in jQuery is especially egregious in accessing services and breaking their cache, as explained in this blog post from the YQL team8. Because the request to the service using getJSON() creates a unique URL every time, the service does not deliver its cached version but rather fully accesses the system and databases every time you read data from it. This is not efficient, which is why you should cache locally and use ajax() instead.

Use Case #2: Maintaining The State Of An Interface The Simple Way

Another use case is to store the state of interfaces. This could be as crude as storing the entire HTML or as clever as maintaining an object with the state of all of your widgets. One instance where I am using local storage to cache the HTML of an interface is the Yahoo Firehose research interface9 (source on GitHub10):

The code is very simple — using YUI3 and a test for local storage around the local storage call:

YUI().use('node', function(Y) {
  if(('localStorage' in window) && window['localStorage'] !== null){
    var key = 'lastyahoofirehose';
  
    localStorage.setItem(key,Y.one('form').get('innerHTML'));
  
  if(key in localStorage){
      Y.one('#mainform').set('innerHTML',localStorage.getItem(key));
      Y.one('#hd').append('

Notice: We restored your last search for you - not live data'); } } });

You don’t need YUI at all; it only makes it easier. The logic to generically cache interfaces in local storage11 is always the same: check if a “Submit” button has been activated (in PHP, Python, Ruby or whatever) and, if so, store the innerHTML of the entire form; otherwise, just read from local storage and override the innerHTML of the form.

The Dark Side Of Local Storage

Of course, any powerful technology comes with the danger of people abusing it for darker purposes. Samy, the man behind the “Samy is my hero” MySpace worm12, recently released a rather scary demo called Evercookie13, which shows how to exploit all kind of techniques, including local storage, to store information of a user on their computer even when cookies are turned off. This code could be used in all kinds of ways, and to date there is no way around it.

Research like this shows that we need to look at HTML5′s features and add-ons from a security perspective very soon to make sure that people can’t record user actions and information without the user’s knowledge. An opt-in for local storage, much like you have to opt in to share your geographic location, might be in order; but from a UX perspective this is considered clunky and intrusive. Got any good ideas?

(al)

Footnotes

  1. 1 http://dev.w3.org/html5/webstorage/
  2. 2 http://hacks.mozilla.org/2009/06/localstorage/
  3. 3 /wp-content/uploads/2010/10/opera-e1285930764969.png
  4. 4 http://coding.smashingmagazine.com/wp-content/uploads/2010/10/opera-e1285930764969.png
  5. 5 http://10k.aneventapart.com/Entry/185
  6. 6 http://developer.yahoo.com/geo
  7. 7 http://github.com/codepo8/worldinfo
  8. 8 http://www.yqlblog.net/blog/2010/03/12/avoiding-rate-limits-and-getting-banned-in-yql-and-pipes-caching-is-your-friend/
  9. 9 http://ff8phhaa.joyent.us/firehose-research/index.php
  10. 10 http://github.com/codepo8/firehose-research
  11. 11 http://www.wait-till-i.com/2010/08/26/using-html5-storage-to-cache-application-interfaces/
  12. 12 http://namb.la/popular/tech.html
  13. 13 http://samy.pl/evercookie/

↑ Back to topShare on Twitter

An international Developer Evangelist working for Mozilla in the lovely town of London, England.

Advertising
  1. 1

    For your information, “onstorage” event doesn’t seems implemented yet in Firefox nor Safari…. except iPad ?!?!?

    -31
  2. 2

    Very nice article Christian!
    Btw, really good talk at Fronteers, I enjoyed!

    0
  3. 3

    Good article. I always get a bit of a chuckle out of the new and shiny HTML5 technologies when Flash has had local storage for years. Even if the site wasn’t a “Flash site”, using Flash as a method for storing and receiving locally stored data (and passing back via ExternalInterface) was a powerful alternative to a cookie (not to mention the ability to store native objects instead of just strings!).

    As Apple throws their weight around with their ban against Flash on their devices, developers will have to start finding new ways (like HTML5′s local storage) to do the things that were already working so well in the past.

    -4
  4. 4

    Seeing/removing local storage in Chrome is *way* easier than shown in this demo. Just open the developer tools. CMD+Shift+J and then check the storage tab. Local storage is listed on the left along with cookies and local DBs. Just view and remove.

    -2
  5. 5

    And what do you do with your shiny project when you encounter users like me who block all local storage, I wonder?

    Because the flip side is – local storage can be abused, and as such is a security risk. There are going to be a lot of IT people out there who will shut this stuff down. A lot of the IT security sites are having discussion on exactly this point already.

    So while it’s a cool technology – what are your plans for degrading gracefully?

    -3
  6. 6

    Obviously, you should use
    if(window.localStorage) …
    instead of
    if(localStorage) …
    And it seems there’s no way of storing actual live objects (with methods!) in localStorage… That’s too bad.
    I love use case #2
    – edit
    In case of your world-thingie: if you abort before all data is loaded, NULL is saved into the localStorage and next time nothing else is loaded: oops.

    0
  7. 7

    Thanks Chris!

    I’ve got a much better undestanding localStorage now, I especially like the idea of storing the badges for different API’s and not having to request them all the time!

    Cheers!

    1
  8. 8

    Nice article, although I usually don’t see a great deal of functionality in HTML5 local storage capabilities I still think it’s a great feature for perhaps using it as a front-end session-like storage, which could be viable for interactive and javascript abundant apps.

    Good introduction on the topic, thanks for sharing.

    -1
  9. 9

    Another use case:

    http://www.rgraph.net/docs/annotating.html

    The annotation data survives refreshes by way of localStorage

    -3
  10. 10

    Rizqi Djamaluddin

    October 11, 2010 6:28 am

    That’s actually pretty sexy. But this means they’re basically just super-buffed mega-cookies, no? Maybe even a bit more difficult because we can’t interact with them directly in PHP or other server-side programming languages. I guess they’re perfect for storing stuff that can stay fully on the user end for most of the time.

    Oh, and for those questioning it, this is supported by Firefox 3.5 up, IE8 up, Safari 4, and Chrome 4 up, as far as I know.

    -4
  11. 11

    Great article, Christian. I think that the GEOPlanet demo you showed me last week (also in this article) was an excellent example of where local storage really comes in useful.

    The reality is that anyone wanting to use these technologies cross-browser *can* if they use the right tools. You can polyfill IE’s lack of local storage support in older browsers using something like YUI’s SWFStore (there are several alternatives) but most modern browsers do already support this.

    -1
  12. 12

    Got some ideas on local storage. Still things seems too complex to understand :( May be a simple example using localstorage will do great for newbies in html5

    -7
  13. 13

    localStorage === window.localStorage

    localStorage
    window.localStorage
    window['localStorage']

    They’re all the same – global variables are properties of the window object.

    7
  14. 14

    One thing I didn’t see mention of is browser support. Usually, when it comes to “HTML5″, IE is woefully far behind, but Web Storage is available in IE8. There’s also some fallback techniques you can use in non-native supporting browsers listed at http://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-browser-Polyfills

    Also, I believe Web Storage allows 5 megabytes per domain/origin, though I’m not sure if you get prompted to allow more if you exceed that or if it just fails silently.

    Another interesting difference between sessionStorage and localStorage is with sessionStorge, values are only visible within the window or tab that created them, whereas with localStorage, values are shared across every window or tab running at the same origin.

    0
  15. 15

    In Chrome you can delete web and extension Local Storage using an amazing extension named Click&Clean, you will find it at Chrome extensions gallery:
    https://chrome.google.com/extensions/detail/ghgabhipcejejjmhhchfonmamedcbeod

    Enjoy!

    3
  16. 16

    Good article and I think there are situations where this is useful. Keep in mind though, that users are increasingly accessing web applications from multiple devices. Since local storage is local to the device, users may encounter inconsistent experiences across devices.

    And, another dark side of local storage is that it is the enemy of data consistency. If your data definition changes, which is not uncommon in web applications, your local version will conflict with the server-side set. You will have to find a syncing solution then.

    Useful in the context of the examples given, less useful in other contexts.

    2
  17. 17

    Great writeup!

    Though I could see the data being stored locally as an issue as far as security is concerned.

    Thanks for sharing!

    0
  18. 18

    Very nice but the explanation of HTTP statelessness is not correct. The connection is stateless in itself and the opening or closing of an application has nothing to do with it. The connection is closed everytime the request is fulfilled. No popular website-hoster can manage 10.000′s of connection at the sametime and the host/servers would certainly fail.
    So an application needs to re-establish connection everytime it needs something done. That makes everthing so slow.

    -1
  19. 19

    Good article,

    Except the last part about ever cookie. The entire “Test” for the ever cookie is a pathetic joke. How can you test a pice of code in one browser and then make claims about every other browser out there and still openly say you never tested them.

    -1
  20. 20

    Thanks Christian. Good article. I already have a use for it ;)

    -3
  21. 21

    Is there any workarounds for using this in IE6 and IE7?

    -4
  22. 22

    For Chrome/Safari, you can also open the Dev Tools, go to the Storage tab and delete entries right there. (As Henrik pointed out)

    Of course, for all browsers, you just need to do this in a console:
    localStorage.clear()

    Also unfortunately, because of some strict Firefox security settings… people now have to wrap their feature test in a try/catch. Modernizr and Twitter.com have done this a bit ago:
    http://github.com/Modernizr/Modernizr/blob/1cecd6a/modernizr.js#L646-674

    4
  23. 23

    Nice one, got the thing which I wanted for my new directory project.

    -5
  24. 24

    How many browsers is the JSON object actually native in? I was under the impression it was just a Firefox thing.

    -4
  25. 25

    I see no one has mentioned Lawnchair, which is a client side JSON document store that makes use of local storage and greatly simplifies its implementation. It can also be extended via a series of adapters to support different types of storage.
    More info at:
    http://blog.westcoastlogic.com/lawnchair/
    and on Github:
    http://github.com/brianleroux/lawnchair

    0
  26. 26

    Thanks for the information which you have shared here and that is really useful for the website making purpose.

    -5
  27. 27

    Thanks for clearing this up, Paul!

    0
  28. 28
  29. 29

    Not to self promote too much (oops), but I helped my company (HUGE) make a small JS library which allows for local & session storage across all browsers – yes, including IE 6. Actually, IE 5.5 too, but who’s counting.

    It’s on github if any of you are interested:

    http://github.com/hugeinc/USTORE.js

    0
  30. 30

    I recently began working on a localStorage jQuery plugin that archiving form data while the user progresses through a long form. When the user submits the form, their data is cleared. My power kept going out over a 2-month period, and the most frustrating moment was when it happened while I was filling out a long web form. Naturally, I thought that a jQuery plugin could fix this (^_^)

    http://github.com/blackcoat/Savify

    -3
  31. 31

    The problem of web storage is that some people are still under the illusion that they have some sort of privacy (and probably still believe the world is flat).

    3
  32. 32

    if (localStorage) …
    throws an exception if localStorage is not in scope.
    if (window.localStorage) …
    does not.

    3
  33. 33

    Thanks for sharing.
    I just made a prototype for a new web-site with 6 menu-links for demonstration purpose, only using HTML and JavaScript AND no server…Showing, deleting, adding data locally on my pc using local storage. It works great…
    Thanks a lot – Again
    And as mentioned earlier it’s realy a super coockie+++ with a large bold C+.

    0
  34. 34

    Really nice sir.can you please put a tutorial to connect and access remote database in phonegap?

    0
  35. 35

    I like the way you presented the ideas and techniques. I’ll definitely look for more. Thanks, Christian.

    -1
  36. 36

    localStorage is the most compatible, even with limits on size usage on some browsers

    i created a really simple and efficient way of dealing with localStorage as database with all the whistles add/remove/update easy and quick

    can check in github https://github.com/joaoN1x/DBosta.js

    0
  37. 37

    Hi, great article!
    something is not really clear for me though… anyone can clarify?
    which is the difference bertween use the methods getItem, setItem, … or just do localstorage.myKey = ‘myValueString’ ?
    maybe it has a obvious answer, but don’t I can’t see it…
    thanks and congrats for this good stuff anyway!

    0
  38. 38

    In the actual specification, those two ways of getting and setting the values are exactly the same. You can also do localStorage["myKey"] = value or delete localStorage.myKey.

    0

↑ Back to top