Local Storage — co to jest i jak używać localStorage w JavaScript
Local storage co to: pamięć przeglądarki typu klucz–wartość. Metody setItem i getItem, zapis obiektów w JSON, limity, bezpieczeństwo i porównanie z cookies.

W skrócie
- localStorage to magazyn klucz–wartość w przeglądarce, przypisany do jednego originu (protokół + domena + port); dane nie wygasają same.
- Podstawowe metody: setItem, getItem, removeItem, clear, key i właściwość length.
- Przechowuje wyłącznie tekst — obiekty i tablice zapisuj przez JSON.stringify, a odczytuj przez JSON.parse.
- Limit to zwykle około 5 MB na origin; po jego przekroczeniu zapis rzuca wyjątek QuotaExceededError.
- Nie trzymaj w localStorage haseł ani tokenów sesji — każdy skrypt na stronie (także wstrzyknięty przez XSS) może je odczytać.
Spis treści
Local Storage (w kodzie: localStorage) to pamięć przeglądarki, w której strona może zapisać dane w postaci par klucz–wartość. Dane są przypisane do konkretnej witryny, nie wygasają same i przetrwają zamknięcie karty, przeglądarki, a nawet restart komputera. Obsługują go wszystkie współczesne przeglądarki.
Typowe zastosowania to zapamiętanie motywu (jasny/ciemny), języka, zawartości koszyka w prostym sklepie czy szkicu formularza. Poniżej znajdziesz pełne API z przykładami, ograniczenia, zasady bezpieczeństwa i porównanie z sessionStorage, cookies oraz IndexedDB.
Local storage — co to jest i jak działa
localStorage jest częścią standardu Web Storage (dziś opisanego w specyfikacji HTML). Każda strona dostaje własny, odizolowany magazyn przypisany do originu, czyli kombinacji:
- protokołu (
httpsvshttp), - domeny (
sklep.example.comto inny origin niżexample.com), - portu (
localhost:3000ilocalhost:5173mają osobne magazyny).
Strona nie ma dostępu do localStorage innych stron, a serwer nie widzi tych danych — w odróżnieniu od cookies nie są one dołączane do żądań HTTP. Jeśli chcesz coś wysłać na serwer, robisz to samodzielnie, np. przez fetch() (więcej o komunikacji z backendem w poradniku o REST API).
Trzy cechy, o których trzeba pamiętać od początku:
- Przechowuje tylko ciągi znaków. Liczba
5zapisze się jako"5", a obiekt bez konwersji jako bezużyteczne"[object Object]". - Działa synchronicznie — każde wywołanie blokuje główny wątek, dopóki przeglądarka nie odczyta lub nie zapisze danych.
- Nie ma daty ważności. Dane znikają dopiero, gdy usunie je kod strony, użytkownik albo przeglądarka (np. przy braku miejsca na dysku lub po zamknięciu okna prywatnego).
Metody localStorage: setItem, getItem, removeItem, clear
Obiekt localStorage implementuje interfejs Storage. Oto wszystkie jego metody:
// zapis wartości pod kluczem
localStorage.setItem('motyw', 'ciemny');
// odczyt — zwraca string albo null, gdy klucza nie ma
const motyw = localStorage.getItem('motyw'); // "ciemny"
// usunięcie jednego klucza
localStorage.removeItem('motyw');
// usunięcie wszystkich danych tej strony
localStorage.clear();
// liczba zapisanych kluczy i nazwa klucza o danym indeksie
console.log(localStorage.length);
console.log(localStorage.key(0));
Można też używać składni obiektowej (localStorage.motyw = 'ciemny'), ale nie jest to zalecane. Klucz o nazwie takiej jak wbudowana metoda (np. key czy length) nie zadziała poprawnie, a getItem jasno zwraca null dla brakującego klucza, zamiast undefined.
Żeby przejrzeć wszystkie zapisane pary, iteruj po indeksach:
for (let i = 0; i < localStorage.length; i++) {
const klucz = localStorage.key(i);
console.log(klucz, localStorage.getItem(klucz));
}
Zapisywanie obiektów i tablic przez JSON
Ponieważ localStorage przyjmuje tylko tekst, dane złożone serializuje się do JSON:
const koszyk = [
{ id: 17, nazwa: 'Kabel HDMI', ilosc: 2 },
{ id: 42, nazwa: 'Router', ilosc: 1 }
];
localStorage.setItem('koszyk', JSON.stringify(koszyk));
const zapisany = JSON.parse(localStorage.getItem('koszyk') ?? '[]');
console.log(zapisany[0].nazwa); // "Kabel HDMI"
Operator ?? '[]' zabezpiecza przed sytuacją, w której klucza nie ma — JSON.parse(null) zwróci null, a próba odczytu zapisany[0] zakończy się błędem. Pamiętaj też, że JSON nie przenosi wszystkiego: obiekty Date zamienią się w tekst, a Map, Set i funkcje zostaną utracone.
W praktyce warto owinąć localStorage prostymi funkcjami pomocniczymi, które obsłużą błędy parsowania i brak dostępu do magazynu:
function zapisz(klucz, wartosc) {
try {
localStorage.setItem(klucz, JSON.stringify(wartosc));
return true;
} catch (e) {
// QuotaExceededError, zablokowany magazyn itp.
console.warn('Nie udało się zapisać', klucz, e);
return false;
}
}
function odczytaj(klucz, domyslna = null) {
try {
const surowe = localStorage.getItem(klucz);
return surowe === null ? domyslna : JSON.parse(surowe);
} catch {
return domyslna;
}
}
Blok try/catch nie jest przesadną ostrożnością. Dostęp do localStorage może rzucić wyjątek, gdy użytkownik zablokował dane witryn w ustawieniach, gdy strona działa w ramce z restrykcjami albo gdy skończy się limit miejsca.
Dane z datą ważności i synchronizacja między kartami
localStorage nie ma wbudowanego wygasania, ale łatwo je dodać, zapisując razem z wartością znacznik czasu:
function zapiszNa(klucz, wartosc, minuty) {
const wpis = { wartosc, wygasa: Date.now() + minuty * 60_000 };
localStorage.setItem(klucz, JSON.stringify(wpis));
}
function odczytajWazne(klucz) {
const wpis = JSON.parse(localStorage.getItem(klucz) ?? 'null');
if (!wpis) return null;
if (Date.now() > wpis.wygasa) {
localStorage.removeItem(klucz);
return null;
}
return wpis.wartosc;
}
Gdy jedna karta zmieni dane, pozostałe karty tej samej strony dostają zdarzenie storage. Pozwala to np. wylogować użytkownika we wszystkich kartach naraz albo odświeżyć licznik koszyka:
window.addEventListener('storage', (event) => {
if (event.key === 'koszyk') {
const nowy = JSON.parse(event.newValue ?? '[]');
odswiezLicznik(nowy.length);
}
});
Zdarzenie nie jest wywoływane w karcie, która dokonała zmiany — tylko w pozostałych. Do bardziej rozbudowanej komunikacji między kartami lepiej nadaje się BroadcastChannel.
Limity i ograniczenia localStorage
| Cecha | Jak to wygląda w praktyce |
|---|---|
| Pojemność | Zwykle ok. 5 MB na origin (Chrome, Edge, Firefox, Safari); standard nie ustala dokładnej wartości |
| Typ danych | Tylko string; resztę trzeba serializować |
| Wydajność | Operacje synchroniczne; duże zapisy mogą przycinać interfejs |
| Dostępność | Tylko w głównym wątku — nie ma go w Web Workerach ani Service Workerach |
| Tryb prywatny | Działa, ale dane są kasowane po zamknięciu okien prywatnych |
| Safari | Mechanizm ITP może usunąć dane zapisane skryptem, jeśli użytkownik nie odwiedzał strony przez 7 dni |
Po przekroczeniu limitu setItem rzuca DOMException o nazwie QuotaExceededError. Jeśli potrzebujesz więcej miejsca albo przechowujesz pliki, obrazy lub tysiące rekordów, sięgnij po IndexedDB — asynchroniczną bazę w przeglądarce z limitami liczonymi w setkach megabajtów lub więcej, zależnie od wolnego miejsca na dysku.
Bezpieczeństwo: czego nie zapisywać w localStorage
localStorage nie jest szyfrowany i nie ma żadnej kontroli dostępu poza izolacją originu. Każdy skrypt uruchomiony na stronie — Twój, z biblioteki zewnętrznej, z widżetu reklamowego albo wstrzyknięty przez atakującego — może odczytać cały magazyn jedną linijką kodu.
Uwaga: Nie przechowuj w localStorage haseł, danych kart płatniczych, danych osobowych ani tokenów uwierzytelniających (np. JWT z długim czasem życia). Jedna podatność Cross-Site Scripting wystarczy, żeby atakujący wysłał je na swój serwer i przejął sesję użytkownika.
Tokeny sesyjne bezpieczniej trzymać w ciasteczkach z flagami HttpOnly, Secure i SameSite — HttpOnly sprawia, że JavaScript w ogóle ich nie widzi. Trzeba wtedy zadbać o ochronę przed atakami CSRF, ale to problem łatwiejszy do opanowania niż kradzież tokenu. Więcej o skutkach przejęcia sesji przeczytasz w tekście o session hijacking.
Druga sprawa to prywatność. Przepisy o przechowywaniu informacji na urządzeniu użytkownika dotyczą nie tylko cookies, ale każdego takiego mechanizmu. Jeśli zapisujesz w localStorage identyfikatory do analityki lub marketingu, potrzebujesz zgody tak samo jak przy ciasteczkach — patrz poradnik o Google Consent Mode v2. Dane niezbędne do działania strony (np. zawartość koszyka, wybrany motyw) zwykle zgody nie wymagają.
localStorage, sessionStorage, cookies czy IndexedDB?
| localStorage | sessionStorage | Cookies | IndexedDB | |
|---|---|---|---|---|
| Czas życia | Do usunięcia | Do zamknięcia karty | Do daty wygaśnięcia lub końca sesji | Do usunięcia |
| Zasięg | Wszystkie karty originu | Jedna karta | Domena i ścieżka | Wszystkie karty originu |
| Pojemność | ok. 5 MB | ok. 5 MB | ok. 4 KB na ciasteczko | Setki MB i więcej |
| Wysyłane do serwera | Nie | Nie | Tak, z każdym żądaniem | Nie |
| API | Synchroniczne, proste | Synchroniczne, proste | document.cookie lub nagłówki HTTP | Asynchroniczne, złożone |
| Dobre do | Preferencji, cache, szkiców | Stanu jednego formularza lub kreatora | Sesji i uwierzytelniania | Dużych zbiorów danych, trybu offline |
Prosta reguła: preferencje i niewielkie dane interfejsu — localStorage; stan tylko na czas wizyty w jednej karcie — sessionStorage; uwierzytelnianie — ciasteczka HttpOnly; dużo danych lub aplikacja offline — IndexedDB (najlepiej przez bibliotekę typu idb lub Dexie).
Jak podejrzeć i wyczyścić localStorage w przeglądarce
Podczas pracy nad stroną najwygodniej korzystać z narzędzi deweloperskich:
- Chrome, Edge, Opera: naciśnij
F12→ karta Application → w lewym panelu Storage → Local storage → wybierz adres strony. Wpisy możesz edytować dwuklikiem, a ikoną z przekreślonym kółkiem wyczyścić wszystko. - Firefox:
F12→ karta Storage → Local Storage. - Safari: włącz menu Programowanie w ustawieniach zaawansowanych, potem Programowanie → Pokaż inspektora www → karta Storage.
Z konsoli możesz też wyświetlić całą zawartość jednym poleceniem:
console.table(Object.entries(localStorage));
Zwykły użytkownik, który chce usunąć dane jednej strony, zrobi to w ustawieniach przeglądarki: w Chrome Ustawienia → Prywatność i bezpieczeństwo → Ustawienia witryn → Wyświetl uprawnienia i dane przechowywane na stronach, a następnie usuwa dane wybranej witryny. Wyczyszczenie „plików cookie i danych witryn” w historii usuwa także localStorage.
Dobre praktyki na koniec
- Nadawaj kluczom prefiks aplikacji (np.
mojaapp:motyw), żeby uniknąć kolizji ze skryptami zewnętrznymi na tej samej domenie. - Zapisuj numer wersji struktury danych — po zmianie formatu łatwo wykryjesz stare wpisy i je zmigrujesz.
- Zawsze obsługuj brak danych i wyjątki; aplikacja musi działać także z pustym magazynem.
- Traktuj localStorage jak cache, a nie źródło prawdy: wszystko, co ważne, powinno być też na serwerze.
- Nie zapisuj dużych obiektów przy każdym naciśnięciu klawisza — użyj debounce, bo zapis jest synchroniczny.
Najczęściej zadawane pytania
Local storage co to jest?
To wbudowany w przeglądarkę mechanizm Web Storage, który pozwala stronie zapisać pary klucz–wartość na komputerze użytkownika. Dane zostają po zamknięciu karty i przeglądarki, dopóki strona lub użytkownik ich nie usunie.
Ile danych zmieści localStorage?
W popularnych przeglądarkach około 5 MB na origin, czyli na kombinację protokołu, domeny i portu. Limit nie jest ustalony w standardzie, więc nie projektuj aplikacji na styk.
Czym różni się localStorage od sessionStorage?
API jest identyczne, ale sessionStorage żyje tylko w obrębie jednej karty i znika po jej zamknięciu. localStorage jest wspólny dla wszystkich kart tej samej strony i przetrwa restart przeglądarki.
Czy localStorage jest bezpieczny?
Nie nadaje się do danych wrażliwych. Nie jest szyfrowany, a dostęp ma każdy skrypt JavaScript działający na stronie, więc atak XSS pozwala go w całości odczytać.
Jak wyczyścić localStorage w przeglądarce?
W Chrome i Edge otwórz narzędzia deweloperskie (F12), kartę Application, sekcję Local storage i usuń wpisy. Możesz też usunąć dane witryny w ustawieniach prywatności przeglądarki albo wywołać localStorage.clear() w konsoli.
Autor
Założyciel i redaktor XAD.pl. Pisze o sieciach, bezpieczeństwie IT, administracji systemami Windows i Linux oraz o sprzęcie, który sprawia ludziom problemy na co dzień.


