yfinance: .info returns 404 on all tickers

@ValueRaider hijacking top post


Describe bug

Call to .info returns 404 error on all tickers. Example url: https://query2.finance.yahoo.com/v6/finance/quoteSummary/SPY?modules=financialData&modules=quoteType&modules=defaultKeyStatistics&modules=assetProfile&modules=summaryDetail&ssl=true Using browsers on multiple connections/devices, yahoo output “Will be right back… Our engineers are working quickly to resolve the issue.”

Data could have moved to new link

Simple code that reproduces your problem

import yfinance as yf yf_ticker=yf.Ticker(“SPY”) yf_ticker.info

Debug log

HTTPError: 404 Client Error: Not Found for url: https://query2.finance.yahoo.com/v6/finance/quoteSummary/SPY?modules=financialData&modules=quoteType&modules=defaultKeyStatistics&modules=assetProfile&modules=summaryDetail&ssl=true

Bad data proof

No response

yfinance version

0.2.31

Python version

No response

Operating system

No response

About this issue

  • Original URL
  • State: closed
  • Created 6 months ago
  • Reactions: 65
  • Comments: 147 (6 by maintainers)

Commits related to this issue

Most upvoted comments

Another poll, but to survey if Pull Request #1657 works / doesn’t work. Works in USA - vote 👍 or 👎

Hi, Here a script I wrote to fix the problem without the yfinance package in my own project. If a developer want to internalize it in yfinance be free:

import requests
import urllib.parse
class YFinance:
    user_agent_key = "User-Agent"
    user_agent_value = ("Mozilla/5.0 (Windows NT 6.1; Win64; x64) "
                        "AppleWebKit/537.36 (KHTML, like Gecko) "
                        "Chrome/58.0.3029.110 Safari/537.36")
    
    def __init__(self, ticker):
        self.yahoo_ticker = ticker

    def __str__(self):
        return self.yahoo_ticker

    def _get_yahoo_cookie(self):
        cookie = None

        headers = {self.user_agent_key: self.user_agent_value}
        response = requests.get("https://fc.yahoo.com",
                                headers=headers,
                                allow_redirects=True)

        if not response.cookies:
            raise Exception("Failed to obtain Yahoo auth cookie.")

        cookie = list(response.cookies)[0]

        return cookie

    def _get_yahoo_crumb(self, cookie):
        crumb = None

        headers = {self.user_agent_key: self.user_agent_value}

        crumb_response = requests.get(
            "https://query1.finance.yahoo.com/v1/test/getcrumb",
            headers=headers,
            cookies={cookie.name: cookie.value},
            allow_redirects=True,
        )
        crumb = crumb_response.text

        if crumb is None:
            raise Exception("Failed to retrieve Yahoo crumb.")

        return crumb

    @property
    def info(self):
        # Yahoo modules doc informations :
        # https://cryptocointracker.com/yahoo-finance/yahoo-finance-api
        cookie = self._get_yahoo_cookie()
        crumb = self._get_yahoo_crumb(cookie)
        info = {}
        ret = {}

        headers = {self.user_agent_key: self.user_agent_value}

        yahoo_modules = ("summaryDetail,"
                         "financialData,"
                         "indexTrend,"
                         "defaultKeyStatistics")

        url = ("https://query1.finance.yahoo.com/v10/finance/"
               f"quoteSummary/{self.yahoo_ticker}"
               f"?modules={urllib.parse.quote_plus(yahoo_modules)}"
               f"&ssl=true&crumb={urllib.parse.quote_plus(crumb)}")

        info_response = requests.get(url,
                                     headers=headers,
                                     cookies={cookie.name: cookie.value},
                                     allow_redirects=True)

        info = info_response.json()
        info = info['quoteSummary']['result'][0]

        for mainKeys in info.keys():
            for key in info[mainKeys].keys():
                if isinstance(info[mainKeys][key], dict):
                    try:
                        ret[key] = info[mainKeys][key]['raw']
                    except (KeyError, TypeError):
                        pass
                else:
                    ret[key] = info[mainKeys][key]

        return ret

I’m using the API v10 and only get values from this modules : “summaryDetail,” “financialData,” “indexTrend,” “defaultKeyStatistics”.

If you need more modules add it in the yahoo_modules

I’ve just installed #1657 and it works like a charm.

pip install git+https://github.com/ranaroussi/yfinance@feature/cookie-and-crumb

for all of you who need it.

Works in Asia - vote 👍 or 👎

Works in Europe - vote 👍 or 👎

@psychoz971 solution fixes Ticker.info in Europe - vote 👍 or 👎

Official release out. If this still doesn’t fix issue for some people (Asia?), create a new issue because a whole new investigation will be required and this thread is long enough.

Can someone tell me when this is going to be fixed? Is it dependent on Yahoo? Is it an issue with the API? Is it because Yahoo wants to charge for the service? Is the current state of Yfinance irreversible? Thank you!

for me it is unrelated to threads, download seems to work always, others not:

#!/bin/python3

import yfinance as yf

