> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/gradio-app/gradio/llms.txt
> Use this file to discover all available pages before exploring further.

# Managing state in Blocks

> Learn how to manage global state, session state, and browser state in your Gradio applications.

When building Gradio applications, you often need to persist data between interactions. This is called **state management**. Gradio provides three ways to manage state:

* **Global state**: Shared among all users, persists while the app is running
* **Session state**: Unique to each user, persists during their session
* **Browser state**: Stored in the browser's localStorage, persists even after page refresh

## Global state

Global state is straightforward: any variable created outside a function is shared between all users.

```python theme={null}
import gradio as gr

# This variable is shared between all users
visitor_count = 0

def increment_counter():
    global visitor_count
    visitor_count += 1
    return visitor_count

with gr.Blocks() as demo:
    number = gr.Textbox(label="Total Visitors", value="Counting...")
    demo.load(increment_counter, inputs=None, outputs=number)

demo.launch()
```

Every user who opens the app increases the visitor count. The value is shared globally across all sessions.

<Warning>
  **When not to use global state**: If you need values that are unique to each user (like chat history, user preferences, or individual progress), use session state or browser state instead.
</Warning>

## Session state

Session state allows you to persist data for each user individually. Data is maintained across multiple interactions but does not transfer between users. If a user refreshes the page, their session state is reset.

To use session state, follow these steps:

