
How to Get Yahoo Finance Financial Statements in Python Using yfinance
How to Scrape Financial Statements from Yahoo Finance with Python: A Practical Guide
This guide walks through a practical workflow for extracting Yahoo Finance financial statements using Python. We will start with the fastest path—yfinance—and then build a more resilient HTML scraper with requests and BeautifulSoup for times when you need direct page-level control.
What You'll Need: Python Libraries for Yahoo Finance Data
Installing yfinance and pandas
Begin with a clean Python environment. Install the core libraries from PyPI:
pip install yfinance pandas
yfinance provides a convenient wrapper around Yahoo Finance data endpoints and returns data in pandas DataFrames. pandas is the workhorse for cleaning, reshaping, and analyzing tabular financial data.
When to use requests and BeautifulSoup instead
If the yfinance wrapper is unavailable, insufficient for a specific statement period, or you need to inspect the raw HTML directly, add requests and an HTML parser:
pip install requests beautifulsoup4 lxml
requests fetches the page, while BeautifulSoup or lxml parses the HTML tables. This fallback is useful when Yahoo changes its layout or when you need a field that the wrapper does not expose.
| Library | Primary role |
|---|---|
yfinance | Access Yahoo Finance data as pandas DataFrames |
pandas | Clean, reshape, and analyze financial tables |
requests | Fetch raw HTML pages |
BeautifulSoup / lxml | Parse HTML and extract statement tables |
Why Yahoo Finance Is a Practical Source for Fundamental Data
Stock prices, company financials, and key metrics
Yahoo Finance is a practical starting point because it brings together stock prices, company financials, and key metrics in one place. For quantitative research, this means you can pull income statement, balance sheet, cash flow statement, and historical price data without switching between many sources.
The yfinance library wraps Yahoo Finance data into clean pandas DataFrames. That structure is especially useful for analysis: each row can represent a financial line item and each column a reporting period, or vice versa, depending on how you transpose the data.
Quick Start: Fetch Financial Statements with yfinance
Initializing a Ticker object
Start by creating a Ticker object for the company you want to analyze:
import yfinance as yf
ticker = yf.Ticker('AAPL')
The ticker string can be any symbol Yahoo Finance recognizes, such as MSFT, JPM, or an index-tracking ETF.
Accessing .financials, .balance_sheet, and .cashflow
Once the Ticker object exists, access the three core statements through properties:
income_statement = ticker.income_stmt
balance_sheet = ticker.balance_sheet
cash_flow = ticker.cashflow
Each property returns a pandas DataFrame. In the default orientation, columns are reporting dates and rows are line items such as revenue, operating income, total assets, or free cash flow.
Displaying data in a structured format
To inspect the first few rows:
print(income_statement.head())
If you prefer one row per reporting period, transpose the table:
income_statement_t = income_statement.T
This is the easiest way to get financial statements from Yahoo Finance in Python. Use the DataFrames directly for screening, feature engineering, or exploratory analysis.
Building a Resilient HTML Scraper with requests and BeautifulSoup
Sometimes the wrapper is not enough. For example, you may need the exact table as rendered on Yahoo Finance, or you may want to capture a statement that yfinance does not return cleanly.
Fetching pages with requests
A resilient scraper starts with a realistic request. Set a user-agent header and fetch the page:
import requests
url = 'https://finance.yahoo.com/quote/AAPL/financials'
headers = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Safari/537.36'
}
response = requests.get(url, headers=headers)
print(response.status_code)
If the status code is not 200, stop and investigate before retrying.
Parsing tables with BeautifulSoup or lxml
Parse the returned HTML and locate the statement table:
from bs4 import BeautifulSoup
soup = BeautifulSoup(response.text, 'lxml')
table = soup.find('div', class_='tableContainer')
Yahoo Finance page structures can change, so inspect the page markup in your browser's developer tools and adjust selectors accordingly.
Polite request delays to avoid IP bans
Always add delays between requests. A simple time.sleep(2) between pages can help reduce the risk of being IP-banned. Do not fire hundreds of requests rapidly; respect the site and fetch only what you need.
import time
time.sleep(2)
A slower, reliable scraper is better than a fast one that gets blocked.
Preparing Scraped Statements for Analysis
Cleaning rows and columns
Raw HTML tables often contain repeated header rows, blank columns, or mixed text values. Start by removing rows that are completely empty:
df = df.dropna(how='all')
Then normalize line-item labels. For example, remove trailing whitespace, collapse multiple spaces, and make labels lowercase if that helps your matching logic:
df.columns = [str(c).strip() for c in df.columns]
df.iloc[:, 0] = df.iloc[:, 0].str.strip()
Converting HTML tables to pandas DataFrames
A faster route is to let pandas parse the HTML directly:
import pandas as pd
tables = pd.read_html(response.text)
df = tables[0]
From there, set the first column as the row index and the first row as column headers if needed:
df = df.set_index(df.columns[0])
df.columns = df.iloc[0]
df = df.iloc[1:]
The goal is a tidy DataFrame where each financial line item is a row, each reporting period is a column, and every cell contains a numeric value where possible. That structure is suitable for downstream quantitative analysis.
From Raw Financial Statements to Quantitative Signals
Ranking assets by expected future returns
Financial statement data can become features for machine-learning models that rank assets by expected future returns. For example, you might construct features from revenue growth, operating margin, asset turnover, or changes in cash flow, then use those features to sort assets from most to least attractive.
Walk-forward, cross-sectional evaluation
The right evaluation matters more than the feature set. In walk-forward, cross-sectional signal forecasting, you train on past data and evaluate on the next period, repeating this process as time moves forward. This is an out-of-sample process because the model never sees the period it is trying to predict.
A common performance metric is the Sharpe ratio, calculated from the strategy's period-by-period returns after ranking assets. If you want a deeper explanation, see The 'Walk‑Forward' Test: The Only Backtest That Matters. For a practical Python implementation of the return-based metric, see How to Compute the Sharpe Ratio from a Pandas Series of Returns.
The Sharpe ratio rewards robust and uncorrelated signals rather than overfit results. A signal that performs well only in-sample is not useful; a signal that holds up out-of-sample across many periods is harder to ignore.
How AlphaNova Competitions Use This Research Workflow
A pure machine-learning problem with obfuscated data
AlphaNova hosts walk-forward, cross-sectional signal forecasting competitions. Participants receive obfuscated financial data: tabular data with multiple assets per period, but with the underlying company names and statement labels hidden. This makes the challenge a pure machine-learning problem rather than a traditional fundamental stock-picking exercise.
Submission, testing, and evaluation
Participants submit a single Python Predictor class. A local runner is provided for testing before submission, so you can validate the code and output format on your own machine.
Submissions are evaluated out-of-sample using the Sharpe ratio. A greedy quality selection process admits only genuinely uncorrelated, overfit-filtered signals. That means your signal must add information beyond what existing signals already capture.
Performance-based rewards and intellectual property
This workflow mirrors the scraper-to-signal path described above: extract data, clean it, create features, then evaluate them under a strict out-of-sample regime. The main difference is that AlphaNova provides the obfuscated data and the evaluation infrastructure, letting you focus on the predictive model.
Prizes, Ownership, and Community at AlphaNova
Cash prizes are paid in stablecoins or directly to a bank account. There is no staking and no token volatility; performance alone determines earnings. Prize pools scale with participation, and top-performing signals may earn ongoing profit sharing.
Participants retain full ownership of their intellectual property. Competitions are free to enter.
The community includes data scientists, quants, and students from around the world. If you want more context on how crowdsourced quant platforms evolved, see A Brief History of Crowdsourced Hedge Funds: Quantopian, Quantiacs and Numerai.
AlphaNova's mission is to democratise access to institutional-grade quantitative research. The competition format is designed to reward signal quality, not marketing or reputation.
Next Steps: Build Your Own Financial Statement Scraper
Use yfinance first for quick access to financial statements. Add a polite HTML scraper only when you need direct page-level control. Then shift your energy toward the harder part: turning cleaned fundamentals into testable, out-of-sample signals.