print('Quotes:\n')
quotes = yf.download('ORCL', period = '1d')
print(quotes)

print('\n\nQuote:\n')
quote = yf.Ticker('ORCL')
print(quote.info['currentPrice'])
Quotes:

[*********************100%%**********************]  1 of 1 completed
                  Open        High         Low       Close   Adj Close    Volume
Date                                                                            
2023-10-20  106.989998  107.035004  100.660004  101.849998  101.849998  21718467


Quote:

Traceback (most recent call last):
  File "/opt/svn/DynatraceFinance/./test.py", line 11, in <module>
    print(quote.info['currentPrice'])
  File "/home/dstadler/.local/lib/python3.10/site-packages/yfinance/ticker.py", line 142, in info
    return self.get_info()
  File "/home/dstadler/.local/lib/python3.10/site-packages/yfinance/base.py", line 1736, in get_info
    data = self._quote.info
  File "/home/dstadler/.local/lib/python3.10/site-packages/yfinance/scrapers/quote.py", line 571, in info
    self._fetch(self.proxy)
  File "/home/dstadler/.local/lib/python3.10/site-packages/yfinance/scrapers/quote.py", line 600, in _fetch
    result = self._data.get_raw_json(
  File "/home/dstadler/.local/lib/python3.10/site-packages/yfinance/data.py", line 75, in get_raw_json
    response.raise_for_status()
  File "/home/dstadler/.local/lib/python3.10/site-packages/requests/models.py", line 1021, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 404 Client Error: Not Found for url: https://query2.finance.yahoo.com/v6/finance/quoteSummary/ORCL?modules=financialData&modules=quoteType&modules=defaultKeyStatistics&modules=assetProfile&modules=summaryDetail&ssl=true

For the kind of programmers like me (not really experienced and patient) , to fix it I needed to remove the old installation of yfinance (the same version) then do https://github.com/ranaroussi/yfinance/issues/1729#issuecomment-1801880260

yesterday it was working fine with a US VPN, today is not. Locally it is not working either and am based in the US/EAST

The page is genuinely under maintenance I guess https://query2.finance.yahoo.com/v6/finance/quoteSummary/AAPL?modules=financialData&modules=quoteType&modules=defaultKeyStatistics&modules=assetProfile&modules=summaryDetail&ssl=true

That message is the same as 10 days ago.

I’ve observed different IP addresses for query2.finance.yahoo.com when running nslookup on AWS EC2 instances in the US and EU.

Using the following curl command works in the US but not in the EU: curl -v 'https://query2.finance.yahoo.com/v6/finance/quoteSummary/SPY?modules=financialData&modules=quoteType&modules=defaultKeyStatistics&modules=assetProfile&modules=summaryDetail&ssl=true' However, when I hardcode the IP address returned by the DNS lookup from the US instance, the request works outside of the US: curl -v -k -H "Host: query2.finance.yahoo.com" 'https://69.147.92.11/v6/finance/quoteSummary/SPY?modules=financialData&modules=quoteType&modules=defaultKeyStatistics&modules=assetProfile&modules=summaryDetail&ssl=true' Please note that this is not a long-term solution, as the IP address might change dynamically. It’s just an observation that might help diagnose the issue.

Currently I am using https://query2.finance.yahoo.com/v7/finance/options/AAPL which gives us the option chain with quote details

import requests
import json

url = "https://query2.finance.yahoo.com/v7/finance/options/AAPL"
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'}
response = requests.get(url=url, headers=headers)
if response.status_code == 200:
  data = json.loads(response.content)
  print(data['optionChain']['result'][0]['quote']) # provides fundamental data
else:
  print('Error fetching data from URL:', response.status_code)

image

Should I write a email to yahoo?I think it’s their fault isn’t it?

@psychoz971 solution fixes Ticker.info in USA - vote 👍 or 👎

> @bot-unit That reminds me, does #1657 help anyone?

I don’t known. We just need to fix url to use api v7,v8 and v10 and include crumb= in requests.

Crumb we can take something like this:

        self.session = requests.Session()
        response = self.session.get('https://guce.yahoo.com/consent', headers=self.user_agent_headers)
        soup = BeautifulSoup(response.content, 'html.parser')
        csrfTokenInput = soup.find('input', attrs={'name': 'csrfToken'})
        csrfToken = csrfTokenInput['value']
        sessionIdInput = soup.find('input', attrs={'name': 'sessionId'})
        sessionId = sessionIdInput['value']
        originalDoneUrl = 'https://finance.yahoo.com/'
        namespace = 'yahoo'
        data = {
            'agree': ['agree', 'agree'],
            'consentUUID': 'default',
            'sessionId': sessionId,
            'csrfToken': csrfToken,
            'originalDoneUrl': originalDoneUrl,
            'namespace': namespace,
        }
        self.session.post(f'https://consent.yahoo.com/v2/collectConsent?sessionId={sessionId}', data=data, headers=self.user_agent_headers)
        self.session.get(f'https://guce.yahoo.com/copyConsent?sessionId={sessionId}', headers=self.user_agent_headers)
        self.crumb = self.session.get('https://query2.finance.yahoo.com/v1/test/getcrumb', headers=self.user_agent_headers).text

I can confirm using USA VPN fixes the issue. Thanks for sharing @MrH32 !

@psychoz971 solution fixes Ticker.info in Asia - vote 👍 or 👎

I am managing to work around .info no longer working to some extent. From aIl the above activity and proposed workarounds I’m getting the impression that .info isn’t going to be fixed. I am now using fast info and .history. My question is, I’d like to retrieve quantities like dividend yield, capitalization, PE and target mean. I’m not a sophisticated enough python programmer to use the cookie and crumb related workarounds. Can I get those other quantities in a more straightforward way?

@mykolaz Thank you for this help. I figured out how to get .info to work with the cookies&crumbs fix but can no longer get the .Ticker method and associated .history.

The separate class that was provided only contains the endpoint for .info. If you want to use .history() then you just have to use the standard yfinance provided Ticker class which still works fine for that use case. Until the changes are implemented into the library, what I did (since I don’t have enough knowledge of the codebase to make my own fork / pull request at the moment) is just make two Ticker classes and call history or info appropriately depending on which one I need.

@mykolaz Thank you for this help. I figured out how to get .info to work with the cookies&crumbs fix but can no longer get the .Ticker method and associated .history.

The separate class that was provided only contains the endpoint for .info. If you want to use .history() then you just have to use the standard yfinance provided Ticker class which still works fine for that use case. Until the changes are implemented into the library, what I did (since I don’t have enough knowledge of the codebase to make my own fork / pull request at the moment) is just make two Ticker classes and call history or info appropriately depending on which one I need.

It is not that difficult of a workaround. Just use the snippet of code to declare functions that return cookie and crumb. Then use the cookie and crumb like this:

def _get_info(ticker):

     cookie = _get_yahoo_cookie()
     crumb = _get_yahoo_crumb(cookie)

     headers = {USER_AGENT: USER_AGENT_VALUE}

     # Initialized dictionaries
     info = {}
     ret = {}

     yahoo_modules = ("summaryDetail,"
                    "financialData,"
                    "indexTrend,"
                    "defaultKeyStatistics")
     
     url = ("https://query1.finance.yahoo.com/v10/finance/"
               f"quoteSummary/{ticker}"
               f"?modules={urllib.parse.quote_plus(yahoo_modules)}"
               f"&ssl=true&crumb={urllib.parse.quote_plus(crumb)}")
     
     info_response = requests.get(url,
                                   headers=headers,
                                   cookies={cookie.name: cookie.value},
                                   allow_redirects=True)
     
     info = info_response.json()
     info = info['quoteSummary']['result'][0]

     for mainKeys in info.keys():
          for key in info[mainKeys].keys():
               if isinstance(info[mainKeys][key], dict):
                    try:
                         ret[key] = info[mainKeys][key]['raw']
                    except (KeyError, TypeError):
                         pass
               else:
                    ret[key] = info[mainKeys][key]

     return ret

Then use the _get_info function in a variable that you used to do with yf.Ticker({Ticker}).info

@LordByron1788 Are you dumb? You literally posted after someone showing info contains price-related data. I assure you that fast_info is a subset of info - I wrote it. I grant you it’s a small subset and some key names different because it was rushed out in Spring last time info failed, but it helped a lot of users.

Seems like the endpoint fix was also broken as of today. Trying to use the https://e1.ycpi.vip.dca.yahoo.com/ endpoint from Lucas’ fix returns a 404 now.

HTTPError: 404 Client Error: Not Found for url: https://e1.ycpi.vip.dca.yahoo.com/v6/finance/quoteSummary/AAPL?modules=financialData&modules=quoteType&modules=defaultKeyStatistics&modules=assetProfile&modules=summaryDetail&ssl=true

Not an immediate solution to the problem, but roic.ai has API access for only $67 per month. https://roic.ai/pricing

This thread may not be the ideal place to discuss this, but I, for one, would like to have a contingency plan in place for when Yahoo decides to close their API, as I believe some of Yahoo’s APIs have been deprecated for years. I’m okay with paying a reasonable amount for a robust data source. There are a variety of API providers available, and I imagine there are many potential pitfalls.

What’s your stance on this, @ranaroussi and @ValueRaider? Would it be okay to start a discussion on backup alternatives?

How can I solve the problem if I’m working from Spain?

Is there any free solution?

Temporary solution: sed -i ‘0 i 69.147.92.11 query2.finance.yahoo.com’ /etc/hosts

I tried to apply curl changes to yfinance, as a temporary hotfix for testing

https://github.com/ranaroussi/yfinance/compare/main...lucas03:yfinance:lukas/yahoo_domain

I am not really into programming at this level but i think the answers is understanding why it works with an american IP…

Because Yahoo is banning not-American IP ˆ)

