Skip to content

๐Ÿ’พย ย Local Storage Manager

Submitted by Lukas Masuch

Summary

Read and write browser localStorage from Python with automatic JSON serialization.

Functions

local_storage_manager

Create a localStorage manager to read and write browser localStorage from Python.

This component provides a dict-like interface for managing browser localStorage. Unlike cookies (~4KB limit), localStorage can store ~5-10MB of data. Values are automatically serialized to/from JSON, so you can store dicts, lists, and primitives.

The returned LocalStorageManager implements Python's MutableMapping protocol, so you can use it like a dictionary:

  • manager["key"] - get a value (raises KeyError if not found)
  • manager.get("key", default) - get with a default value
  • manager["key"] = value - set a value (auto-serialized to JSON)
  • del manager["key"] - delete a key
  • "key" in manager - check if a key exists
  • len(manager) - count of stored items
  • dict(manager) - convert to a regular dict
  • manager.keys(), manager.values(), manager.items() - iterate
  • manager.clear() - remove all items for this app

For values that should auto-expire, use manager.set(key, value, expires_in=...) instead of dict-style assignment.

Data is automatically namespaced per-app (based on URL path) to prevent collisions between different Streamlit apps on the same domain.

Parameters:

Name Type Description Default
key str

A unique key for this component instance. Defaults to "local_storage_manager". Use different keys if you need multiple independent storage managers.

'local_storage_manager'

Returns:

Type Description
LocalStorageManager

A LocalStorageManager instance that provides dict-like access to localStorage.

Note
  • Call manager.ready() to check if data has synced from the browser
  • Use st.stop() on first load while waiting for sync
  • After setting/deleting values, call st.rerun() to see changes
  • Data persists across page refreshes and browser sessions
  • Expired values return None (via .get()) or raise KeyError

Example:

```python
manager = local_storage_manager()
if not manager.ready():
    st.stop()  # Wait for browser sync
settings = manager.get("settings", {"theme": "light"})
if st.button("Use dark theme"):
    settings["theme"] = "dark"
    manager["settings"] = settings
    st.rerun()
```

Example with expiration:

```python
from datetime import timedelta

manager = local_storage_manager()
if manager.ready():
    # Cache data for 1 hour
    manager.set("cache", expensive_data, expires_in=timedelta(hours=1))
```
Source code in src/streamlit_extras/local_storage_manager/__init__.py
@extra
def local_storage_manager(*, key: str = "local_storage_manager") -> LocalStorageManager:
    """Create a localStorage manager to read and write browser localStorage from Python.

    This component provides a dict-like interface for managing browser localStorage.
    Unlike cookies (~4KB limit), localStorage can store ~5-10MB of data. Values are
    automatically serialized to/from JSON, so you can store dicts, lists, and primitives.

    The returned ``LocalStorageManager`` implements Python's ``MutableMapping`` protocol,
    so you can use it like a dictionary:

    - ``manager["key"]`` - get a value (raises ``KeyError`` if not found)
    - ``manager.get("key", default)`` - get with a default value
    - ``manager["key"] = value`` - set a value (auto-serialized to JSON)
    - ``del manager["key"]`` - delete a key
    - ``"key" in manager`` - check if a key exists
    - ``len(manager)`` - count of stored items
    - ``dict(manager)`` - convert to a regular dict
    - ``manager.keys()``, ``manager.values()``, ``manager.items()`` - iterate
    - ``manager.clear()`` - remove all items for this app

    For values that should auto-expire, use ``manager.set(key, value, expires_in=...)``
    instead of dict-style assignment.

    Data is automatically namespaced per-app (based on URL path) to prevent
    collisions between different Streamlit apps on the same domain.

    Args:
        key: A unique key for this component instance. Defaults to "local_storage_manager".
            Use different keys if you need multiple independent storage managers.

    Returns:
        A LocalStorageManager instance that provides dict-like access to localStorage.

    Note:
        - Call ``manager.ready()`` to check if data has synced from the browser
        - Use ``st.stop()`` on first load while waiting for sync
        - After setting/deleting values, call ``st.rerun()`` to see changes
        - Data persists across page refreshes and browser sessions
        - Expired values return ``None`` (via ``.get()``) or raise ``KeyError``

    Example:

        ```python
        manager = local_storage_manager()
        if not manager.ready():
            st.stop()  # Wait for browser sync
        settings = manager.get("settings", {"theme": "light"})
        if st.button("Use dark theme"):
            settings["theme"] = "dark"
            manager["settings"] = settings
            st.rerun()
        ```

    Example with expiration:

        ```python
        from datetime import timedelta

        manager = local_storage_manager()
        if manager.ready():
            # Cache data for 1 hour
            manager.set("cache", expensive_data, expires_in=timedelta(hours=1))
        ```
    """
    return LocalStorageManager(key=key)

Import:

from streamlit_extras.local_storage_manager import local_storage_manager # (1)!
  1. You should add this to the top of your .py file ๐Ÿ› 

Examples

example

def example() -> None:
    """Example usage of the local_storage_manager component."""
    st.info(
        "localStorage can store ~5-10MB of data (vs ~4KB for cookies). "
        "Data persists across page refreshes and browser sessions."
    )

    manager = local_storage_manager(key="demo_local_storage")

    if not manager.ready():
        st.info("Syncing localStorage from browser. The app will be ready on the next rerun.")
        st.stop()

    st.subheader("Current localStorage")
    st.json(dict(manager))

    get_col, set_col, delete_col = st.columns(3)

    with get_col:
        st.markdown("**Get value**")
        get_key = st.text_input("Key", key="storage_get_key")
        if st.button("Read value", key="storage_get_button"):
            value = manager.get(get_key)
            if value is not None:
                st.write(value)
            else:
                st.write("*Not found*")

    with set_col:
        st.markdown("**Set value**")
        set_key = st.text_input("Key", key="storage_set_key")
        set_value = st.text_area("Value (JSON)", key="storage_set_value", height=100)
        if st.button("Write value", key="storage_set_button"):
            try:
                # Try to parse as JSON, otherwise store as string
                try:
                    parsed_value = json.loads(set_value)
                except json.JSONDecodeError:
                    parsed_value = set_value
                manager[set_key] = parsed_value
                st.rerun()
            except StreamlitAPIException as e:
                st.error(str(e))

    with delete_col:
        st.markdown("**Delete value**")
        delete_key = st.text_input("Key to delete", key="storage_delete_key")
        if st.button("Delete", key="storage_delete_button"):
            manager.delete(delete_key)
            st.rerun()
        if st.button("Clear all", key="storage_clear_button"):
            manager.clear()
            st.rerun()

    st.subheader("Basic usage")
    st.code(
        """
from datetime import timedelta

manager = local_storage_manager()

if not manager.ready():
    st.stop()  # Wait for browser sync

# Store any JSON-serializable data
settings = manager.get("settings", {"theme": "light", "lang": "en"})
st.write(f"Current theme: {settings['theme']}")

if st.button("Use dark theme"):
    settings["theme"] = "dark"
    manager["settings"] = settings
    st.rerun()

# Store with expiration (auto-expires after duration)
manager.set("session_cache", {"user": "alice"}, expires_in=timedelta(hours=1))

# Expired values return None via .get() or raise KeyError via []
cached = manager.get("session_cache")  # None if expired
""".strip(),
        language="python",
    )