I Tested 4 Free Stock Market APIs — Here’s Which One Actually Works for Side Projects

Last month I needed real-time-ish stock quotes for a personal trading dashboard. Nothing fancy — just current prices, daily OHLCV, and maybe some basic fundamentals. I figured this would take an afternoon. It took a week, because every “free” market data API has a different definition of “free.”

I tested Polygon.io, Finnhub, Alpha Vantage, and yfinance (the unofficial Yahoo Finance wrapper) for a simple use case: pull 30 tickers every 5 minutes during market hours, store the data in SQLite, and trigger alerts on volume spikes.

The Test Setup

I wrote the same data pipeline four times — one per API. Each version pulls price data for 30 S&P 500 stocks, handles rate limits gracefully, and logs failures. The code ran on a $5 VPS for two weeks straight.

import requests
import time
from datetime import datetime

TICKERS = ["AAPL", "MSFT", "NVDA", "GOOGL", "AMZN", ...]  # 30 total

def fetch_polygon(ticker, api_key):
    url = f"https://api.polygon.io/v2/aggs/ticker/{ticker}/prev"
    r = requests.get(url, params={"apiKey": api_key})
    if r.status_code == 429:
        time.sleep(12)  # free tier: 5 calls/min
        return fetch_polygon(ticker, api_key)
    return r.json()["results"][0]

Polygon.io — Best Docs, Painful Rate Limits

Polygon’s free tier gives you 5 API calls per minute. For 30 tickers, that’s 6 minutes minimum per refresh cycle. Their docs are excellent — OpenAPI spec, clear error codes, consistent response formats. The data quality is solid; I never got a stale quote during market hours.

The catch: 5 calls/min means you’re always waiting. I ended up batching with their grouped daily endpoint (/v2/aggs/grouped/locale/us/market/stocks/{date}) which returns all tickers in one call. That’s the move if you’re on the free plan.

Verdict: Best API design. Use the grouped endpoints and you can work within 5 calls/min. Paid plan ($29/mo) removes limits entirely.

Finnhub — Generous Limits, Quirky Data

Finnhub gives you 60 calls/min on the free tier. That’s 12x Polygon’s allowance. I could refresh all 30 tickers in under a minute with room to spare.

def fetch_finnhub(ticker, api_key):
    url = "https://finnhub.io/api/v1/quote"
    r = requests.get(url, params={"symbol": ticker, "token": api_key})
    data = r.json()
    return {
        "price": data["c"],      # current
        "open": data["o"],
        "high": data["h"],
        "low": data["l"],
        "prev_close": data["pc"],
        "volume": data.get("v")  # sometimes missing!
    }

The issue: volume data was missing or zero for about 8% of my calls during the first hour of trading. Pre-market data is inconsistent. And their WebSocket (which is real-time on free tier!) occasionally drops connection without sending a close frame, so your reconnect logic needs to be reliable.

Verdict: Best free tier for polling frequency. The free WebSocket is genuinely useful for real-time dashboards. Just validate your data — don’t trust volume numbers before 10:30 AM ET.

Alpha Vantage — The OG That’s Showing Its Age

Alpha Vantage has been around forever. Free tier: 25 calls/day. Yes, per day, not per minute. They recently slashed this from 500/day (which was already tight).

25 calls/day is useless for anything beyond a daily cron job checking your portfolio at close. I couldn’t even pull all 30 tickers once. The response format is also uniquely annoying — keys like “1. open” and “2. high” instead of just “open” and “high.”

# Alpha Vantage response format... why?
{
    "Global Quote": {
        "01. symbol": "AAPL",
        "02. open": "189.5100",
        "05. price": "191.2400",
        # seriously, numbered string keys?
    }
}

Verdict: Skip it in 2026. The rate limits make it impractical for anything but the simplest daily check. The API design feels stuck in 2015.

yfinance — Free But Fragile

yfinance is an unofficial Python library scraping Yahoo Finance. No API key needed. No rate limits (sort of). Sounds perfect, right?

It broke twice during my two-week test. Yahoo changes their page structure, the library stops working, someone pushes a fix to PyPI in a day or two. For a personal project you check occasionally, that’s fine. For anything running unattended, it’s a liability.

import yfinance as yf

# Simple, but fragile
ticker = yf.Ticker("AAPL")
hist = ticker.history(period="1d", interval="5m")
# Works great until it doesn't

When it works, the data is rich — splits, dividends, options chains, financials, all free. The download() function handles batching natively. But I wouldn’t build anything I can’t babysit on top of it.

Verdict: Best for Jupyter notebooks and research. Don’t put it in a cron job you want to forget about.

My Actual Setup (What I Ended Up Using)

I use Finnhub’s WebSocket for real-time price updates during market hours, Polygon’s grouped daily endpoint for end-of-day OHLCV, and yfinance for fundamentals data I pull once a week. Three APIs, each doing what it does best.

import websocket
import json

def on_message(ws, message):
    data = json.loads(message)
    for trade in data.get("data", []):
        price = trade["p"]
        symbol = trade["s"]
        volume = trade["v"]
        # write to SQLite, check alerts
        check_volume_spike(symbol, volume)

ws = websocket.WebSocketApp(
    f"wss://ws.finnhub.io?token={FINNHUB_KEY}",
    on_message=on_message,
    on_error=lambda ws, e: reconnect(ws),
)

Total cost: $0/month. The tradeoff is maintenance — when yfinance breaks or Finnhub drops connections, I fix it manually. If I valued my time at $50/hr, Polygon’s $29/mo plan would pay for itself in the first week.

Quick Comparison

Polygon.io Free: 5 calls/min, excellent docs, 15-min delayed quotes, best for batch daily data
Finnhub Free: 60 calls/min + free WebSocket, good data (watch pre-market volume), best for real-time
Alpha Vantage Free: 25 calls/day, outdated format, skip it
yfinance: No limits but breaks periodically, rich data, best for research notebooks

What I’d Recommend

If you’re building a trading dashboard or alert system, start with Finnhub. The 60 calls/min and free WebSocket give you the most room to experiment. Once you know your architecture works, consider Polygon’s paid tier for reliability.

If you’re doing backtesting or research, yfinance is hard to beat for the price (free). Just pin your dependency version and keep a fallback data source.

For the actual trading execution side, I’ve been using Alpaca’s API which has its own market data included with a brokerage account — that’s a separate topic I covered recently.

If you’re running this kind of setup on a home server, a Beelink Mini PC (affiliate link) draws about 15W and handles multiple Python processes and SQLite without breaking a sweat. I’ve been running mine 24/7 for months. A CyberPower UPS (affiliate link) keeps it alive through power blips — lost data during a brownout once, never again.

For monitoring your API pipeline, I keep a Grafana dashboard tracking call counts, error rates, and data freshness. A portable second monitor (affiliate link) dedicated to dashboards saves constant window-switching.


📡 I share trading signals and market intelligence daily in my free Telegram channel. If you’re building trading tools, the context helps. Join https://t.me/alphasignal822 for free market intelligence.

📧 Get weekly insights on security, trading, and tech. No spam, unsubscribe anytime.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

Also by us: StartCaaS — AI Company OS · Hype2You — AI Tech Trends