Right now I am trying with this american VPN ip 143.244.44.169 and I am getting 404. =)

For any other amateurs who are struggling to even fathom GitHub, I pulled https://github.com/ranaroussi/yfinance.git@feature/cookie-and-crumb directly into PyCharm via package manager, after putting a GitHub user credentials into PyCharm settings. All .info 404 issues now fixed (UK user).

(I know this is the computer equivalent of using a crayon for all of you, but might be useful to people like myself who use yfinance as finance nerds rather than IT nerds. Delete if not helpful.)

Thanks to everyone who sorted!!

A better solution is to install this branch https://github.com/ranaroussi/yfinance/pull/1657

Attached is my full script that is facing this issue. It alwayts has worked for me but now broken past few days or so.

Stock Chart.txt

Very easy. As I said, with my custom class, the problem will be fixed. Here is your modified script and the custom class for yfinance. Please rename both of them from .txt to .py and make sure to keep them in the same directory.

All: I can’t fix all of your scripts, but as I mentioned earlier, if you check this example and read my previous posts, you will realize this is a possible solution to the issue that originated this thread. Many thanks to psychoz971 for creating the base of this custom class. I hope this solution will be incorporated into the next releases of yfinance.

Plot stock Charts - Fixed.txt YourCustomYFinance.txt

