Yahoo Finance API in 2026: Is There Still an Official API? (Python, Limits, Pricing and Alternatives)
Originally published on dev.to

No. There is no official Yahoo Finance API in 2026.
There's no developer portal, no API key and no pricing page. What developers call "the Yahoo Finance API" is almost always yfinance, an open-source Python library built on the public endpoints behind Yahoo's website.
The library says so itself. Its README states that yfinance is "not affiliated, endorsed, or vetted by Yahoo", describes it as "intended for research and educational purposes", and reminds users that Yahoo's finance API is meant for personal use.
So the question worth asking is whether yfinance is safe to build on.
If you're:
- building a stock screener or a portfolio tracker,
- feeding market data to an AI agent,
- or about to put yfinance inside something other people depend on,
this matters.
I ran a reproducible test to answer it. Same 50 tickers, same five years, yfinance against a documented REST API. The result wasn't the one I expected.

Why "Yahoo Finance API" is still a question in 2026
The search results tell the story. The first page for "yahoo finance api" is a 2013 Q&A thread, a Stack Overflow question, a few wrappers and a blog post calling it "now discontinued". Search "yahoo finance api python" and the #3 result is a Reddit thread titled "yfinance is so unreliable; any other free apis?"
Developers keep asking because the answer keeps shifting.
Yahoo shut down its official finance API in 2017. The website kept serving data, so the community built clients on top of it. yfinance became the default because it's free and one pip install away.
But a client for a website is a different thing from an API.
An API comes with a contract: documented endpoints, versioning, rate limits you can read, and someone to email when it breaks. yfinance has none of that, by design. If Yahoo changes its website, yfinance has to catch up.
You can see how often that happens. I checked yfinance's release history on PyPI: 150 releases since May 2019, 12 of them in the last 12 months. That's roughly one release a month.
Some are features. Many are fixes for something Yahoo changed.
The test: 50 tickers, two sources, same five years
Here's the setup, so you can reproduce it:
- Tickers: 50 US large caps and ETFs (AAPL, MSFT, NVDA, BRK-B, JPM, SPY, QQQ, GLD and others)
- Range: daily bars from 2021-10-29 to 2026-10-28
- Source A: yfinance 1.7.0, one
Ticker.history()call per ticker - Source B: EODHD's End-of-Day API, one REST call per ticker
- Run: October 29, 2026, sequential requests from my own machine on a single connection
I measured four things: how many tickers came back complete, how long it took, whether the two sources agree on the dates, and whether they agree on the prices.
Step 1: The same request in both libraries
Start small. Five days of Apple, side by side:
pip install yfinance requests pandas
import os
import requests
import pandas as pd
import yfinance as yf
# yfinance: unofficial client for Yahoo's web endpoints
yf_df = yf.Ticker("AAPL").history(start="2026-10-22", end="2026-10-29", auto_adjust=False)
print("yfinance")
print(yf_df[["Close", "Adj Close", "Volume"]].round(2).to_string())
# EODHD: documented REST API, one call per ticker
r = requests.get(
"https://eodhd.com/api/eod/AAPL.US",
params={"api_token": os.environ["EODHD_API_KEY"], "fmt": "json",
"from": "2026-10-22", "to": "2026-10-28"},
timeout=30,
)
eo_df = pd.DataFrame(r.json()).set_index("date")
print("\nEODHD")
print(eo_df[["close", "adjusted_close", "volume"]].to_string())

The closes match to the cent. Two small things stand out, though.
Yahoo rounds volume to the nearest hundred (46,898,900 vs 46,898,875). And on the most recent day, October 28, the volumes differ: 35,595,700 on Yahoo against 35,714,331 on EODHD.
The latest yfinance row (close 343.83, volume 35,595,700) is exactly what Yahoo's own history page shows:

Note what's missing from that page when you're not signed in to a paid account: a download button. Historical downloads are now a paid feature. I covered that change and seven alternatives in Yahoo Finance Historical Data Download Is Now Paid.
Step 2: The 50-ticker benchmark
The core of the script is two fetch functions that return the same shape:
import time
from datetime import date, timedelta
END = date(2026, 10, 28)
START = END - timedelta(days=5 * 365)
def fetch_yfinance(ticker):
t0 = time.perf_counter()
try:
df = yf.Ticker(ticker).history(start=START, end=END + timedelta(days=1), auto_adjust=False)
err = None if not df.empty else "empty"
except Exception as e: # yfinance raises on rate limits
df, err = pd.DataFrame(), f"{type(e).__name__}: {e}"
return df, err, time.perf_counter() - t0
def fetch_eodhd(ticker):
t0 = time.perf_counter()
params = {"api_token": os.environ["EODHD_API_KEY"], "fmt": "json", "from": START, "to": END}
try:
r = requests.get(f"https://eodhd.com/api/eod/{ticker}.US", params=params, timeout=30)
r.raise_for_status()
df = pd.DataFrame(r.json())
err = None if not df.empty else "empty"
except Exception as e:
df, err = pd.DataFrame(), f"{type(e).__name__}: {e}"
return df, err, time.perf_counter() - t0
Then loop over the 50 tickers with each one and count.

Both sources returned all 50 tickers, 1,254 trading days each. No errors, no empty frames, no "Too Many Requests".
yfinance was also faster: 9.3 seconds against 60.6 for EODHD, both sequential, one request at a time.
Step 3: Do the numbers agree?
Coverage is one thing. The data has to match too.
I aligned both datasets by date and compared the adjusted close on every shared day:

- Dates only in one source: 0
- Adjusted closes differing by more than 0.5%: 4 out of 62,700
All four are IBM, in the last four sessions before the Kyndryl spin-off on November 4, 2021. Yahoo records that spin-off as a 1.046 "split" and adjusts earlier prices with it. EODHD's prices for those four days don't apply the same factor. Neither source is missing data. They just model a corporate action in different ways, and that's worth knowing if you backtest across spin-offs.
Every other adjusted close was within 0.5%, and the largest gap outside IBM was 0.497% (CAT).
Step 4: Trying to break yfinance
The Reddit threads talk about rate limits and random failures, so I went looking for them:
- Test A: three back-to-back
yf.download()calls, all 50 tickers, multi-threaded - Test B:
Ticker.info(the fundamentals snapshot) for all 50 tickers, no pauses between calls

It held. 150 out of 150 in the bursts, 50 out of 50 on .info.
So here's the honest result: from a single machine, at 50 tickers, yfinance worked perfectly.
Then why not just use yfinance?
For a lot of projects, you should.
The test shows that yfinance works today. It can't show what yfinance promises, because it promises nothing.
Here's what the test didn't cover, and where the trouble usually starts:
- Scale and IP reputation. I ran from one machine, at a modest volume. I didn't test cloud servers or thousands of tickers, which is where most "Too Many Requests" complaints in those Reddit threads come from.
- Change without notice. Twelve releases in a year means your code depends on a maintainer reacting fast whenever Yahoo moves something. That's free work by volunteers, with no SLA.
- Terms of use. The library itself points you to Yahoo's terms and says Yahoo's API is intended for personal use. A paid product or a client deliverable sits on different ground.
- Nobody to call. When a documented API returns a wrong number, you open a ticket. When yfinance does, you open a GitHub issue and hope.
A demo, a notebook or a personal tracker can live with that. A product used by other people usually can't.
What about the Google Finance API?
Same story, slightly worse.
Google retired its Finance API years ago. Today the only official way to get Google Finance data is the GOOGLEFINANCE() function, and it only works inside Google Sheets. There's no REST endpoint and no Python client.
Developers who need Google Finance data in code end up scraping the website or the Sheets output, which is more fragile than yfinance.
If you're a Sheets user fighting #N/A errors, that's a different problem with its own fixes.
yfinance vs a documented API: the decision table
| yfinance | Documented API (EODHD) | |
|---|---|---|
| Official | No, community library | Yes, documented REST API |
| API key | None | Required |
| Cost | Free | Free tier, then paid plans |
| Limits | Undocumented, enforced by Yahoo | Published per plan |
| Our 50-ticker test | 50/50, 9.3 s | 50/50, 60.6 s |
| Price agreement (our test) | 62,696 of 62,700 adjusted closes within 0.5% of each other | (same comparison) |
| Change notice | None, library follows the website | Public documentation |
| Support | GitHub issues | Support tickets |
| Commercial use | Check Yahoo's terms | Separate commercial plans |
Use yfinance when:
- it's a notebook, a prototype or a personal project,
- a day of broken data costs you nothing,
- you can pin a version and fix things yourself.
Move to a documented API when:
- other people depend on the output,
- the code runs unattended on a server,
- you need fundamentals, many exchanges or a written guarantee of what you're getting.
Where EODHD fits, and what it costs
I use EODHD for this kind of work because it answers the questions yfinance can't: what am I allowed to call, how often, and what happens when something looks wrong.
From its pricing page:
| Plan | Price | API calls/day | End-of-day history |
|---|---|---|---|
| Free | $0 | 20 | 1 year |
| EOD Historical All-World | $19.99/mo | 100,000 | 30+ years |
| Fundamentals Data Feed | $59.99/mo | 100,000 | Not included (fundamentals only) |
| All-In-One | $99.99/mo | 100,000 | 30+ years |
Be careful with one detail. The free plan won't run this benchmark. Fifty tickers is 50 calls, the free plan allows 20 a day, and five years of history needs more than its one year. It also doesn't include fundamentals. To reproduce the full test, you need EOD Historical All-World.
Each end-of-day request costs 1 call, and a fundamentals request costs 10.
๐ Get started with EODHD here. Use the code KEVIN10 for 10% off.
Three gotchas I hit while building the test
1. "Close" doesn't mean the same thing in both libraries. With auto_adjust=False, yfinance's Close is already split-adjusted. EODHD's close is the raw price. My first comparison showed gaps of 95% on GOOGL and AMZN and 90% on NVDA, and they were all stock splits. Compare Adj Close with adjusted_close. I explained why this breaks backtests in Backtesting in Python: Why Most Backtests Lie.
2. Ticker formats differ. Berkshire is BRK-B on Yahoo and BRK-B.US on EODHD. I wrongly converted it to BRK.B.US and got a 404. Keep the hyphen and add the exchange suffix.
3. Timestamps differ. yfinance returns a timezone-aware index (2026-10-22 00:00:00-04:00), and EODHD returns plain dates. Strip the timezone and normalize before you join them, or nothing will align.
Key takeaways
- There is no official Yahoo Finance API in 2026. yfinance is an unofficial client for Yahoo's website.
- In my test it worked flawlessly: 50/50 tickers, no rate-limit errors, and adjusted closes within 0.5% of EODHD on 62,696 of 62,700 days.
- What's missing is a contract: no SLA, no notice before changes, and terms that point to personal use.
FAQs
โ Is there an official Yahoo Finance API? โ No. Yahoo doesn't offer a public developer API, API keys or paid API plans for Finance data. Tools like yfinance read the endpoints behind Yahoo's website and aren't affiliated with Yahoo.
โ Is the Yahoo Finance API free? โ yfinance is free and needs no key. What you're allowed to do with the data depends on Yahoo's terms of use, and the library notes it's intended for personal use.
โ What is the yfinance rate limit?
โ
Yahoo doesn't publish one. In my test, 50 sequential history calls, three multi-threaded 50-ticker bursts and 50 .info calls all went through from a single machine. Most rate-limit complaints come from higher volumes and cloud servers, which I didn't test.
โ Do I need a Yahoo Finance API key? โ No, because there's no official API to issue one. If a tutorial asks for a "Yahoo Finance API key", it's usually a third-party service that resells or wraps Yahoo data.
โ Is there a Google Finance API for Python?
โ
No. Google's only official access today is the GOOGLEFINANCE() function inside Google Sheets. For Python you need a separate data provider.
โ Is yfinance data accurate? โ In my 50-ticker, five-year comparison, adjusted closes matched EODHD within 0.5% on 62,696 of 62,700 days. The four exceptions came from different handling of IBM's 2021 spin-off.
yfinance isn't broken. It's unofficial.
For a notebook, that's a fine trade. For a product, the question that matters is who's responsible when the data changes, and with yfinance the answer is nobody.
Looking for technical content for your company? I can help โ LinkedIn ยท kevinmenesesgonzalez@gmail.com