In this tutorial, you’ll learn how to build web apps with Streamlit in Python, with an example.
Web-based applications are a great way to display and share data insights. But they often require front-end experience, which takes much effort and time to learn and implement. Using Streamlit, we can easily build beautiful and interactive web apps within minutes, all in Python.
Following this quick Streamlit Python tutorial, you’ll learn:
- What is Streamlit
- How to add text, media, sidebar
- How to display data
- How to add data visualizations
- How to create interactive widgets
- How to build forms
- Lots more!
So if you want to build your first interactive web app in Python Streamlit, this tutorial will demonstrate a real example project in detail.
Let’s dive in!
Further learning: if you want to learn about Streamlit’s alternative – Dash, please read our article How to create Python Interactive Dashboards with Plotly Dash: 6 steps Tutorial. Dash is also a Python library that enables us to create interactive web apps. Compared to Streamlit, Dash is more comprehensive and customizable but with a steeper learning curve at the beginning.
To follow this Streamlit Python tutorial, you need to know Python, including basic knowledge of pandas
. If you need help, please check out the below resources:
- Python basics: FREE Python crash course
- Python
pandas
: Python for Data Analysis with projects course. This course teachespandas
, which is necessary to transform your dataset into an app, and much more!
What is Streamlit?
Streamlit is an open-source (free) Python library, which provides a fast way to build interactive web apps. It is a relatively new package launched in 2019 but has been growing tremendously. It is designed and built especially for machine learning engineers or other data science professionals. Once you are done with your analysis in Python, you can quickly turn those scripts into web apps/tools to share with others.
As long as you can code in Python, it should be straightforward for you to write Streamlit apps. Imagine the app as the canvas. We can write Python scripts from top to bottom to add all kinds of elements, including text, charts, widgets, tables, etc.
In this tutorial, we’ll build an example app with Streamlit in Python. You’ll be able to use the common elements and commands from Streamlit and expand to others on your own!
How to set up the environment?
This Streamlit Python tutorial will use the PyCharm Editor – Community Edition. It’s free and has many useful features for writing Python code. But you can stick to your favorite editor.
We understand that many of you use the Jupyter environment for data analysis. But we should use one of the Python editors when developing web applications. We want to focus on building and running the apps as a whole script. Plus, the editors often offer more features such as syntax check, which help us to code easier.
It’s also necessary to use the pip install streamlit
command in your terminal to install Streamlit before using it. After the installation, it is optional to test using the command streamlit hello
. An app should open in the web browser if the installation works.
Now we can start writing code to build our first Streamlit app.
Write a basic Streamlit app and Run it
After creating a Python script and naming it streamlit_example.py
, we can start writing our Streamlit app.
We import the below libraries. Note that we also put the complete script for the app at the end of the tutorial.
import streamlit as st
import pandas as pd
import plotly.express as px
Then, let’s also add another line of code:
'# Avocado Prices dashboard'
This is simply a string with the Markdown format. But we already have a basic Streamlit app!
Let’s run and see it.
Once you’ve entered and run the below command in the terminal, you should see your first app opening in your web browser.
streamlit run streamlit_example.py
It should look like this – a heading level 1 ‘Avocado Prices dashboard’.

This is the magic feature of Streamlit. Every time we put a literal value, or a variable on its own line, Streamlit automatically writes it to our apps. That’s why we can display the Markdown string '# Avocado Prices dashboard'
without using any Streamlit commands.
Alternatively, we can use the below code. It will show the same results. Since the Streamlit magic is using the function st.write
to display the elements behind the scenes.
st.write('# Avocado Prices dashboard')
And there’s even more st.write
can do. According to Streamlit, st.write
is the ‘Swiss Army knife’. It can write various things to the app for us. Besides the Markdown string, st.write
(or the magic feature) can also display other arguments such as DataFrame, function, and chart.
In short, the magic feature or st.write
can display almost anything easily! They will inspect the objects we throw in and try to show them most appropriately.
So you might be wondering, since st.write
can display almost everything, why do I need other functions?
Due to its generic nature, st.write
is limited in customizations and further modifications. So I would recommend trying st.write
when you are not sure. Then if you’ve found that you need specific customizations, you can use other functions we’ll cover below.
All right! Now you’ve learned the most basic and powerful concept in Streamlit: the magic and st.write
. Let’s move on to more details.
Display and format text
In the previous section, we displayed a Markdown string using the magic or the st.write
command. There are also dedicated functions for text.
Let’s add some of them to our app using the below code:
st.title
: display text in title formatting. We comment it out next to the previous command since it returns the same level 1 heading.st.markdown
: display Markdown-formatted string. We ask it to display a description and the data source with a hyperlink. Please ensure there are two spaces after:avocado:
to break onto the next line. Again, we could put the argument directly and use the magic to display it as well.st.header
: display text in header formatting. Each document should only have onest.title
, and multiplest.header
s. Sincest.header
creates headers that are lower levels thanst.title
.
st.write('# Avocado Prices dashboard') #st.title('Avocado Prices dashboard') st.markdown(''' This is a dashboard showing the *average prices* of different types of :avocado: Data source: [Kaggle](https://www.kaggle.com/datasets/timmate/avocado-prices-2020) ''') st.header('Summary statistics') st.header('Line chart by geographies')
After adding and saving the above new code, you should notice the page with your app has the below options.

