Getting a Streamlit app running on your own laptop is easy. Getting it running on the internet — at a URL you can share with anyone — requires a few extra steps. But those steps are simpler than you might think, and the best options are completely free.
This guide covers two deployment platforms. Streamlit Cloud is the official free hosting service — it takes about five minutes and requires nothing more than a GitHub repository. Render is a more general cloud platform that gives you more control, persistent storage and the option to run other services alongside your app.
By the end you will have a public URL you can share with anyone, and you will know how to handle secrets, update your app and troubleshoot common problems.
Preparing Your App — Steps for Both Platforms
Both Streamlit Cloud and Render deploy from a GitHub repository. Before you deploy anywhere you need to do three things: create a requirements file, organise your folder structure and push everything to GitHub.
requirements.txt — Listing Your Dependencies
When you run your app locally, all the packages are already installed on your machine. The cloud server has nothing. You need to tell it exactly which packages to install and which versions to use. That is what requirements.txt does.
# Option 1: freeze everything currently installed in your environment
pip freeze > requirements.txt
# Option 2: use pipreqs to detect only what your app actually imports
# This is cleaner — it only lists packages your code actually uses
pip install pipreqs
pipreqs . --force
# Option 3: write it manually (best for simple apps)
# Create a file called requirements.txt and list each package on its own line
streamlit==1.31.0
pandas==2.2.0
numpy==1.26.4
matplotlib==3.8.2
scikit-learn==1.4.0
plotly==5.19.0
requests==2.31.0
# Pin exact versions so the cloud build is identical to your local setup
# Pinning prevents "it works on my machine" surprises
⚠️
Never put secrets in requirements.txt. This file is public in your GitHub repository. API keys, database passwords and tokens belong in secrets managers — covered below.
Folder Structure
Keep your project organised. Both platforms expect your main app file to be at the root of the repository or clearly specified. Here is a clean structure that works for both platforms:
my-streamlit-app/
app.py # your main Streamlit script
requirements.txt # all dependencies
.gitignore # files to exclude from git
README.md # optional but good practice
.streamlit/
config.toml # optional: theme and settings
secrets.toml # local secrets — NEVER commit this
data/
sample.csv # static data files if needed
utils/
helpers.py # helper functions
# Secrets — NEVER commit these
.streamlit/secrets.toml
.env
*.env
# Python cache
__pycache__/
*.pyc
*.pyo
.pytest_cache/
# Virtual environments
venv/
.venv/
env/
# Editor files
.vscode/
.idea/
*.DS_Store
Pushing to GitHub
# Initialise git in your project folder
git init
git add .
git commit -m "Initial commit — Streamlit app"
# Create a new repo on GitHub (github.com/new), then connect it
git remote add origin https://github.com/YOUR_USERNAME/YOUR_REPO_NAME.git
git branch -M main
git push -u origin main
# After the first push, updating is just three commands
git add .
git commit -m "Your update message"
git push
Deploying on Streamlit Cloud
Streamlit Cloud is the official free hosting built by the Streamlit team. It is deeply integrated with GitHub — you connect your repo and it handles everything else automatically. Every time you push to GitHub, your app redeploys within seconds.
Step-by-Step Deployment
1
Sign up at share.streamlit.io
Go to share.streamlit.io and click "Sign up". Use your GitHub account — this grants Streamlit Cloud access to your repositories.
2
Click "New app"
On your Streamlit Cloud dashboard, click the "New app" button in the top right corner.
3
Fill in the three fields
Repository: select your GitHub repo. Branch: select main. Main file path: type the filename of your app, for example app.py.
4
Click "Deploy!"
Streamlit Cloud installs your dependencies and launches the app. This takes 1–3 minutes the first time.
5
Your app is live
You get a URL like https://yourname-yourapp-app-abc123.streamlit.app. Share this with anyone.
Managing Secrets on Streamlit Cloud
Secrets are API keys, database URLs, passwords and any other sensitive value your app needs. You never put these in your code or in GitHub. Streamlit Cloud has a built-in secrets manager where you store them safely.
Locally, you store secrets in .streamlit/secrets.toml. On Streamlit Cloud, you paste the same content into the Secrets section of your app settings. Your code reads from the same place either way — st.secrets.
# .streamlit/secrets.toml — this file stays on your machine only
# Add this filename to your .gitignore
OPENAI_API_KEY = "sk-your-actual-key-here"
DATABASE_URL = "postgresql://user:password@host:5432/dbname"
WEATHER_API_KEY = "abc123xyz"
# Group related secrets under a header
[aws]
access_key_id = "AKIAIOSFODNN7EXAMPLE"
secret_access_key = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
region = "ap-south-1"
import streamlit as st
# Access top-level secrets by key name
api_key = st.secrets["OPENAI_API_KEY"]
database_url = st.secrets["DATABASE_URL"]
# Access grouped secrets using dot notation
aws_key = st.secrets["aws"]["access_key_id"]
aws_secret = st.secrets.aws.secret_access_key
# Fallback to environment variable if secret is not set (useful for testing)
import os
api_key = st.secrets.get("OPENAI_API_KEY") or os.environ.get("OPENAI_API_KEY")
# Add secrets in Streamlit Cloud dashboard:
# App → Settings → Secrets → paste the toml content → Save
Updating Your App
Once deployed, updating your app is just a git push. Streamlit Cloud watches your repository and automatically redeploys every time you push a commit to the connected branch. The whole process takes about 30 seconds.
# Make changes to your app locally
# Test it: streamlit run app.py
# Then deploy the update
git add .
git commit -m "Add new chart to dashboard"
git push
# Streamlit Cloud detects the push and redeploys automatically
# Your live URL stays the same — no action needed on the dashboard
Streamlit Config — Theme and Settings
You can customise your app's theme, page title, icon and layout using a config.toml file. Unlike secrets, this file is committed to GitHub — it contains no sensitive information.
[theme]
primaryColor = "#ffb800" # accent colour for buttons and sliders
backgroundColor = "#0d0e14" # main background
secondaryBackground = "#1a1b23" # sidebar and widget backgrounds
textColor = "#ffffff"
font = "sans serif"
[server]
headless = true # required for deployment
port = 8501
[browser]
gatherUsageStats = false # disable telemetry
# Must be the FIRST Streamlit command in your script
st.set_page_config(
page_title="My Awesome App",
page_icon="📊", # emoji or path to image file
layout="wide", # "centered" or "wide"
initial_sidebar_state="expanded"
)
Deploying on Render
Render is a general-purpose cloud platform that can host web services, background workers, databases and cron jobs. For Streamlit apps it works excellently, and it gives you more flexibility than Streamlit Cloud — including persistent disk storage and the ability to run your app alongside a database or API.
Required Extra Files
Render needs two extra files that Streamlit Cloud handles automatically. You need to tell Render how to start your app and which Python version to use.
web: streamlit run app.py --server.port=$PORT --server.address=0.0.0.0 --server.headless=true
Your project now needs these five files at minimum:
my-streamlit-app/
app.py # your Streamlit app
requirements.txt # dependencies
Procfile # start command for Render
runtime.txt # Python version
.gitignore # secrets and cache excluded
Step-by-Step Deployment on Render
1
Sign up at render.com
Create a free account. Connect your GitHub account when prompted so Render can access your repositories.
2
Click "New +" and choose "Web Service"
From the Render dashboard, click "New +" then select "Web Service" from the dropdown.
3
Connect your GitHub repository
Search for your repo and click "Connect". Render will scan it for the Procfile and requirements.txt automatically.
4
Configure the service
Name: anything you like. Region: closest to your users. Branch: main. Build Command: pip install -r requirements.txt. Start Command: streamlit run app.py --server.port=$PORT --server.address=0.0.0.0 --server.headless=true.
5
Select "Free" plan and click "Create Web Service"
Render starts building your app. Watch the logs — the build takes 2–5 minutes the first time.
6
Your app is live
You get a URL like https://your-app-name.onrender.com. The first request after a period of inactivity is slow (cold start) — this is normal on the free tier.
Environment Variables on Render
On Render, secrets are set as environment variables rather than TOML files. Your code reads them with os.environ.get() or through st.secrets if you also have a secrets.toml provided at build time.
import os
import streamlit as st
# Read environment variables set in Render dashboard
api_key = os.environ.get("OPENAI_API_KEY")
database_url = os.environ.get("DATABASE_URL")
# Raise a clear error if a required key is missing
if not api_key:
st.error("OPENAI_API_KEY is not set. Add it in Render → Environment.")
st.stop()
# On Render: Dashboard → Your Service → Environment → Add Environment Variable
# Key: OPENAI_API_KEY Value: sk-your-actual-key
# Click Save Changes — Render redeploys automatically
Secrets Best Practices
Leaking a secret key is one of the most common and expensive mistakes in deployment. API keys found in public GitHub repos are scraped by bots within seconds. Here are the rules to follow every time.
| Rule | Correct | Wrong |
| Store API keys | Secrets manager or env variable | Directly in app.py or constants file |
| Commit secrets | Never — add to .gitignore | secrets.toml or .env in git |
| Share secrets | Via platform dashboard only | Email, Slack, code comments |
| Test locally | .streamlit/secrets.toml (gitignored) | Hardcoded strings in your code |
| Key exposed? | Revoke immediately on the API provider | Delete the commit (too late — already scraped) |
Custom Domain
Both platforms give you a generated URL by default. If you want your app at app.yourname.com you can add a custom domain.
# Step 1: Add your custom domain in the platform dashboard
# Streamlit Cloud: App → Settings → Custom domain
# Render: Your Service → Settings → Custom Domains → Add domain
# Step 2: The platform gives you a CNAME record to add to your DNS
# Example CNAME record:
# Name: app (this creates app.yourname.com)
# Value: cname.streamlit.app (or your Render service URL)
# Step 3: Add the CNAME in your domain registrar (Namecheap, GoDaddy, Cloudflare)
# DNS changes take 5 minutes to 48 hours to propagate
# Step 4: HTTPS is enabled automatically — no certificate needed
ℹ️
Render free tier supports custom domains. Streamlit Cloud requires you to verify domain ownership via a TXT record first, then add the CNAME. Both provide free HTTPS automatically.
Troubleshooting — Common Deployment Problems
Most deployment failures come from the same handful of issues. Here are the most common ones and how to fix them.
── Error: ModuleNotFoundError: No module named 'pandas' ───────────────
# Fix: the package is missing from requirements.txt
# Add the package and pin the version:
# pandas==2.2.0
# Commit and push — the app rebuilds automatically
── Error: FileNotFoundError: data/myfile.csv ──────────────────────────
# Fix: the data file was not committed to GitHub
# Check your .gitignore is not excluding your data folder
# git add data/myfile.csv
# git commit -m "Add data file"
# git push
── Error: KeyError: 'OPENAI_API_KEY' ─────────────────────────────────
# Fix: the secret is not set in the platform secrets manager
# Streamlit Cloud: App → Settings → Secrets → Add key
# Render: Service → Environment → Add Environment Variable
── Error: Port 8501 is already in use ────────────────────────────────
# Fix: on Render, use $PORT not 8501
# Procfile: streamlit run app.py --server.port=$PORT
── App runs locally but crashes on deploy ────────────────────────────
# Fix checklist:
# 1. Are ALL imports in requirements.txt?
# 2. Are file paths relative (not absolute like /Users/shashank/...)?
# 3. Are secrets set in the platform dashboard?
# 4. Is st.set_page_config() the FIRST Streamlit command?
# 5. Does the Python version in runtime.txt match your local version?
── App is very slow on first load (Render free tier) ─────────────────
# Normal behaviour — free tier services sleep after 15 minutes of inactivity
# The cold start (spinning up) takes 30-60 seconds
# Solution: upgrade to a paid plan, or ping the app periodically
# with a free uptime monitor like UptimeRobot
Platform Comparison
| Feature | Streamlit Cloud | Render (Free) |
| Price | Free | Free tier available |
| Setup time | 5 minutes | ~15 minutes |
| Extra config files | None needed | Procfile + runtime.txt |
| Auto-redeploy on push | Yes | Yes |
| Secrets management | Built-in TOML editor | Environment variables |
| Custom domain | Yes (with verification) | Yes (simpler setup) |
| Persistent storage | No | Yes (paid plans) |
| Sleep on inactivity | Yes (free tier) | Yes (free tier) |
| Works with non-Streamlit apps | No — Streamlit only | Yes — Flask, FastAPI, etc. |
| Best for | Quickest Streamlit deploy | More control and flexibility |
⚡ Key Takeaways
- Both platforms deploy from GitHub. Every push to your connected branch triggers an automatic redeploy. Your live URL never changes.
- Create requirements.txt before deploying. The cloud server has nothing installed. Every package your app imports must be listed. Pin exact version numbers to prevent version mismatch surprises.
- Add .streamlit/secrets.toml and .env to .gitignore before your very first commit. Once a secret is pushed to GitHub, assume it is compromised — revoke it immediately on the API provider.
- Streamlit Cloud is the fastest path to a live URL — five minutes, no extra config files, built-in secrets editor. Use it for pure Streamlit apps you want to share quickly.
- Render requires a Procfile and runtime.txt but gives you more control — custom domains, persistent disk, background workers and support for any Python framework.
- On Render, use --server.port=$PORT in your start command. Render assigns the port dynamically — hardcoding 8501 will cause the deployment to fail.
- Read secrets with st.secrets["KEY"] on Streamlit Cloud and with os.environ.get("KEY") on Render. You can combine both with a fallback: st.secrets.get("KEY") or os.environ.get("KEY").
- st.set_page_config() must be the first Streamlit command in your script. Calling any other st. function before it will cause a deployment error.
- Both free tiers sleep after inactivity. The first request after the app wakes up takes 30–60 seconds. Use UptimeRobot or a similar free service to ping your app every 14 minutes if you want it always awake.
- To troubleshoot a failed deployment, read the build logs carefully. The error is almost always a missing package in requirements.txt, a missing data file, or a missing secret.
Tags:
Streamlit
Deployment
Python
Streamlit Cloud
Render
Beginner
Shashank Shekhar
Founder & Creator — Hoopsiper.com
Full stack developer and educator. Building Hoopsiper to help developers learn faster through practical, no-fluff coding guides on JavaScript, AI/ML, Python and modern web development.