I’m not in the US, using this url the info is returned. Perhaps the base_url and ticker.py url need changing.

https://query2.finance.yahoo.com/v7/finance/options/bt-a.l

{“optionChain”:{“result”:[{“underlyingSymbol”:“BT-A.L”,“expirationDates”:[],“strikes”:[],“hasMiniOptions”:false,“quote”:{“language”:“en-US”,“region”:“US”,“quoteType”:“EQUITY”,“typeDisp”:“Equity”,“quoteSourceName”:“Delayed Quote”,“triggerable”:false,“customPriceAlertConfidence”:“LOW”,“currency”:“GBp”,“exchangeTimezoneShortName”:“GMT”,“gmtOffSetMilliseconds”:0,“esgPopulated”:false,“regularMarketChangePercent”:-1.463416,“regularMarketPrice”:111.1,“messageBoardId”:“finmb_171577”,“exchangeTimezoneName”:“Europe/London”,“market”:“gb_market”,“exchange”:“LSE”,“shortName”:“BT GROUP PLC ORD 5P”,“longName”:“BT Group plc”,“marketState”:“POSTPOST”,“tradeable”:false,“cryptoTradeable”:false,“priceHint”:2,“regularMarketChange”:-1.6500015,“regularMarketTime”:1698860724,“regularMarketDayHigh”:113.45,“regularMarketDayRange”:“111.0 - 113.45”,“regularMarketDayLow”:111.0,“regularMarketVolume”:32525515,“regularMarketPreviousClose”:112.75,“bid”:110.1,“ask”:125.0,“bidSize”:0,“askSize”:0,“fullExchangeName”:“LSE”,“financialCurrency”:“GBP”,“regularMarketOpen”:113.1,“averageDailyVolume3Month”:30413774,“averageDailyVolume10Day”:32775872,“fiftyTwoWeekLowChange”:88.118,“fiftyTwoWeekLowChangePercent”:3.8342178,“fiftyTwoWeekRange”:“22.982 - 165.49”,“fiftyTwoWeekHighChange”:-54.390007,“fiftyTwoWeekHighChangePercent”:-0.32866037,“fiftyTwoWeekLow”:22.982,“fiftyTwoWeekHigh”:165.49,“fiftyTwoWeekChangePercent”:-11.741686,“earningsTimestamp”:1698908400,“earningsTimestampStart”:1698908400,“earningsTimestampEnd”:1698908400,“trailingAnnualDividendRate”:0.077,“trailingPE”:5.8473682,“dividendRate”:0.08,“trailingAnnualDividendYield”:6.8292685E-4,“dividendYield”:6.83,“epsTrailingTwelveMonths”:0.19,“epsForward”:18.45,“epsCurrentYear”:18.24,“priceEpsCurrentYear”:6.0910087,“sharesOutstanding”:9943310336,“bookValue”:1.49,“fiftyDayAverage”:115.447,“fiftyDayAverageChange”:-4.347,“fiftyDayAverageChangePercent”:-0.037653644,“twoHundredDayAverage”:131.6465,“twoHundredDayAverageChange”:-20.546501,“twoHundredDayAverageChangePercent”:-0.15607329,“marketCap”:11047018496,“forwardPE”:0.0602168,“priceToBook”:74.56376,“sourceInterval”:15,“exchangeDataDelayedBy”:15,“averageAnalystRating”:“2.4 - Buy”,“firstTradeDateMilliseconds”:583743600000,“symbol”:“BT-A.L”},“options”:[]}],“error”:null}}

I think @zq99 is on to something. His approach works for me. After appending the crumb from a request to: https://query2.finance.yahoo.com/v1/test/getcrumb to this URL: https://query2.finance.yahoo.com/v10/finance/quoteSummary/AAPL?module=summaryDetail&ssl=true&crumb=<crumbfrompreviouscall> I get a valid result. Without having any modifications in /etc/hosts. I should say that I am in the US, but if I use the v6 API and an unmodified hosts file I still get 404 errors.

