Instantly share code, notes, and snippets.

Embed
What would you like to do?
a brief history of detecting local storage

A timeline of the last four years of detecting good old window.localStorage.


Jan Lenhart, bless his heart contributed the first patch for support:

October 2009: 5059daa

(typeof window.localStorage != 'undefined')

Simplicifations

November 2009: 15020e7

!!window.localStorage

If cookies disabled in FF, exception. Softer detect

December 2009: 1e0ba91

!!('localStorage' in window)

If DOM storage disabled in IE, window.localStorage is present but === null.

January 2010: d8947c9

(localStorage in window) && window[localStorage] !== null

FF with dom.storage.enabled = false throws exceptions

July 2010: ef2c47

try {
  return ('localStorage' in window) && window[localstorage] !== null;
} catch(e) {
  return false;
}

more shit because of FF exceptions

December 2010: c630c39

try {
    return !!localStorage.getItem;
} catch(e) {
    return false;
}

iOS private browsing fucks everyone!!!

October 2011: 5e2fa0e

try {
    return !!localStorage.getItem('getItem');
} catch(e) {
    return false;
}

stronger full capability test for localstorage with iOS private browsing protection

October 2011: a93625c

try {
    localStorage.setItem(mod, mod);
    localStorage.removeItem(mod);
    return true;
} catch(e) {
    return false;
}
@gr2m

This comment has been minimized.

Show comment
Hide comment
@gr2m

gr2m May 13, 2013

This is awesome, great summary! I think I went trough every single step myself :)

gr2m commented May 13, 2013

This is awesome, great summary! I think I went trough every single step myself :)

@djhopper01

This comment has been minimized.

Show comment
Hide comment
@djhopper01

djhopper01 May 13, 2013

This is great. Thank you for this.

djhopper01 commented May 13, 2013

This is great. Thank you for this.

@RodrigoAyala

This comment has been minimized.

Show comment
Hide comment
@RodrigoAyala

RodrigoAyala May 13, 2013

Great story. Code is always on evolution and improvement, and this is a great example. Thank you for this!

RodrigoAyala commented May 13, 2013

Great story. Code is always on evolution and improvement, and this is a great example. Thank you for this!

@pmuellr

This comment has been minimized.

Show comment
Hide comment
@pmuellr

pmuellr May 14, 2013

reminds me of IEFBR14 - see the note from John Pershing near the bottom of the article

pmuellr commented May 14, 2013

reminds me of IEFBR14 - see the note from John Pershing near the bottom of the article

@toobstar

This comment has been minimized.

Show comment
Hide comment
@toobstar

toobstar Jul 31, 2014

I have a IE9 VM running on mac & this isn't working. Setting & removing a value works OK but when you fetch it out you get a null. An improvement could be actually testing that you can retrieve value and it matches input.

toobstar commented Jul 31, 2014

I have a IE9 VM running on mac & this isn't working. Setting & removing a value works OK but when you fetch it out you get a null. An improvement could be actually testing that you can retrieve value and it matches input.

@DominoPivot

This comment has been minimized.

Show comment
Hide comment
@DominoPivot

DominoPivot Jan 13, 2016

Just in case anyone wonders even though it was an old comment, toobstar did something wrong because I tested IE9 on a VM and it works fine.

DominoPivot commented Jan 13, 2016

Just in case anyone wonders even though it was an old comment, toobstar did something wrong because I tested IE9 on a VM and it works fine.

@mpavel

This comment has been minimized.

Show comment
Hide comment
@mpavel

mpavel Apr 18, 2016

According to MDN (https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API), this is now best done with:

function storageAvailable(type) {
    try {
        var storage = window[type],
            x = '__storage_test__';
        storage.setItem(x, x);
        storage.removeItem(x);
        return true;
    }
    catch(e) {
        return false;
    }
}
if (storageAvailable('localStorage')) {
    // Yippee! We can use localStorage awesomeness
}
else {
    // Too bad, no localStorage for us
}

Lovely :)

mpavel commented Apr 18, 2016

According to MDN (https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API), this is now best done with:

function storageAvailable(type) {
    try {
        var storage = window[type],
            x = '__storage_test__';
        storage.setItem(x, x);
        storage.removeItem(x);
        return true;
    }
    catch(e) {
        return false;
    }
}
if (storageAvailable('localStorage')) {
    // Yippee! We can use localStorage awesomeness
}
else {
    // Too bad, no localStorage for us
}

Lovely :)

@Download

This comment has been minimized.

Show comment
Hide comment
@Download

Download Aug 27, 2016

Actually, I based that sample on the code and history presented in this very gist. So thank you all who contributed to it!

EDIT: I released that snippet as an NPM package so you don't have to copy-paste it... Also we can maintain it if stuff needs to change to it in the future,

https://www.npmjs.com/package/storage-available

Download commented Aug 27, 2016

Actually, I based that sample on the code and history presented in this very gist. So thank you all who contributed to it!

EDIT: I released that snippet as an NPM package so you don't have to copy-paste it... Also we can maintain it if stuff needs to change to it in the future,

https://www.npmjs.com/package/storage-available

@theUtherSide

This comment has been minimized.

Show comment
Hide comment
@theUtherSide

theUtherSide Jul 6, 2017

On a related, if you're looking to shim localStorage, there are great vanilla JS solutions:

Using cookies:
https://developer.mozilla.org/en-US/docs/Web/API/Storage/LocalStorage

