Fetch Stock Data the Clean Way (No More Eye Strain)
Before we jump into the code: If you need custom data tools or dashboards built, I’m currently open for freelance projects. Feel free to reach out to me on [LinkedIn Here].
We’ve all been there. You need historical price data for a specific stock to run some analysis. You go to Yahoo Finance, search for the ticker, navigate to the “Historical Data” tab, filter the dates, apply the filter, and then finally hunt for the download button and now its doesn’t work as well :> .
It’s tedious. Especially if you need to do it for five or ten different stocks.
I decided to solve this problem by building a dedicated tool. I wanted something clean, simple, and fast. The goal was to build a web app that takes a stock symbol and hands me a CSV file — no ads, no navigation menus, just data.
Thanks to Streamlit and yfinance, I managed to pull this off in under 50 lines of code.
Here is how I built it, and how you can run it too.
The Code
Here is the full script. It handles the UI, fetches the data from Yahoo Finance, handles errors (in case you mistype a symbol), and generates a download button.
import streamlit as st
import yfinance as yf
# Page Setup
st.set_page_config(page_title="Stock Downloader", layout="centered")
st.title(" Personal Stock Data Downloader")
# User Inputs should be exactly same as it would be on yahoo finance
ticker = st.text_input("Enter Stock Symbol", value="AAPL").upper()
mode = st.radio("Select Date Mode:", ["Period", "Date Range"], horizontal=True)
data = None
try:
# Logic to fetch data based on mode
if mode == "Period":
period = st.selectbox("Select Period", ["1mo", "3mo", "6mo", "1y", "5y", "max"])
if st.button("Fetch Data"):
data = yf.download(ticker, period=period, progress=False)
elif mode == "Date Range":
dates = st.date_input("Select Range", [])
if len(dates) == 2 and st.button("Fetch Data"):
data = yf.download(ticker, start=dates[0], end=dates[1], progress=False)
# Display and Download Section
if data is not None and not data.empty:
st.success(f"Data fetched for {ticker}!")
st.dataframe(data)
csv = data.to_csv().encode('utf-8')
st.download_button("Download CSV", csv, f"{ticker}_data.csv", "text/csv")
elif data is not None and data.empty:
st.error("No data found. Please check the ticker symbol.")
except Exception as e:
st.error(f"An error occurred: {e}")
How It Works
I wanted this to be robust, not just a script that works once and breaks the next time. Here is the logic behind the build:
The Setup
We import streamlit for the interface and yfinance to tap into market data. I used st.set_page_config to give the browser tab a proper title and center the layout—small details that make the app feel polished.Flexible Inputs
Sometimes you want “the last 3 months” of data. Other times, you need a specific date range (e.g., from Jan 1st, 2020 to Jan 1st, 2021). I used a radio button to let the user switch between these two modes:
- Period Mode: Uses a simple dropdown menu.
- Date Range Mode: Uses a calendar picker. Note the check if len(dates) == 2. This ensures the code only runs once the user has picked both a start and an end date, preventing crashes.
Error Handling (The “Pro” Touch)
APIs can be finicky. Sometimes the internet cuts out, or more likely, you mistype “GOOG” as “GOOGGG.” I wrapped the logic in a try...except block and added a check for data.empty. Instead of the app crashing with a wall of red code, it simply tells the user: "No data found. Please check the ticker symbol."The Download Button
This is the most important feature. Displaying data on a screen is nice, but useless if you can’t take it with you. The st.download_button converts our DataFrame into a CSV string and lets you save it directly to your machine.
Summary
This project proves you don’t need complex frameworks to build useful tools. In less than 50 lines, we have a functional, interactive web app that solves a real-world workflow problem.
If you’re looking to build something similar — maybe a dashboard that visualizes this data, or a portfolio tracker — I’m available for freelance work. [Reach out to me on LinkedIn] and let’s talk about your project.
Top comments (0)