I have been having a brief look at the code. The ‘quoteSummary’ v6 URL is declared in the module quote.py.

However, when I was looking at the version history of this module, it seems that the original URL was actually pointing to v10 rather than v6.

A change from v10 to v6 was made on Jul 13th with commit 509a109

So maybe there was some kind of issue with the v10 url.

So I followed some crumbs and a reddit user, this is a workaround (not sure if it covers all cases):

Changed line 24 of quote.py BASIC_URL to BASIC_URL = “https://query2.finance.yahoo.com/v8/finance/chart/” And ln 603 & 605 changed result[“quoteSummary”] with result[“chart”] same for result.get(“quoteSummary” for result.get(“chart”

Not sure if it will help using chart instead of quote

I think @zq99 is on to something. His approach works for me. After appending the crumb from a request to: https://query2.finance.yahoo.com/v1/test/getcrumb to this URL: https://query2.finance.yahoo.com/v10/finance/quoteSummary/AAPL?module=summaryDetail&ssl=true&crumb=<crumbfrompreviouscall> I get a valid result. Without having any modifications in /etc/hosts. I should say that I am in the US, but if I use the v6 API and an unmodified hosts file I still get 404 errors.

I might (unfortunately) be able to add some extra complexity to this issue. I’m running automated tests in my github workflows using yfinance, one test which tries and fetch information using the get_info() method on the yf.Ticker object.

This workflow is run on [ubuntu-latest, macos-latest, windows-latest] for Python3.10.x. Interestingly, the tests pass when running on ubuntu and macos, but failing when running on windows.

The request to the following url is getting a 404: https://query2.finance.yahoo.com/v6/finance/quoteSummary/ABB.ST?modules=financialData&modules=quoteType&modules=defaultKeyStatistics&modules=assetProfile&modules=summaryDetail&ssl=true

The runner version are the following:

os version image provisioner fails due to 404
Ubuntu 22.04.3 LTS 20231016.1.0 2.0.312.1 No
macOS 12.6.9 21G726 20230921.1 2.0.312.1 No
Microsoft Windows Server 2022 10.0.20348 Datacenter 20231023.1.0 2.0.312.1 Yes

Link to the entire failing test output due to 404.

Could it be that GitHub’s ubuntu and macOS workers are hosted in the US, whereas the windows worker is hosted in the EU?

Looking forward to follow this issue and hopefully help narrow the problem down 😃

//w

I use yahooquery and for me hardcoding the IP for “query2.finance.yahoo.com” in /etc/hosts works as a temporary solution for my script. @lucas03 using the subdomain is probably better but is there a quick way to fix existing scripts with subdomain as for IP adresses?

I don’t know what you did but it also reduced A LOT the CPU usage for downloading history() and get_info(). Thanks!

Not sure if this is important to anyone else, but I had tried to install the cookie-and-crumb feature branch multiple times, and at one point I was wondering if the updates actually got applied, since pip caches the downloaded packages by default. So, I started to disable the installation cache. I am honestly not sure whether this made a difference for me, but it’s working now. If you suspect this might be a problem for you, you can try this:

pip install git+https://github.com/ranaroussi/yfinance@feature/cookie-and-crumb --no-cache-dir

or, if you use SSH:

pip install git+ssh://git@github.com/ranaroussi/yfinance@feature/cookie-and-crumb --no-cache-dir

This will force pip to download the most recent version from Github.

pip install git+https://github.com/ranaroussi/yfinance@feature/cookie-and-crumb

Didn’t work for me, location: India.

https://github.com/ranaroussi/yfinance/issues/1729#issuecomment-1790830481 (psychoz971 solution) works in Canada. For certainty, and based on other recommendations, I was required to add the following to the start of the YFinance module given by psychoz971 import requests import urllib and edited the yahoo_modules part of the code to include the following (for greater information access, such as company name, etc): yahoo_modules = ("summaryDetail," "financialData," "indexTrend," "quoteType," "assetProfile," "defaultKeyStatistics") Now, can access .info with this new YFinance module (and still can access .fast_info and .get_history_metadata() using the original yfinance module). Really appreciate all the work and expertise that has been offered up to allow this!

I am managing to work around .info no longer working to some extent. From aIl the above activity and proposed workarounds I’m getting the impression that .info isn’t going to be fixed. I am now using fast info and .history.
My question is, I’d like to retrieve quantities like dividend yield, capitalization, PE and target mean. I’m not a sophisticated enough python programmer to use the cookie and crumb related workarounds. Can I get those other quantities in a more straightforward way?

@mykolaz Thank you for this help. I figured out how to get .info to work with the cookies&crumbs fix but can no longer get the .Ticker method and associated .history.

The separate class that was provided only contains the endpoint for .info. If you want to use .history() then you just have to use the standard yfinance provided Ticker class which still works fine for that use case. Until the changes are implemented into the library, what I did (since I don’t have enough knowledge of the codebase to make my own fork / pull request at the moment) is just make two Ticker classes and call history or info appropriately depending on which one I need.