This is because when Streamlit detects the changes in the script, it asks us whether we want to rerun the app. Let’s select the option ‘Always rerun’ so that the new app will be displayed automatically when we change and save the script.
Now you should be able to see the new app. It has a title, some description with Markdown formatting, and two headers. We’ll create two sections: one to show the summary statistics, and the other to show a line chart.

Display data/table
We’ll start filling out the summary statistics section. As the header suggested, we’ll put a data table showing statistics.
So we’ll add the below lines of code under this header. We grab the avocado prices dataset and calculate its statistics (the average prices by avocado types), then display the results using st.dataframe
. The function st.dataframe
displays the DataFrames as interactive tables.
st.header('Summary statistics') avocado = pd.read_csv('avocado.csv') avocado_stats = avocado.groupby('type')['average_price'].mean() st.dataframe(avocado_stats)
Now, if we go to the browser, you should see the new app.

Since it’s an interactive table, you can try, for example, clicking on the column header average_price and sorting the data by it.
Great!
That’s it for the summary statistics section.
Visualize the data
Now we’ll work on the line chart section. Let’s first display a simple line chart.
There are multiple ways to display charts in Streamlit, such as Streamlit functions, Matplotlib, Altair, and Plotly. We’ll use the plotly chart as an example.
So please put the below code into your script. We can generate a line figure using the Plotly Express library and then display it using st.plotly_chart
. And since there are different geographies in the dataset, we use ‘Los Angeles’ as an example.
st.header('Line chart by geographies') line_fig = px.line(avocado[avocado['geography'] == 'Los Angeles'], x='date', y='average_price', color='type', title='Avocado Prices in Los Angeles') st.plotly_chart(line_fig)
Nice!
In the new app, you should be able to find the plotly line chart under the ‘Line chart by geographies’ section.

So this is a line chart for only one geography. We want to explore this same chart from different geographies other than ‘Los Angeles’.
How can we do that?
Let’s add some interactive widgets to this section.
Add interactive widgets
Now let’s make our line chart interactive.
We add two widgets: a select box, and a button. So please replace the code from the last section as below. Please note that in Streamlit, we treat widgets like variables.
selected_geography = st.selectbox(label='Geography', options=avocado['geography'].unique()) submitted = st.button('Submit') if submitted: filtered_avocado = avocado[avocado['geography'] == selected_geography] line_fig = px.line(filtered_avocado, x='date', y='average_price', color='type', title=f'Avocado Prices in {selected_geography}') st.plotly_chart(line_fig)
Let’s take a closer look at what we’ve added:
st.selectbox
: this widget provides options for unique geographies. Since we use widgets like variables in Streamlit, we assign it to the variableselected_geography
. Whenever the user selects geography on the select box, its value is stored in such variablest.button
: this widget displays a button. Then we use anif
statement to define its behavior. If the button is clicked (True), we filter for the dataset being that specific geography chosen on the select box, then create and display its line chart
Now you should be able to see the new widgets within the app. Try to select geography from the select box, and click the button. You should see a line chart displayed like below.

