Show API reference for

ASGI-compatible Streamlit application.

Warning

This feature is experimental and may change or be removed in future versions without warning. Use at your own risk.

Warning

Hosting multiple App instances with different script_path values in the same process is not supported. The first App constructed in a process pins the script-level config directory (via the process-global config._main_script_path), and subsequent App instances will resolve relative script_path values against that first directory rather than the current working directory.

This class provides a way to configure and run Streamlit applications with custom routes, middleware, lifespan hooks, and exception handlers.

Class description[source]

st.App(script_path, *, secrets=None, lifespan=None, routes=None, middleware=None, on_script_error=None, exception_handlers=None, debug=False)

Methods

Get a lifespan context manager for mounting on external ASGI frameworks.

Attributes

script_path (str | Path)

Path to the main Streamlit script. Can be absolute or relative. Relative paths are resolved based on context: when started via streamlit run, they resolve relative to the main script; when started directly via uvicorn or another ASGI server, they resolve relative to the current working directory.

secrets (Mapping[str, SecretsValue] | None)

A dictionary of secrets to make available via st.secrets. Supported value types are: str, int, float, bool, and nested dict. When provided, these secrets are shallow-merged with file-based secrets (programmatic secrets override file-based secrets at the top level). Unsupported types raise TypeError at construction.

lifespan (Callable[[App], AbstractAsyncContextManager[dict[str, Any] | None]] | None)

Async context manager for startup/shutdown logic. The context manager receives the App instance and can yield a dictionary of state that will be accessible via app.state.

routes (Sequence[BaseRoute] | None)

Additional routes to mount alongside Streamlit. User routes are checked against reserved Streamlit routes and will raise ValueError if they conflict.

middleware (Sequence[Middleware] | None)

Middleware stack to apply to all requests. User middleware runs before Streamlit's internal middleware.

on_script_error (Callable[[Exception], bool | None] | None)

Callback invoked when an uncaught exception occurs during script execution. The callback receives the exception and can optionally return True to suppress the default exception display in the UI, allowing custom error UI to be shown instead. Returns False or None to show the exception normally. Useful for integrating with error monitoring services like Sentry.

The handler is invoked for:

  • Uncaught exceptions in the full app script
  • Exceptions in widget callbacks (on_change, on_click, etc.)

The handler is NOT invoked for:

  • st.stop() / st.rerun() (control flow, not errors)
  • Syntax/compile errors in the script
  • KeyboardInterrupt / SystemExit

exception_handlers (Mapping[Any, ExceptionHandler] | None)

A mapping of either integer status codes, or exception class types onto callables which handle the exceptions. Exception handler callables should be of the form handler(request, exc) -> response and may be either standard functions, or async functions. This is only for exception handling on the network layer. Use on_script_error for customized handling of uncaught exceptions from the app script.

debug (bool)

Enable debug mode for the underlying Starlette application.

Application state, populated by lifespan context manager.

Examples

Basic usage:

from streamlit.web.server.starlette import App
app = App("main.py")

With lifespan hooks:

from contextlib import asynccontextmanager
from streamlit.web.server.starlette import App

@asynccontextmanager
async def lifespan(app):
    print("Starting up...")
    yield {"model": "loaded"}
    print("Shutting down...")

app = App("main.py", lifespan=lifespan)

With custom routes:

from starlette.routing import Route
from starlette.responses import JSONResponse
from streamlit.web.server.starlette import App

async def health(request):
    return JSONResponse({"status": "ok"})

app = App("main.py", routes=[Route("/health", health)])

With programmatic secrets:

import os
from streamlit.web.server.starlette import App

app = App(
    "main.py",
    secrets={
        "database": {
            "host": os.environ["DB_HOST"],
            "password": os.environ["DB_PASSWORD"],
        }
    },
)

With error monitoring (Sentry):

import sentry_sdk
from streamlit.web.server.starlette import App

sentry_sdk.init(dsn="...")

def log_to_sentry(exc):
    sentry_sdk.capture_exception(exc)
    return None  # Show default exception display

app = App("main.py", on_script_error=log_to_sentry)

With custom error UI:

import streamlit as st
from streamlit.web.server.starlette import App

def custom_error_handler(exc):
    st.error("Something went wrong!")
    return True  # Suppress default exception display

app = App("main.py", on_script_error=custom_error_handler)
forum

Still have questions?

Our forums are full of helpful information and Streamlit experts.