Company name: not that I can see. I’m printing out all the field names (data items) I find below. If PASS then that field wasn’t, for example, of type dict and the field is unaccepted (not in the output).

Company name appears neither in the accepted nor unaccepted values. Not though that isn’t in there somewhere in the API anyway - but not the code as it stands currently. As best I can determine.

[note prabhakaran2812, sanyearng: code needs import requests, urllib]

D:\Projects\QQQ>python yf2.py

d:\projects\qqq\yf2.py(5)<module>() -> test = YFinance2(‘GOOG’) (Pdb) c maxAge priceHint previousClose open dayLow dayHigh regularMarketPreviousClose regularMarketOpen regularMarketDayLow regularMarketDayHigh dividendRate PASS: dividendRate dividendYield PASS: dividendYield exDividendDate PASS: exDividendDate payoutRatio fiveYearAvgDividendYield PASS: fiveYearAvgDividendYield beta trailingPE forwardPE volume regularMarketVolume averageVolume averageVolume10days averageDailyVolume10Day bid ask bidSize askSize marketCap yield PASS: yield ytdReturn PASS: ytdReturn totalAssets PASS: totalAssets expireDate PASS: expireDate strikePrice PASS: strikePrice openInterest PASS: openInterest fiftyTwoWeekLow fiftyTwoWeekHigh priceToSalesTrailing12Months fiftyDayAverage twoHundredDayAverage trailingAnnualDividendRate trailingAnnualDividendYield navPrice PASS: navPrice currency fromCurrency toCurrency lastMarket coinMarketCapLink volume24Hr PASS: volume24Hr volumeAllCurrencies PASS: volumeAllCurrencies circulatingSupply PASS: circulatingSupply algorithm maxSupply PASS: maxSupply startDate PASS: startDate tradeable maxAge priceHint enterpriseValue forwardPE profitMargins floatShares sharesOutstanding sharesShort sharesShortPriorMonth sharesShortPreviousMonthDate dateShortInterest sharesPercentSharesOut heldPercentInsiders heldPercentInstitutions shortRatio shortPercentOfFloat PASS: shortPercentOfFloat beta impliedSharesOutstanding morningStarOverallRating PASS: morningStarOverallRating morningStarRiskRating PASS: morningStarRiskRating category bookValue priceToBook annualReportExpenseRatio PASS: annualReportExpenseRatio ytdReturn PASS: ytdReturn beta3Year PASS: beta3Year totalAssets PASS: totalAssets yield PASS: yield fundFamily fundInceptionDate PASS: fundInceptionDate legalType threeYearAverageReturn PASS: threeYearAverageReturn fiveYearAverageReturn PASS: fiveYearAverageReturn priceToSalesTrailing12Months PASS: priceToSalesTrailing12Months lastFiscalYearEnd nextFiscalYearEnd mostRecentQuarter earningsQuarterlyGrowth revenueQuarterlyGrowth PASS: revenueQuarterlyGrowth netIncomeToCommon trailingEps forwardEps pegRatio lastSplitFactor lastSplitDate enterpriseToRevenue enterpriseToEbitda 52WeekChange SandP52WeekChange lastDividendValue PASS: lastDividendValue lastDividendDate PASS: lastDividendDate lastCapGain PASS: lastCapGain annualHoldingsTurnover PASS: annualHoldingsTurnover maxAge symbol peRatio pegRatio estimates maxAge currentPrice targetHighPrice targetLowPrice targetMeanPrice targetMedianPrice recommendationMean recommendationKey numberOfAnalystOpinions totalCash totalCashPerShare ebitda totalDebt quickRatio currentRatio totalRevenue debtToEquity revenuePerShare returnOnAssets returnOnEquity grossProfits freeCashflow operatingCashflow earningsGrowth revenueGrowth grossMargins ebitdaMargins operatingMargins profitMargins financialCurrency marketCap = {‘raw’: 1601643872256, ‘fmt’: ‘1.6T’, ‘longFmt’: ‘1,601,643,872,256’}

The data is returned using the modified URL …

https://query2.finance.yahoo.com/v7/finance/options/AAPL?modules=financialData&modules=quoteType&modules=defaultKeyStatistics&modules=assetProfile&modules=summaryDetail&ssl=true

Much of the data appears to be similar but there are still some absences. sector industry and news data are all missing and possibly others as well.

Please move fast_info discussion to a separate Issue / Discussion. If what you’re actually talking about is the branch feature/cookie-and-crumb, then post in #1657.

I’m not unhappy, just trying to maintain order, otherwise we get a single thread with 200+ comments of interleaved conversations. That’s a lot to read before replying.

I will lock this for a short while to give people time to read.

yesterday it was working fine with a US VPN, today is not. Locally it is not working either and am based in the US/EAST

The page is genuinely under maintenance I guess https://query2.finance.yahoo.com/v6/finance/quoteSummary/AAPL?modules=financialData&modules=quoteType&modules=defaultKeyStatistics&modules=assetProfile&modules=summaryDetail&ssl=true

In my case using threads=False partially solves it

can you explain more It is a yfinace option(yd.download(share, threads=False))