This is good! But there’s one thing unusual with it.
Now, if we select another geography from the select box, the line chart for the previous selection disappears. This is because every time we interact with a widget like the select box, the app reruns everything and updates its value. But it is not what we expect from a usual app. The chart should stay there until we click the button to update it.
We’ll fix that by containing these elements in a form.
Control flow with form
So let’s replace the previous code with the below.
with st.form('line_chart'): selected_geography = st.selectbox(label='Geography', options=avocado['geography'].unique()) submitted = st.form_submit_button('Submit') if submitted: filtered_avocado = avocado[avocado['geography'] == selected_geography] line_fig = px.line(filtered_avocado, x='date', y='average_price', color='type', title=f'Avocado Prices in {selected_geography}') st.plotly_chart(line_fig)
In the above code, we add st.form
. This function creates a form that batches elements with a ‘Submit’ style button. Whenever that Submit button is clicked in the form, all widgets values in the form will be processed in a batch.
We use the with
statement to add elements to st.form
. Within the form, the elements mostly stay the same as before, except for the button. Within the form, we must define it as st.form_submit_button
, instead of st.button
.
Now, if we go to our new app, you should see the widgets are grouped visually inside a form.
The line chart will appear again if we select geography and hit the submit button. While as shown in the screenshot below, if we change the selection to another geography, the previous line chart remains until we hit the submit button again. Because now the information is batched and processed together in the form. This is exactly the behavior we are used to!

Change the layout
All right, so our app already has its main content. We can also add something to show extra information about it.
We’ll add a sidebar to the left panel of it.
Please add the below code to your script to display the sidebar. We use the with
statement again to put elements (a subheader and a Markdown string) into the sidebar.
with st.sidebar: st.subheader('About') st.markdown('This dashboard is made by Just into Data, using **Streamlit**')
Now looking at the new app, you should see the sidebar with text.

Add media content
In the end, let’s add some media: an image to our dashboard.
We use st.sidebar.image
below, which is an alternative to adding st.image
into the with
statement of st.sidebar
. This applies to other elements as well. We can either add st.sidebar
.element directly, or add to the with st.sidebar
statement, st.
element. We use a Streamlit logo online for the image and set its width to 50.
with st.sidebar: st.subheader('About') st.markdown('This dashboard is made by Just into Data, using **Streamlit**') st.sidebar.image('https://streamlit.io/images/brand/streamlit-mark-color.png', width=50)
You should be able to see such an image displayed within the sidebar.

Cache for better performance
One last thing we’d like to cover in this Streamlit Python tutorial. We can replace the code for loading the dataset with the below function wrapped with the st.cache
decorator.
@st.cache def load_data(path): dataset = pd.read_csv(path) return dataset avocado = load_data('avocado.csv')
When we mark a function with @st.cache
, Streamlit first runs it and stores the results in a local cache. So that the next time the function is called, Streamlit will skip the execution of the function if nothing has been changed. You can read about the details here.
Within our example, it’s fast to load our small dataset. You won’t notice any difference. But this is extremely useful if you put really slow operations within the function.
The complete script and Run it through URL
If you haven’t gotten the chance to run your app, look here. We have deployed this app on the Streamlit Cloud so that you can interact with it as a user. Select different geographies within the select box and see the updated chart.
Here is the complete script for our app.
import streamlit as st import pandas as pd import plotly.express as px st.write('# Avocado Prices dashboard') #st.title('Avocado Prices dashboard') st.markdown(''' This is a dashboard showing the *average prices* of different types of :avocado: Data source: [Kaggle](https://www.kaggle.com/datasets/timmate/avocado-prices-2020) ''') st.header('Summary statistics') @st.cache def load_data(path): dataset = pd.read_csv(path) return dataset avocado = load_data('avocado.csv') avocado_stats = avocado.groupby('type')['average_price'].mean() st.dataframe(avocado_stats) st.header('Line chart by geographies') with st.form('line_chart'): selected_geography = st.selectbox(label='Geography', options=avocado['geography'].unique()) submitted = st.form_submit_button('Submit') if submitted: filtered_avocado = avocado[avocado['geography'] == selected_geography] line_fig = px.line(filtered_avocado, x='date', y='average_price', color='type', title=f'Avocado Prices in {selected_geography}') st.plotly_chart(line_fig) with st.sidebar: st.subheader('About') st.markdown('This dashboard is made by Just into Data, using **Streamlit**') st.sidebar.image('https://streamlit.io/images/brand/streamlit-mark-color.png', width=50)
One last tip here. We can run Streamlit script stored in an URL. We’ve saved the complete script on GitHub. So you can run the command below in your terminal to launch the example app as well.
streamlit run https://github.com/liannewriting/streamlit_example/blob/main/streamlit_example.py
In this tutorial, you’ve successfully created your first Streamlit app in Python!
For further learning, please check out the official documentation:
Please leave a comment for any questions you may have or anything else.