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.

Choosing a Platform

🚀 Streamlit Cloud
100% Free
  • Deploy in 5 minutes from GitHub
  • Zero configuration required
  • Auto-redeploys on every git push
  • Built-in secrets manager
  • Official support from Streamlit team
  • Apps sleep after inactivity (free tier)
  • Only Streamlit apps — no other services
  • Limited compute on free tier
⚙️ Render
Free + Paid Tiers
  • Works with any Python web app
  • Persistent disk storage available
  • Custom domains on all plans
  • Background workers and cron jobs
  • Detailed build and runtime logs
  • Slightly more setup than Streamlit Cloud
  • Free tier also sleeps after inactivity
  • Cold starts can be slow on free tier
ℹ️ Which should you use? Start with Streamlit Cloud if you want the fastest path to a live URL. Use Render if you need persistent storage, want to run a database alongside your app, or need a custom domain without paying.

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.

Terminal — generating requirements.txt automatically
# 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
requirements.txt — example for a typical Streamlit data app
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:

Folder structure — clean layout for deployment
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
.gitignore — files to keep out of GitHub
# 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

Terminal — creating a GitHub repo and pushing your app
# 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 — local secrets file (never commit this)
# .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"
Python — reading secrets in your app code
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.

Terminal — the update workflow
# 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.

.streamlit/config.toml — customising your app's appearance
[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
Python — setting page config at the top of your app
# 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.

Procfile — tells Render how to start your app
web: streamlit run app.py --server.port=$PORT --server.address=0.0.0.0 --server.headless=true
runtime.txt — specifies which Python version to use
python-3.11.7

Your project now needs these five files at minimum:

Project structure for Render deployment
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.

Python — reading environment variables on Render
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.

RuleCorrectWrong
Store API keysSecrets manager or env variableDirectly in app.py or constants file
Commit secretsNever — add to .gitignoresecrets.toml or .env in git
Share secretsVia platform dashboard onlyEmail, Slack, code comments
Test locally.streamlit/secrets.toml (gitignored)Hardcoded strings in your code
Key exposed?Revoke immediately on the API providerDelete 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.

Custom domain setup — same process for both platforms
# 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.

Common errors and their fixes
── 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

FeatureStreamlit CloudRender (Free)
PriceFreeFree tier available
Setup time5 minutes~15 minutes
Extra config filesNone neededProcfile + runtime.txt
Auto-redeploy on pushYesYes
Secrets managementBuilt-in TOML editorEnvironment variables
Custom domainYes (with verification)Yes (simpler setup)
Persistent storageNoYes (paid plans)
Sleep on inactivityYes (free tier)Yes (free tier)
Works with non-Streamlit appsNo — Streamlit onlyYes — Flask, FastAPI, etc.
Best forQuickest Streamlit deployMore 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.