same issue but when i open USA vpn it works

For reference some of the methods still working: .history .fast_info .news .earnings_dates .history_metadata .option_chain

A great way to express gratitude is contributing to project. There’s a dozen abandoned incomplete Pull Requests, and some Issues that need fixing.

Agreed @antonior the process is more performant. @ValueRaider and everyone, excellent progress, great work!

For the kind of programmers like me (not really experienced and patient) , to fix it I needed to remove the old installation of yfinance (the same version) then do #1729 (comment)

This worked for me as well. Uninstalled yfinance, and did the steps in the comments. Restarted my jupyter notebook in between steps

Francemur, Thank Youso much! It works like a charm. Much appreciated for eceryone’s assistance and the community as a whole

Could there be a bug that will cause new on missing attributes clear when trying to clear cookies session. In the code data.py under yfinance.

The part of the init constructor where _session is set: self._session = session or requests Fix: self._session = session or requests.Session()

@Breezeman69

… finance.yahoo.com/v6/finance …

Why v6? v6 is broken, none of the solutions use it, as this thread thoroughly explains.

@Breezeman69 First, use my custom class. Copy the code I provided in one of my previous posts, save it as a.py file and name it as “YourCustomYFinance.py” Put the file in the very same directory of your .py script. Then you also have to edit your original .py script to make sure it will be using the customized class.

For instance, if in your original script you had:

import yfinance as yf import pandas as pd from datetime import datetime, timedelta, timezone

You should replace it with this at the beginning of your script:

import requests import pandas as pd from datetime import datetime, timedelta, timezone import urllib.parse # Add this import statement from YourCustomYFinance import YFinance # Import your custom YFinance class

Hope this helps…