Using in-memory:
https://gist.github.com/juliocesar/926500

theUtherSide commented Jul 6, 2017

On a related, if you're looking to shim localStorage, there are great vanilla JS solutions:

Using cookies:
https://developer.mozilla.org/en-US/docs/Web/API/Storage/LocalStorage

Using in-memory:
https://gist.github.com/juliocesar/926500

@tigr5

This comment has been minimized.

Show comment
Hide comment
@tigr5

tigr5 Dec 2, 2017

by way of interest, there's a slight difference in the current version of the code put in the comment above from mpavel (commented on Apr 18, 2016) regarding the Web Storage API 'Basic Concepts' page section entitled:
"Here is a function that detects whether localStorage is both supported and available:"
mpavel in April 2016 put this:

catch(e) { return false; }

today in December 2017 this snippet reads thus:
catch(e) { return e instanceof DOMException && ( // everything except Firefox e.code === 22 || // Firefox e.code === 1014 || // test name field too, because code might not be present // everything except Firefox e.name === 'QuotaExceededError' || // Firefox e.name === 'NS_ERROR_DOM_QUOTA_REACHED') && // acknowledge QuotaExceededError only if there's something already stored storage.length !== 0; }

tigr5 commented Dec 2, 2017

by way of interest, there's a slight difference in the current version of the code put in the comment above from mpavel (commented on Apr 18, 2016) regarding the Web Storage API 'Basic Concepts' page section entitled:
"Here is a function that detects whether localStorage is both supported and available:"
mpavel in April 2016 put this:

catch(e) { return false; }

today in December 2017 this snippet reads thus:
catch(e) { return e instanceof DOMException && ( // everything except Firefox e.code === 22 || // Firefox e.code === 1014 || // test name field too, because code might not be present // everything except Firefox e.name === 'QuotaExceededError' || // Firefox e.name === 'NS_ERROR_DOM_QUOTA_REACHED') && // acknowledge QuotaExceededError only if there's something already stored storage.length !== 0; }

@tobsn

This comment has been minimized.

Show comment
Hide comment
@tobsn

tobsn Dec 27, 2017

@tigr5

like this?

function storageAvailable(type) {
	try {
		var storage = window[type],
			x = '__storage_test__';
		storage.setItem(x, x);
		storage.removeItem(x);
		return true;
	}
	catch(e) {
		return e instanceof DOMException && (
			e.code === 22 || e.code === 1014 ||
			e.name === 'QuotaExceededError' ||
			e.name === 'NS_ERROR_DOM_QUOTA_REACHED'
		) && storage.length !== 0;
	}
}

tobsn commented Dec 27, 2017

@tigr5

like this?

function storageAvailable(type) {
	try {
		var storage = window[type],
			x = '__storage_test__';
		storage.setItem(x, x);
		storage.removeItem(x);
		return true;
	}
	catch(e) {
		return e instanceof DOMException && (
			e.code === 22 || e.code === 1014 ||
			e.name === 'QuotaExceededError' ||
			e.name === 'NS_ERROR_DOM_QUOTA_REACHED'
		) && storage.length !== 0;
	}
}
@Download

This comment has been minimized.

Show comment
Hide comment
@Download

Download Jul 26, 2018

The first lines inside the try block might already fail with an exception:

var storage = window[type], // could throw if storage is disabled (Firefox)
    x = '__storage_test__';
// storage might be null here.... (Internet Explorer)
storage.setItem(x, x);  // would throw if storage is null

Just read back in this gist. FF will in some cases throw an exception if you touch window.localStorage.... IE might give you a null object... So I don't see how the extra checks for the exception type help. In fact I think they actively break the code.

The way I approach it, if simply setting and removing an item from storage fails in any way then storage is not available.

I stand by my original version. I have given up on maintaining the MDN page. People keep coming by and 'fixing' the code sample. I have even seen people change it to samples that don't even run at all or always return true etc. My original sample works fine and does not need those extra lines imho. In fact the code becomes less reliable because of those extra lines.

Download commented Jul 26, 2018

The first lines inside the try block might already fail with an exception:

var storage = window[type], // could throw if storage is disabled (Firefox)
    x = '__storage_test__';
// storage might be null here.... (Internet Explorer)
storage.setItem(x, x);  // would throw if storage is null

Just read back in this gist. FF will in some cases throw an exception if you touch window.localStorage.... IE might give you a null object... So I don't see how the extra checks for the exception type help. In fact I think they actively break the code.

The way I approach it, if simply setting and removing an item from storage fails in any way then storage is not available.

I stand by my original version. I have given up on maintaining the MDN page. People keep coming by and 'fixing' the code sample. I have even seen people change it to samples that don't even run at all or always return true etc. My original sample works fine and does not need those extra lines imho. In fact the code becomes less reliable because of those extra lines.

@SebAlbert

This comment has been minimized.

Show comment
Hide comment
@SebAlbert

SebAlbert Aug 3, 2018

@Download The modified catch block will still return false except when the caught error happens to be "over quota error" (which is checked in four different ways), which means that the storage system is actually available, but just exhausted, and thus the (arguably) correct answer is still true

SebAlbert commented Aug 3, 2018

@Download The modified catch block will still return false except when the caught error happens to be "over quota error" (which is checked in four different ways), which means that the storage system is actually available, but just exhausted, and thus the (arguably) correct answer is still true

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment