Still "Too Many Requests" Error also in Version 0.2.62
Describe bug
Issue Description yfinance shows different behavior between interactive Python interpreter mode and script execution mode. In script mode, fetching stock information fails with a "Too Many Requests" error, while identical code works correctly in interactive mode.
###Root Cause The problem originates in the _get_ticker_tz() function (in base.py) and its interaction with the caching system:
- In interactive mode, _fetch_ticker_tz() is called when a symbol is not in the cache (tkr-tz.db) or when the cache is invalid.
- In script mode, however, _fetch_ticker_tz() is not called if the symbol already exists in the cache, even if the script runs in a completely new process.
- The critical issue is that _fetch_ticker_tz() doesn't just retrieve the timezone but also has important side effects: it initializes cookies and crumb values in the YfData class that are required for all subsequent API requests.
- When this initialization is bypassed, API requests fail with "Too Many Requests" errors due to missing authentication information.
###How to Reproduce
- Run in interactive Python interpreter:
import yfinance as yf
yf.Ticker("AAPL").history() # Works fine
- Then run a script with the same symbol:
import yfinance as yf
yf.Ticker("AAPL").history() # Fails with "Too Many Requests"
- If you clear the cache or change the cache directory, the script suddenly works again:
# Clear cache before using yfinance
import os, platformdirs, sqlite3
cache_dir = os.path.join(platformdirs.user_cache_dir(), "py-yfinance")
tz_db = os.path.join(cache_dir, "tkr-tz.db")
if os.path.exists(tz_db):
conn = sqlite3.connect(tz_db)
conn.execute("DELETE FROM _kv")
conn.execute("DELETE FROM _tz_kv")
conn.commit()
conn.close()
import yfinance as yf
yf.Ticker("AAPL").history() # Works again
Technical Analysis
(Generated by Claude Sonnet 3,7) The difference in behavior is due to how the cache is handled between interactive mode and script mode:
- In _get_ticker_tz(), the cache is retrieved with c = cache.get_tz_cache() and checked for the symbol with c.lookup(self.ticker).
- If the symbol is found, no further API calls are made, which are necessary for cookie initialization.
- In interactive mode, these cookies are likely built correctly through shared session use, while in script mode this initialization is skipped.
- The actual authentication happens in YfData._get_crumb_csrf() and YfData._get_cookie_basic(), which can be bypassed depending on the cache status.
Suggested Solution for the yfinance Project
(Generated by Claude Sonnet 3.7)
The _get_ticker_tz() function should be modified to ensure necessary cookies are initialized even when symbols are loaded from cache:
def _get_ticker_tz(self, proxy, timeout):
proxy = proxy or self.proxy
if self._tz is not None:
return self._tz
c = cache.get_tz_cache()
tz = c.lookup(self.ticker)
# Even if we have the timezone from cache, ensure
# cookies are initialized by making a light API call
# or by checking a session variable
if tz and not utils.is_valid_timezone(tz):
c.store(self.ticker, None)
tz = None
if tz is None:
tz = self._fetch_ticker_tz(proxy, timeout)
if utils.is_valid_timezone(tz):
c.store(self.ticker, tz)
else:
tz = None
else:
# Even when we have the timezone, make sure cookies are set
self._ensure_cookies_set(proxy, timeout)
self._tz = tz
return tz
def _ensure_cookies_set(self, proxy, timeout):
# Minimal call to initialize cookies without fetching unnecessary data
try:
self._data._get_crumb_csrf(proxy, timeout)
except Exception:
# Ignore errors here as this is just an attempt to set cookies
pass
Simple code that reproduces your problem
see above
Debug log from yf.enable_debug_mode()
Run in interactive Mode DEBUG Entering history() DEBUG Entering _fetch_ticker_tz() DEBUG Entering get() DEBUG Entering _make_request() DEBUG url=https://query2.finance.yahoo.com/v8/finance/chart/GOOG DEBUG params=frozendict.frozendict({'range': '1d', 'interval': '1d'}) DEBUG Entering _get_cookie_and_crumb()
Run in skript: DEBUG Entering history() DEBUG GOOG: Yahoo GET parameters: {'period1': '2025-05-28 00:00:00-04:00', 'period2': '2025-06-10 04:00:39-04:00', 'interval': '5m', 'includePrePost': False, 'events': 'div,splits,capitalGains'} DEBUG Entering get() DEBUG Entering _make_request() DEBUG url=https://query2.finance.yahoo.com/v8/finance/chart/GOOG DEBUG params={'period1': 1748404800, 'period2': 1749542439, 'interval': '5m', 'includePrePost': False, 'events': 'div,splits,capitalGains'} DEBUG Entering _get_cookie_and_crumb()
Bad data proof
No response
yfinance version
0.2.62
Python version
3.12
Operating system
Windows 11
I really like Gen AI but this isn't explaining the root problem very well. How is loading timezone from cache causing a skip of crumb/cookie init? Cache & timezone logic should be entirely separate from data.py. I suspect a little hallucination happening.
I can't fully answer this question, which is why I marked Claude's "findings" accordingly. I initially searched for the error around cookies.db, while Claude kept focusing on timezones. This eventually led me to discover tkr-tz.db by chance, which contained all previously used Yahoo ticker symbols with their timezone information. The actual fact is: The debug outputs differ in how the functions are called. In the interactive interpreter, _fetch_ticker_tz is always called and no error occurs. In script mode, this function is not called when the entry already exists in tkr-tz.db. That's why the script works when I remove the entries from tkr-tz.db. In my opinion, this can only be an initialization issue and a side effect from a code change. Why the error then occurs at _get_cookie_and_crumb, I cannot say. Debugging yfinance is extremely difficult for me (at least in VS) and not really transparent. That Claude or AI in general can become quite imaginative, especially with diffuse problems, is correct. Particularly in longer chats, it tends to get stuck somewhere. I haven't checked the correction suggestion and cannot do so.
Its crazy that this issue keeps occurring in a lot of new versions.... And we still have no ideas how to solve it despite upgrade yfinance. Sometime force upgrading works, sometimes not
That's the same thing I had to realize as well. Even with my "workarounds" it worked a few times and then didn't work again. The most stable solution so far: I call the script directly via PowerShell instead of through the Visual Studio debugger! I hardly dare to say it: That has worked stably until today! What makes the difference? No idea!
Sorry, it's bullshit. The script don't run under 3.12 with the newest version of yfinance. Unter PowerShell it uses 3.11 and an older version of yfinance. I'll try to analyse this.
@Hektiker24 i can confirm,
import yfinance as yf
yf.Ticker("AAPL").history() # Works again
Python 3.12.3 doesn't work Python 3.11.6 works. Python 3.9.23 works.
Only way I could get this work again was to clear the python cache manually in VSCode and reload the window. I'm US based & latest yfinance: C:\Users\drubach>pip show yfinance Name: yfinance Version: 0.2.65