/vote /vote I’m using my version which is working perfectly (https://github.com/ranaroussi/yfinance/issues/1729#issuecomment-1795344783) Thank you all for your help, especially psychoz971 https://github.com/ranaroussi/yfinance/issues/1729#issuecomment-1790830481 , I’ve just added some more stuff to his great work.

I use .history

Is there a fix for EU?

Here is a version that includes History:
import requests
import yfinance as yf
import urllib.parse  # Add this import statement

class YFinance:
    user_agent_key = "User-Agent"
    user_agent_value = ("Mozilla/5.0 (Windows NT 6.1; Win64; x64) "
                        "AppleWebKit/537.36 (KHTML, like Gecko) "
                        "Chrome/58.0.3029.110 Safari/537.36")

    def __init__(self, ticker):
        self.yahoo_ticker = ticker

    def __str__(self):
        return self.yahoo_ticker

    def _get_yahoo_cookie(self):
        cookie = None
        headers = {self.user_agent_key: self.user_agent_value}
        response = requests.get("https://fc.yahoo.com",
                                headers=headers,
                                allow_redirects=True)

        if not response.cookies:
            raise Exception("Failed to obtain Yahoo auth cookie.")

        cookie = list(response.cookies)[0]

        return cookie

    def _get_yahoo_crumb(self, cookie):
        crumb = None
        headers = {self.user_agent_key: self.user_agent_value}
        crumb_response = requests.get(
            "https://query1.finance.yahoo.com/v1/test/getcrumb",
            headers=headers,
            cookies={cookie.name: cookie.value},
            allow_redirects=True,
        )
        crumb = crumb_response.text

        if crumb is None:
            raise Exception("Failed to retrieve Yahoo crumb.")

        return crumb

    def get_history(self, period="max"):
        # Obtain cookies and crumb for downloading historical data
        cookie = self._get_yahoo_cookie()
        crumb = self._get_yahoo_crumb(cookie)

        # Fetch historical stock data using yfinance
        stock = yf.Ticker(self.yahoo_ticker)
        return stock.history(period=period)

    @property
    def info(self):
        cookie = self._get_yahoo_cookie()
        crumb = self._get_yahoo_crumb(cookie)
        info = {}
        ret = {}

        headers = {self.user_agent_key: self.user_agent_value}

        yahoo_modules = ("summaryDetail,"
                         "financialData,"
                         "quoteType,"
                         "assetProfile,"
                         "indexTrend,"
                         "defaultKeyStatistics")

        url = ("https://query1.finance.yahoo.com/v10/finance/"
               f"quoteSummary/{self.yahoo_ticker}"
               f"?modules={urllib.parse.quote_plus(yahoo_modules)}"  # Use urllib.parse.quote_plus
               f"&ssl=true&crumb={urllib.parse.quote_plus(crumb)}")  # Use urllib.parse.quote_plus

        info_response = requests.get(url,
                                     headers=headers,
                                     cookies={cookie.name: cookie.value},
                                     allow_redirects=True)

        info = info_response.json()
        info = info['quoteSummary']['result'][0]

        for mainKeys in info.keys():
            for key in info[mainKeys].keys():
                if isinstance(info[mainKeys][key], dict):
                    try:
                        ret[key] = info[mainKeys][key]['raw']
                    except (KeyError, TypeError):
                        pass
                else:
                    ret[key] = info[mainKeys][key]

        return ret

Names, both long and short, seem to be in there now with the change above.

        yahoo_modules = ("financialData,"
                         "quoteType,"
                         "defaultKeyStatistics,"
                         "assetProfile,"
                         "summaryDetail")

I’m trying to implement @psychoz971 YFinance class. Can somebody post a short example of some main program code that uses this?

Just grab the main function from the Class and modify for out-of-class usage.

`USER_AGENT = ‘User-Agent’ USER_AGENT_VALUE = ("Mozilla/5.0 (Windows NT 6.1; Win64; x64) " "AppleWebKit/537.36 (KHTML, like Gecko) " “Chrome/58.0.3029.110 Safari/537.36”)

def _get_yahoo_cookie():

 cookie = None

 headers = {USER_AGENT : USER_AGENT_VALUE}
 response = requests.get("https://fc.yahoo.com",
                            headers=headers,
                            allow_redirects=True)
 
 if not response.cookies:

      raise Exception("Failed to obtain Yahoo auth cookie.")

 cookie = list(response.cookies)[0]

 print ('Obtained cookie')

 return cookie

def _get_yahoo_crumb(cookie):

 crumb = None

 headers = {USER_AGENT: USER_AGENT_VALUE}

 crumb_response = requests.get(
        "https://query1.finance.yahoo.com/v1/test/getcrumb",
        headers=headers,
        cookies={cookie.name: cookie.value},
        allow_redirects=True,
    )

 crumb = crumb_response.text

 if crumb is None:

      raise Exception("Failed to get Yahoo crumb.")
 
 return crumb`

Or you can just use the class

client = YFinance('AAPL').info

@psychoz971 Works like a charm, Thank you. To the yfinance admins, if there is an option to say manipulate the BASE URL / URL constructs it will be great.

@prabhakaran2812 if you need it I think you can add new properties base_urland cookie_url and replace it in the YFinance class.

Hi @ValueRaider @psychoz971, thank you both for your amazing work!

I have created a PR that integrates both of your solutions. It should be able to fairly reliably get the info data.

yesterday it was working fine with a US VPN, today is not. Locally it is not working either and am based in the US/EAST

The page is genuinely under maintenance I guess https://query2.finance.yahoo.com/v6/finance/quoteSummary/AAPL?modules=financialData&modules=quoteType&modules=defaultKeyStatistics&modules=assetProfile&modules=summaryDetail&ssl=true

That message is the same as 10 days ago.

The data is returned using the modified URL …

https://query2.finance.yahoo.com/v7/finance/options/AAPL?modules=financialData&modules=quoteType&modules=defaultKeyStatistics&modules=assetProfile&modules=summaryDetail&ssl=true

https://imgur.com/a/YVJNyGQ

For a while VPNing outside the US worked. No longer. I’d guess that they’re not going to be right back.

I’ve same issue in colab. When I try delete runtime and reconnect multiple times, it works. Its very random, should be based on IP I guess.

Try running on Google colab it works for me but still it is not working on local environment. Bit weird 🤔

In my case, it’s the exact opposite. It works locally but doesn’t work on Colab

@bot-unit What symbol did you test crumbs on, and where are you? I am in Europe. https://github.com/ranaroussi/yfinance/issues/1729#issuecomment-1775575210 I get more fails than successes, either with your crumb fetch or mine #1657.

edit: retracting my investigation, smells like a bug

@lukas How did you find the e1.ycpi.vip.dca.yahoo.com subdomain?

I’m using PIA VPN and the only one that works for me is US Houston (191.96.67.107).

That works on my desktop, but my code is running on a server in the DMZ, so can’t fix it with VPN.

hmm, interesting. What about this?

curl -v -k -H "Host: query2.finance.yahoo.com" 'https://e1.ycpi.vip.dca.yahoo.com/v6/finance/quoteSummary/SPY?modules=financialData&modules=quoteType&modules=defaultKeyStatistics&modules=assetProfile&modules=summaryDetail&ssl=true'

both this curl & the one with the IP work for me from the UK

I am not really into programming at this level but i think the answers is understanding why it works with an american IP…

Because Yahoo is banning not-American IP ˆ)

Right now I am trying with this american VPN ip 143.244.44.169 and I am getting 404. =)

I’m using Browsec VPN. Using my Australian IP: 404 Using Browsec German VPN: 404 Using Browsec US VPN: I get results. Using Browsec US (west) VPN: 404.

hmm, interesting. What about this?

curl -v -k -H "Host: query2.finance.yahoo.com" 'https://e1.ycpi.vip.dca.yahoo.com/v6/finance/quoteSummary/SPY?modules=financialData&modules=quoteType&modules=defaultKeyStatistics&modules=assetProfile&modules=summaryDetail&ssl=true'

I am not really into programming at this level but i think the answers is understanding why it works with an american IP…

Because Yahoo is banning not-American IP ˆ)

In my case using threads=False partially solves it

Firefox -> https://finance.yahoo.com/quote/AMZN -> F12 -> Network tab -> F5 -> compare requests vs yfinance That’s essence of how to find fix.