Embedding a Plotly figure in Streamlit means rendering an interactive Plotly chart inside a Streamlit web app with minimal code by calling st.plotly_chart().
Interactive visualizations are essential for data storytelling—Plotly provides the charts, Streamlit delivers them to the browser.
This article walks you through every step required to embed a Plotly figure inside a Streamlit application, explains why the combination is powerful, and highlights best practices, common pitfalls, and advanced tips.
Plotly is a popular Python graphing library for building interactive, publication-quality charts. Streamlit, on the other hand, is a lightweight framework that turns Python scripts into shareable web apps with zero front-end expertise. When you embed Plotly figures in Streamlit, you give stakeholders the ability to explore data by panning, zooming, and hovering—while still deploying the app in minutes.
Streamlit runs your Python script top-to-bottom and sends UI elements to the browser via WebSockets. Any call to st.plotly_chart()
serializes the Plotly figure to JSON and hands it off to the browser-side Plotly.js engine. The chart then becomes fully interactive without additional JavaScript.
px.bar()
, px.line()
, etc.)go.Figure()
)plotly.subplots.make_subplots()
pip install streamlit plotly
import plotly.express as px
import pandas as pd
df = px.data.gapminder().query("year == 2007 & continent == 'Europe'")
fig = px.scatter(
df, x="gdpPercap", y="lifeExp", size="pop", color="country",
hover_name="country", log_x=True, size_max=60,
title="Life Expectancy vs GDP (Europe, 2007)"
)
import streamlit as st
st.set_page_config(page_title="Plotly + Streamlit Demo", layout="wide")
st.title("Embed Plotly Figures in Streamlit")
st.plotly_chart(fig, use_container_width=True)
Save the script as app.py
and launch:
streamlit run app.py
Streamlit widgets (e.g., st.selectbox
, st.slider
) can dynamically update Plotly figures. Because Streamlit reruns your script on every widget interaction, simply recreate the figure with new parameters inside the script.
use_container_width=True
This option allows the chart to auto-resize with the browser window, improving responsiveness on mobile screens.
If your figure relies on heavy preprocessing, wrap that part in @st.cache_data
(Streamlit 1.18+) to avoid redundant processing on reruns.
Plotly renders in the client; huge datasets (>50k points) can become sluggish. Aggregate data or use sampling techniques when possible.
st.empty()
For live dashboards, create an placeholder = st.empty()
container and update it in a loop:
placeholder = st.empty()
while True:
fig = generate_fresh_fig()
placeholder.plotly_chart(fig, use_container_width=True)
time.sleep(5)
Streamlit automatically forwards your app’s theme to Plotly, or you can force a theme by assigning fig.update_layout(template="plotly_dark")
.
Bidirectional communication (e.g., capturing click data) is possible via plotly_events
from streamlit-plotly-events
community component.
import streamlit as st
, the st.plotly_chart()
call fails. Always import first.plotly.tools.mpl_to_plotly()
if required.st.set_page_config(layout="wide")
and containers/columns to manage space."""Full Streamlit app demonstrating Plotly embedding."""
import streamlit as st
import plotly.express as px
st.set_page_config(page_title="Gapminder Explorer", layout="wide")
continent = st.selectbox("Continent", ["Asia", "Europe", "Africa", "Americas", "Oceania"])
year = st.slider("Year", 1952, 2007, 2007, step=5)
@st.cache_data
def load_data():
return px.data.gapminder()
df = load_data()
filtered = df.query("continent == @continent & year == @year")
fig = px.scatter(
filtered, x="gdpPercap", y="lifeExp", size="pop", color="country",
hover_name="country", log_x=True, size_max=60,
title=f"Life Expectancy vs GDP ({continent}, {year})"
)
st.plotly_chart(fig, use_container_width=True)
By leveraging st.plotly_chart()
, you can embed rich, interactive Plotly figures into Streamlit apps with only a few lines of Python. This synergy accelerates prototype-to-production workflows and elevates stakeholder engagement.
Modern data products demand interactivity. Static images quickly become obsolete when stakeholders expect to zoom, hover, and filter their data. Plotly offers deep interactivity out of the box, but shipping Plotly in Flask or Django often requires front-end wiring. Streamlit abstracts that boilerplate: call st.plotly_chart(), and your figure is immediately available via WebSockets to any browser. This drastically shortens development cycles, enabling data engineers and analysts to prototype and deploy analytical tools without a front-end team.
Yes. Place the chart in a placeholder created by st.empty()
or st.container()
and update it inside a loop or callback. Remember to throttle updates (e.g., time.sleep()
) to avoid unnecessary resource usage.
Absolutely. Both Plotly Express figures (px.*
) and Graph Objects (go.Figure
) are instances of plotly.graph_objs._figure.Figure
and can be passed directly to st.plotly_chart()
.
Aggregate or sample your data on the server side, limit marker opacity or size, and cache expensive computations with @st.cache_data
. In some cases, consider WebGL traces (e.g., Scattergl
) for better rendering speed.
You can deploy via Streamlit Community Cloud, Docker, or internal servers. The Plotly figure requires no extra configuration—Streamlit bundles Plotly.js automatically.