Getting Free Financial Data via APIs
Access stock prices, crypto data, exchange rates, and fundamentals using free APIs - no Bloomberg terminal required.
The Free Data Landscape
Professional financial data from Bloomberg or Refinitiv costs thousands per month. But for personal projects, learning, and even small-scale analysis, there are excellent free alternatives. Here are four APIs that cover stocks, crypto, and currencies - giving you a solid foundation for any finance project.
yfinance is the easiest starting point - no API key needed. Alpha Vantage gives you more structured data with a free key. CoinGecko covers cryptocurrency. And the Bank of England provides official exchange rates and economic data.
yfinance: The Quick Start
The yfinance library wraps Yahoo Finance data into a clean Python API. No API key required. You get current prices, historical data, fundamentals, dividends, and more. It is the fastest way to get stock data into Python. Install it with pip install yfinance.
The downside: Yahoo can change their page structure at any time, which occasionally breaks yfinance until the maintainers patch it. For critical production systems, use a paid API. For learning and personal projects, yfinance is unbeatable.
import yfinance as yf
import pandas as pd
# Single stock - quick info
ticker = yf.Ticker('AAPL')
info = ticker.info
print(f'Company: {info["longName"]}')
print(f'Price: ${info["currentPrice"]:.2f}')
print(f'Market Cap: ${info["marketCap"]:,.0f}')
print(f'P/E Ratio: {info["trailingPE"]:.2f}')
print(f'Dividend Yield: {info.get("dividendYield", 0) * 100:.2f}%')
# Historical data - daily prices for the last year
history = ticker.history(period='1y')
print(f'\nLast 5 days:')
print(history.tail())
# Multiple stocks at once
tickers = yf.download(['AAPL', 'MSFT', 'GOOGL'], period='6mo')
print(f'\nDownloaded {len(tickers)} days of data for 3 stocks')
# Save to CSV for later
history.to_csv('aapl_prices.csv')Alpha Vantage: Structured and Reliable
Alpha Vantage provides a proper REST API with JSON responses. The free tier gives you 25 requests per day - enough for daily analysis. Sign up at alphavantage.co to get your key. They cover stocks, forex, crypto, and economic indicators.
The API is well-documented and the response format is consistent, making it easier to build reliable data pipelines compared to web scraping approaches.
import requests
import pandas as pd
# Get your free API key at alphavantage.co
API_KEY = 'YOUR_API_KEY'
BASE_URL = 'https://www.alphavantage.co/query'
def get_daily_prices(symbol):
"""Fetch daily stock prices from Alpha Vantage."""
params = {
'function': 'TIME_SERIES_DAILY',
'symbol': symbol,
'outputsize': 'compact', # Last 100 days
'apikey': API_KEY
}
response = requests.get(BASE_URL, params=params)
data = response.json()
# Parse the nested JSON into a DataFrame
time_series = data.get('Time Series (Daily)', {})
df = pd.DataFrame.from_dict(time_series, orient='index')
df.columns = ['Open', 'High', 'Low', 'Close', 'Volume']
df = df.astype(float)
df.index = pd.to_datetime(df.index)
df = df.sort_index()
return df
# Fetch and display
df = get_daily_prices('MSFT')
print(f'Microsoft - Last 5 days:')
print(df.tail())
# Company overview - fundamentals
def get_fundamentals(symbol):
params = {
'function': 'OVERVIEW',
'symbol': symbol,
'apikey': API_KEY
}
response = requests.get(BASE_URL, params=params)
data = response.json()
return {
'Name': data.get('Name'),
'Sector': data.get('Sector'),
'PE Ratio': data.get('PERatio'),
'EPS': data.get('EPS'),
'Dividend Yield': data.get('DividendYield'),
'52 Week High': data.get('52WeekHigh'),
'52 Week Low': data.get('52WeekLow'),
}
fundamentals = get_fundamentals('MSFT')
for key, val in fundamentals.items():
print(f'{key}: {val}')CoinGecko: Cryptocurrency Data
CoinGecko has the most comprehensive free crypto API available. No API key needed for basic usage. You get prices, market caps, historical data, and information on thousands of coins and tokens. Rate limit is around 10-30 calls per minute on the free tier.
import requests
import pandas as pd
from datetime import datetime
BASE_URL = 'https://api.coingecko.com/api/v3'
def get_crypto_price(coin_id):
"""Get current price for a cryptocurrency."""
url = f'{BASE_URL}/simple/price'
params = {
'ids': coin_id,
'vs_currencies': 'usd,gbp',
'include_24hr_change': 'true',
'include_market_cap': 'true'
}
response = requests.get(url, params=params)
return response.json()
# Current prices - no API key needed
for coin in ['bitcoin', 'ethereum', 'solana']:
data = get_crypto_price(coin)
info = data[coin]
print(f'{coin.title():12s} ${info["usd"]:>10,.2f} 24h: {info["usd_24h_change"]:+.2f}%')
def get_crypto_history(coin_id, days=90):
"""Get historical prices for a cryptocurrency."""
url = f'{BASE_URL}/coins/{coin_id}/market_chart'
params = {'vs_currency': 'usd', 'days': days}
response = requests.get(url, params=params)
data = response.json()
# Parse into DataFrame
prices = data['prices']
df = pd.DataFrame(prices, columns=['timestamp', 'price'])
df['date'] = pd.to_datetime(df['timestamp'], unit='ms')
df = df.set_index('date').drop('timestamp', axis=1)
return df
# Get 90 days of Bitcoin prices
btc = get_crypto_history('bitcoin', 90)
print(f'\nBitcoin - Last 5 days:')
print(btc.tail())
btc.to_csv('bitcoin_90d.csv')Exchange Rates: Bank of England and Free APIs
For GBP exchange rates, the Bank of England publishes official data through their Statistical Interactive Database. For a simpler option, exchangerate.host provides free rates for 170+ currencies with no API key required. Both are suitable for currency conversion in financial applications.
import requests
import pandas as pd
import xml.etree.ElementTree as ET
def get_exchange_rate(from_currency='USD'):
"""Get GBP exchange rates from the Bank of England."""
# Bank of England Statistical Interactive Database
# XUDLGBD = USD/GBP spot rate
series_code = 'XUDLGBD' # USD to GBP
url = (
f'https://www.bankofengland.co.uk/boeapps/database/'
f'fromshowcolumns.asp?Travel=NIx&FromSeries=1&ToSeries=50'
f'&DAession=DA&FirstYear=2024&LastYear=2024'
f'&SeriesCodes={series_code}&csv.x=1'
)
# Alternative: use the simpler JSON endpoint
json_url = (
'https://www.bankofengland.co.uk/boeapps/database/'
'fromshowcolumns.asp?csv.x=yes'
'&SeriesCodes=XUDLGBD&CSVF=TN&UsingCodes=Y'
'&VPD=Y&VFD=N'
)
response = requests.get(json_url)
if response.status_code == 200:
# Parse the CSV response
from io import StringIO
df = pd.read_csv(StringIO(response.text))
print(f'Exchange rate data (latest entries):')
print(df.tail())
return df
else:
print(f'Error: {response.status_code}')
return None
# Alternative: use exchangerate.host (free, no key)
def get_exchange_rates_free():
"""Get latest exchange rates from a free API."""
url = 'https://api.exchangerate.host/latest'
params = {'base': 'GBP'}
response = requests.get(url, params=params)
data = response.json()
rates = data.get('rates', {})
print('GBP Exchange Rates:')
for currency in ['USD', 'EUR', 'JPY', 'CHF', 'AUD']:
rate = rates.get(currency, 'N/A')
print(f' GBP/{currency}: {rate}')
return rates
get_exchange_rates_free()Combining APIs: Full Portfolio Snapshot
The real power comes when you combine multiple APIs. This script pulls stock prices from yfinance and crypto prices from CoinGecko, then calculates your total portfolio value in one view. Add the exchange rate API if your holdings span multiple currencies.
import yfinance as yf
import requests
import pandas as pd
from datetime import datetime
def build_portfolio_snapshot():
"""Combine multiple APIs into one portfolio view."""
print(f'Portfolio Snapshot - {datetime.now().strftime("%d %b %Y %H:%M")}')
print('=' * 60)
# Stocks via yfinance
print('\nStocks:')
stocks = {'AAPL': 10, 'MSFT': 5, 'GOOGL': 3}
stock_total = 0
for symbol, shares in stocks.items():
ticker = yf.Ticker(symbol)
price = ticker.info.get('currentPrice', 0)
value = price * shares
stock_total += value
print(f' {symbol:6s} {shares:3d} x ${price:>8.2f} = ${value:>10,.2f}')
print(f' {"-" * 45}')
print(f' {'Stock Total':30s} ${stock_total:>10,.2f}')
# Crypto via CoinGecko
print('\nCrypto:')
crypto = {'bitcoin': 0.5, 'ethereum': 2.0}
crypto_total = 0
for coin, amount in crypto.items():
url = 'https://api.coingecko.com/api/v3/simple/price'
resp = requests.get(url, params={'ids': coin, 'vs_currencies': 'usd'})
price = resp.json()[coin]['usd']
value = price * amount
crypto_total += value
print(f' {coin.title():12s} {amount:.2f} x ${price:>10,.2f} = ${value:>10,.2f}')
print(f' {"-" * 45}')
print(f' {'Crypto Total':30s} ${crypto_total:>10,.2f}')
print(f'\n {'=' * 45}')
print(f' {'TOTAL PORTFOLIO':30s} ${stock_total + crypto_total:>10,.2f}')
build_portfolio_snapshot()Key Takeaways
- - yfinance is the fastest path to stock data - no API key needed
- - Alpha Vantage provides structured REST APIs with 25 free requests per day
- - CoinGecko covers thousands of cryptocurrencies with no key required
- - Bank of England and exchangerate.host provide free currency data
- - Always store API keys in environment variables, never in code
- - Respect rate limits - cache responses and add delays between calls
- - Combine multiple APIs to build comprehensive financial dashboards