How to run Streamlit in Python
Discover multiple ways to run Streamlit in Python. Get tips, see real-world examples, and learn how to debug common errors.

Streamlit offers a fast way to build and share data apps directly in Python. It turns data scripts into interactive web applications, which simplifies development and deployment for any project.
In this article, you'll explore techniques to run your Streamlit apps. You will find practical tips, see real world applications, and get essential advice to debug your projects effectively.
Running your first Streamlit app
import streamlit as st
st.title("My First Streamlit App")
st.write("Hello, world!")
# Run in terminal: streamlit run app.py--OUTPUT--You can now view your Streamlit app in your browser.
Local URL: http://localhost:8501
Network URL: http://192.168.1.5:8501
This script uses Streamlit functions like st.title() and st.write() to build the app's front end directly in Python. You don't need to write any separate HTML or JavaScript. The library handles the conversion of your Python code into web components.
The key step is the streamlit run app.py command. It starts a local web server that executes your script and makes the resulting app available in your browser. The server automatically watches for changes in your code and reloads the app whenever you save the file.
Basic Streamlit execution options
Beyond the basic run command, you can fine-tune your app's execution and appearance using server flags, command-line arguments, and specific configuration functions.
Customizing server settings with --server flags
import streamlit as st
st.title("Custom Server Settings")
st.write("This app runs on a custom port!")
# Run: streamlit run app.py --server.port 9000--OUTPUT--You can now view your Streamlit app in your browser.
Local URL: http://localhost:9000
Network URL: http://192.168.1.5:9000
You can easily tweak the Streamlit server using command-line flags. These flags, prefixed with --server, let you adjust settings like the port number when you launch the app. This is especially useful if the default port is already in use by another application.
--server.port: Changes the port your app runs on. The example uses9000instead of the default8501.--server.headless: Starts the server without automatically opening a browser tab, which is useful for automated environments.
Passing command-line arguments with --
import streamlit as st
import sys
st.title("Command Line Arguments")
if len(sys.argv) > 1:
st.write(f"Argument received: {sys.argv[1]}")
# Run: streamlit run app.py -- myargument--OUTPUT--You can now view your Streamlit app in your browser.
Local URL: http://localhost:8501
[In the app]: Argument received: myargument
You can pass custom arguments to your script by adding them after a -- separator in the run command. This tells Streamlit to forward anything that follows directly to your Python script instead of interpreting it as a server option.
- Your script can then access these values using Python's
sys.argv, which is a list containing all command-line arguments. - This is a powerful way to make your app's behavior dynamic—for example, you could load a different dataset or set a configuration flag right from the terminal.
Configuring page layout with set_page_config()
import streamlit as st
st.set_page_config(layout="wide", page_title="Wide App")
st.title("Wide Mode Streamlit App")
col1, col2 = st.columns(2)
col1.write("Left column")
col2.write("Right column")--OUTPUT--[A web app with the title "Wide Mode Streamlit App" and two columns spanning the full width of the browser]
The set_page_config() function is your main tool for adjusting the overall look and feel of your app. It’s important to call this function at the very beginning of your script, before any other Streamlit elements.
- The
layout="wide"argument makes your app's content span the full browser width, which is ideal for dashboards or side-by-side comparisons. - You can also set the
page_title, which customizes the text that appears in the browser tab, helping users identify your app.
Advanced Streamlit execution techniques
As your apps become more complex, you'll find advanced execution options essential for deployment, debugging, and managing multiple projects at once.
Running in headless mode for deployment
import streamlit as st
st.title("Headless Mode")
st.write("This app is designed to run on a server")
# Run: streamlit run app.py --server.headless true--OUTPUT--Streamlit app running in headless mode.
Local URL: http://localhost:8501
Network URL: http://192.168.1.5:8501
When you deploy your app to a server or a Docker container, you're often working in an environment that lacks a graphical interface. Using the --server.headless true flag is essential here. It instructs Streamlit to launch the server without attempting to open a browser window, which would fail in a server environment.
- This prevents unnecessary errors during automated deployments.
- Your app starts up quietly in the background, ready to serve users who access it via its URL.
Enabling development mode with --debug
import streamlit as st
st.title("Debug Mode")
st.write("Check the terminal for detailed logs")
# Run: streamlit run app.py --debug--OUTPUT--You can now view your Streamlit app in your browser.
Local URL: http://localhost:8501
[Terminal shows detailed debug logs during execution]
The --debug flag is your go-to tool for troubleshooting complex issues. It increases the verbosity of the server's output, giving you a much closer look at what's happening under the hood. You'll see this extra information appear directly in your terminal, not in the app itself.
- It reveals detailed logs of Streamlit's internal operations as your script executes.
- You get richer error messages that can help you pinpoint the root cause of a bug much faster than with standard output.
Running multiple apps simultaneously
# Terminal 1: streamlit run app1.py
# Terminal 2: streamlit run app2.py --server.port 8502
import streamlit as st
st.title("Multi-App Demo")
st.write("Run multiple Streamlit apps simultaneously")--OUTPUT--Terminal 1:
You can now view your Streamlit app in your browser.
Local URL: http://localhost:8501
Terminal 2:
You can now view your Streamlit app in your browser.
Local URL: http://localhost:8502
You can easily run several Streamlit apps at once, which is great for comparing different versions or working on multiple projects. Each app simply needs its own terminal session to launch.
- The first app can run on the default port, typically
8501. - For every subsequent app, you must assign a unique port using the
--server.portflag to prevent conflicts. For instance, you can run a second app on port8502.
Move faster with Replit
Replit is an AI-powered development platform that transforms natural language into working applications. You can describe what you want to build, and Replit Agent creates it—complete with databases, APIs, and deployment.
It can take the Streamlit execution techniques from this article and turn them into production-ready tools:
- Build a dynamic data dashboard that loads a specific dataset based on a command-line argument.
- Deploy a headless monitoring app that runs on a custom port to track server metrics in the background.
- Create a financial modeling tool that uses a wide layout to display complex charts and data tables side-by-side.
Describe your app idea, and Replit Agent will write the code, test it, and fix issues automatically, all within your browser.
Common errors and challenges
Even with its simplicity, you might encounter a few common roadblocks when running your Streamlit apps.
- One of the most frequent errors involves the
st.set_page_config()function. It must be the very first Streamlit command in your script, otherwise it will raise an error. If you call it after other elements likest.title()orst.write(), it's too late—the page configuration is already set. - Caching can also be a source of confusion, especially with the evolution from the legacy
st.cacheto newer functions. For most use cases involving data, like loading a large CSV or fetching API results, you should usest.cache_data. Using the wrong caching decorator can lead to performance bottlenecks or your app showing stale information. - Managing widget state is a classic challenge because Streamlit reruns your entire script with every user interaction. If your app isn't remembering user input from a text box or a slider, you likely need to use
st.session_state. This dictionary-like object lets you store values across reruns, ensuring your app behaves as expected.
Fixing order of st.set_page_config() calls
The st.set_page_config() function is strict about its placement—it must be the first Streamlit command you call. Placing it after elements like st.title() will trigger an error because the page configuration is already locked in. See this common mistake below.
import streamlit as st
st.title("My Streamlit App")
st.set_page_config(page_title="My App", layout="wide")
st.write("This page configuration won't work correctly")
Calling st.title() draws an element to the page, which finalizes the default layout settings. As a result, the subsequent call to st.set_page_config() is too late and will raise an error. See the correct implementation below.
import streamlit as st
# Page config must be the first Streamlit command
st.set_page_config(page_title="My App", layout="wide")
st.title("My Streamlit App")
st.write("This page configuration works correctly")
The fix is simple: always place st.set_page_config() at the very top of your script, before any other Streamlit functions. As soon as you call a function that draws something to the screen, like st.title(), Streamlit locks in the page's layout. Calling the configuration function after that point is too late. This is a common pitfall, so it's good practice to make it the first line of code in your Streamlit apps.
Troubleshooting st.cache_data vs st.cache issues
Using the wrong caching decorator is a frequent source of issues. The legacy st.cache is deprecated, and modern Streamlit apps should use st.cache_data for data-related functions to ensure performance and prevent errors. The following code illustrates this common pitfall.
import streamlit as st
import pandas as pd
@st.cache # This decorator is deprecated
def load_data():
df = pd.DataFrame({'x': range(10), 'y': range(10)})
return df
data = load_data()
st.line_chart(data)
The st.cache decorator isn't optimized for serializing data objects like DataFrames. This can cause your app to re-run the function unnecessarily, slowing it down. The corrected implementation below shows the proper approach for modern apps.
import streamlit as st
import pandas as pd
@st.cache_data # Use the newer cache_data decorator instead
def load_data():
df = pd.DataFrame({'x': range(10), 'y': range(10)})
return df
data = load_data()
st.line_chart(data)
The fix is to replace the deprecated st.cache with st.cache_data. This newer decorator is optimized for serializing data objects like pandas DataFrames, ensuring they're cached correctly. This prevents the function from re-running on every user interaction, which is crucial for performance when your app loads large datasets or fetches API results. Your app will run faster and won't display stale data.
Handling widget state persistence with st.session_state
Because Streamlit reruns your script with every user interaction, local variables reset. This makes it impossible to track state—like a button click counter—across reruns. The code below demonstrates this problem, where the counter never increments past one.
import streamlit as st
counter = 0
if st.button("Increment"):
counter += 1
st.write(f"Counter value: {counter}") # Will always show 0 or 1
The counter variable is reset to 0 on every script rerun. When you click the button, it briefly becomes 1, but this value is lost immediately on the next rerun. See the correct implementation below.
import streamlit as st
if 'counter' not in st.session_state:
st.session_state.counter = 0
if st.button("Increment"):
st.session_state.counter += 1
st.write(f"Counter value: {st.session_state.counter}")
The solution is to use st.session_state, a dictionary-like object that holds data across reruns. You first check if a key, like 'counter', exists in st.session_state. If it doesn't, you initialize it. This step runs only once. From then on, you can update st.session_state.counter directly. This ensures the value isn't lost, allowing your app to remember user inputs or track events like button clicks correctly.
Real-world applications
Beyond just running scripts, these techniques let you build practical tools like data dashboards and interactive machine learning models.
Creating a simple data visualization dashboard
You can quickly build a dashboard by loading your data into a pandas DataFrame and then using Streamlit functions like st.dataframe() and st.line_chart() to visualize it.
import streamlit as st
import pandas as pd
import numpy as np
st.title("Sales Dashboard")
data = pd.DataFrame({
'Month': ['Jan', 'Feb', 'Mar', 'Apr', 'May'],
'Sales': [15000, 18000, 22000, 19000, 25000]
})
st.dataframe(data)
st.line_chart(data.set_index('Month'))
This script builds a simple sales dashboard. It first creates a pd.DataFrame to hold monthly sales figures. The st.dataframe(data) function then displays this data as a clean, sortable table directly in the app.
To visualize the trend, st.line_chart() plots the sales data. The data.set_index('Month') part is key, as it tells the chart to use the months for the horizontal axis. This combination of a raw data table and a line chart gives you a quick, interactive overview of performance.
Building an interactive machine learning model with st.slider()
You can use widgets like st.slider() to build interactive machine learning apps where users can tune model parameters and instantly see the impact on accuracy.
import streamlit as st
import pandas as pd
from sklearn.datasets import load_iris
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
iris = load_iris()
X, y = iris.data, iris.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
n_estimators = st.slider("Number of trees", 1, 100, 10)
model = RandomForestClassifier(n_estimators=n_estimators)
model.fit(X_train, y_train)
st.write(f"Model accuracy: {model.score(X_test, y_test):.2f}")
This script integrates a scikit-learn model into a Streamlit app. It begins by loading the classic Iris dataset and splitting it into training and testing portions using train_test_split(). This prepares the data for building a predictive model.
The interactive part is the st.slider(), which creates a widget to capture a user's selection for the number of trees in a RandomForestClassifier. The script then trains the model with that value and displays its final accuracy score on the test data, showing a complete workflow from data prep to evaluation.
Get started with Replit
Turn what you've learned into a real tool. Describe your idea to Replit Agent, like “build a dashboard that loads a CSV from a command-line argument” or “create a headless monitoring app on a custom port.”
It will write the code, test for errors, and deploy your app automatically. Start building with Replit.
Create and deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.
Create & deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.

.png)
.png)
.png)