<Steps>
  <Step title="Create a gr.State object">
    Initialize it with a default value if needed. The value must be [deepcopy-able](https://docs.python.org/3/library/copy.html).

    ```python theme={null}
    cart = gr.State([])
    ```
  </Step>

  <Step title="Add State as input/output">
    Include the State object in your event listener's `inputs` and `outputs` as needed.

    ```python theme={null}
    button.click(fn=add_items, inputs=[items, cart], outputs=cart)
    ```
  </Step>

  <Step title="Use State in your function">
    Add the state variable to your function's parameters and return value.

    ```python theme={null}
    def add_items(new_items, previous_cart):
        cart = previous_cart + new_items
        return cart
    ```
  </Step>
</Steps>

### Example: Shopping cart

Here's a complete example of a simple shopping cart:

```python theme={null}
import gradio as gr

with gr.Blocks() as demo:
    cart = gr.State([])  # Initialize empty cart
    items_to_add = gr.CheckboxGroup(
        ["Cereal", "Milk", "Orange Juice", "Water"]
    )
    
    def add_items(new_items, previous_cart):
        cart = previous_cart + new_items
        return cart
    
    gr.Button("Add Items").click(
        add_items, 
        [items_to_add, cart], 
        cart
    )
    
    cart_size = gr.Number(label="Cart Size")
    cart.change(lambda cart: len(cart), cart, cart_size)

demo.launch()
```

<Note>
  Think of `gr.State` as an invisible Gradio component that can store any value. In this example, `cart` is not visible in the UI but is used for calculations.
</Note>

### Understanding State changes

The `.change()` listener for a State variable triggers after any event listener modifies the state:

* For sequences (`list`, `set`, `dict`): Triggers if any elements change
* For objects or primitives: Triggers if the **hash** of the value changes

<Warning>
  If you create a custom class and use it with `gr.State`, make sure the class includes a sensible `__hash__` implementation.
</Warning>

### State persistence

Session state values:

* Are cleared when the user refreshes the page
* Are stored in the app backend for 60 minutes after the user closes the tab
* Can have custom retention with the `delete_cache` parameter in `gr.Blocks`

```python theme={null}
with gr.Blocks(delete_cache=(3600, 3600)) as demo:
    # Delete cached state every hour (3600 seconds)
    pass
```

<Note>
  Learn more about `State` in the [State documentation](/components/state).
</Note>

## Working with non-deepcopyable objects

Some objects cannot be deepcopied (like threading locks or database connections). For these, use a global dictionary keyed by session hash:

```python theme={null}
import gradio as gr

class NonDeepCopyable:
    def __init__(self):
        from threading import Lock
        self.counter = 0
        self.lock = Lock()  # Lock objects cannot be deepcopied
    
    def increment(self):
        with self.lock:
            self.counter += 1
            return self.counter

# Global dictionary to store user-specific instances
instances = {}

def initialize_instance(request: gr.Request):
    instances[request.session_hash] = NonDeepCopyable()
    return "Session initialized!"

def cleanup_instance(request: gr.Request):
    if request.session_hash in instances:
        del instances[request.session_hash]

def increment_counter(request: gr.Request):
    if request.session_hash in instances:
        instance = instances[request.session_hash]
        return instance.increment()
    return "Error: Session not initialized"

with gr.Blocks() as demo:
    output = gr.Textbox(label="Status")
    counter = gr.Number(label="Counter Value")
    increment_btn = gr.Button("Increment Counter")
    
    increment_btn.click(increment_counter, inputs=None, outputs=counter)
    
    # Initialize instance when page loads
    demo.load(initialize_instance, inputs=None, outputs=output)
    
    # Clean up instance when page is closed/refreshed
    demo.unload(cleanup_instance)

demo.launch()
```

<Steps>
  <Step title="Create a global dictionary">
    Store one instance per user, keyed by their `session_hash`.
  </Step>

  <Step title="Initialize on load">
    Use `demo.load()` to create an instance when the user first visits.
  </Step>

  <Step title="Clean up on unload">
    Use `demo.unload()` to delete the instance when the user leaves.
  </Step>

  <Step title="Access via session_hash">
    Use `gr.Request` to get the user's `session_hash` in your functions.
  </Step>
</Steps>

## Browser state

Browser state persists data in the browser's localStorage, allowing it to survive page refreshes and even browser restarts. This is useful for storing user preferences, API keys, or settings.

<Steps>
  <Step title="Create a gr.BrowserState object">
    Optionally provide a default value and a storage key.

    ```python theme={null}
    username = gr.BrowserState("")
    ```
  </Step>

  <Step title="Use like gr.State">
    Add it to event listeners as inputs and outputs.

    ```python theme={null}
    button.click(save_username, inputs=username, outputs=status)
    ```
  </Step>
</Steps>

### Example: Persisting login credentials

```python theme={null}
import gradio as gr

def save_credentials(username, password):
    # In a real app, you would validate and hash the password
    return username, password, "Credentials saved!"

def load_status(username):
    if username:
        return f"Welcome back, {username}!"
    return "No saved credentials found."

with gr.Blocks() as demo:
    gr.Markdown("# Login Demo")
    
    # Store credentials in browser localStorage
    stored_username = gr.BrowserState("")
    stored_password = gr.BrowserState("")
    
    status = gr.Textbox(label="Status", interactive=False)
    
    with gr.Row():
        username_input = gr.Textbox(label="Username")
        password_input = gr.Textbox(label="Password", type="password")
    
    save_btn = gr.Button("Save Credentials")
    save_btn.click(
        save_credentials,
        inputs=[username_input, password_input],
        outputs=[stored_username, stored_password, status]
    )
    
    # Load saved credentials on page load
    demo.load(load_status, inputs=stored_username, outputs=status)

demo.launch()
```

### BrowserState persistence

<Note>
  **Important**: Data stored in `gr.BrowserState` does not persist if the Gradio app is restarted, unless you:

  1. Hardcode specific values for `storage_key` and `secret` in `gr.BrowserState`
  2. Restart the Gradio app on the same server name and port

  Only do this if you're running trusted Gradio apps, as different apps on the same domain could access the same localStorage data.
</Note>

## Choosing the right state type

| State Type | Shared Between Users | Persists on Refresh | Persists After Browser Close | Use Cases |
| - | - | - | - | - |
| **Global State** | ✅ Yes | ✅ Yes (until app restarts) | ✅ Yes (until app restarts) | Visitor counters, global settings, shared resources |
| **Session State** | ❌ No | ❌ No | ❌ No | Chat history, form data, user progress |
| **Browser State** | ❌ No | ✅ Yes | ✅ Yes | User preferences, API keys, login credentials |

## Next steps

Now that you understand state management, you can:

* Build [dynamic apps](/guides/dynamic-apps) with the render decorator
* Learn about [Blocks and event listeners](/guides/blocks-and-events)
* Explore [custom HTML components](/guides/custom-html) for advanced UIs


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.