AlphaNova
Back to Blog
How to Get Yahoo Finance Financial Statements in Python Using yfinance

How to Get Yahoo Finance Financial Statements in Python Using yfinance

Dominik Keller
August 25, 2026

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.

LibraryPrimary role
yfinanceAccess Yahoo Finance data as pandas DataFrames
pandasClean, reshape, and analyze financial tables
requestsFetch raw HTML pages
BeautifulSoup / lxmlParse 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.

Join the latest AlphaNova competition