18

For the past few years, I've been using the following link to fetch a full current quote for the symbols in the query:

https://query1.finance.yahoo.com/v7/finance/quote?symbols=AAPL

All of a sudden, as of about 5 hours ago, I'm now getting the error response 'Unauthorised - Invalid Cookie' on every single device I call it from. Sometimes, I get the error response 'Unauthorised - Invalid Crumb'.

The historic data fetching still works fine:

(https://query1.finance.yahoo.com/v8/finance/chart/AAPL?metrics=high?&interval=1d&range=5d).

Is anyone else having this issue and/or knows how I can fix it??? Or have Yahoo discontinued this endpoint without telling anyone??

Biff Downhill
  • 245
  • 2
  • 10
  • I am having the same problem with the quotes query (also since yesterday). Searching for tickers still works, though: https://query1.finance.yahoo.com/v1/finance/search?q=AAPL – gbroekstg Apr 20 '23 at 11:07
  • Even Alfian Losari's fantastic StocksApp tutorial has the same problem: https://github.com/alfianlosari/stocksapptutorial – gbroekstg Apr 20 '23 at 11:17
  • It seems the original link is working again.. Can anyone confirm this too? – Justin Apr 20 '23 at 15:26

9 Answers9

15

I had the same issue today. Change the "v7" to "v6" in the URL in your GET request. It will then work, at least for now. Because the Yahoo Finance API hasn't been officially supported since 2017, we do what we can with it.

JollyPotato
  • 174
  • 1
  • 4
  • I've only been trying versions greater than v7! Thank you so much, absolute hero – Biff Downhill Apr 20 '23 at 14:08
  • 1
    v6 is still working, I had to also include the following header though: "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/112.0" – redspidermkv May 12 '23 at 13:53
  • 2
    I ran into the same issue +/- the same date. To solve the problem, I tried the crumb and cookie stuff but failed to retrieve the cookie via VBA (crumb was fine). I finally found the solution mentioned by switching to v6. However... since 2 days I get as return: {"finance":{"result":null,"error":{"code":"Not Found","description":"HTTP 404 Not Found"}}}. Any other ideas how to get the data retrieval working again? Or (in the light of the post below), does anyone know where to find a detailed manual for using the Google Finance API instead (as I actually don't care where the data comes from)? – Ultra Junkie May 26 '23 at 05:59
  • 1
    Oof... going from `v7` to `v6` worked for a month or so, for me. Now neither works. v7 returns *"Invalid Crumb"* and v6 returns *"Not found"*. – Bram Jun 08 '23 at 21:24
  • 1
    v10 used to work until about last month. Not any longer – FredrikD Jul 18 '23 at 14:43
  • The v6 API returns not found and is no longer supported. – nordic70 Aug 08 '23 at 06:04
9

that might explain why it isn't working anymore!

enter image description here

emoreau99
  • 634
  • 6
  • 16
  • 1
    Thank you for this, where and when did you see this message? The API has certainly stopped working completely now for a couple of days. – JollyPotato May 26 '23 at 06:29
  • I have found and tested a library yesterday that is working: https://github.com/karlwancl/YahooFinanceApi/tree/14b6c587d94ebe551f11f44c6b954d64285b831c. Be sure to use the pull request 55 which contains the fix. – emoreau99 May 27 '23 at 09:43
  • Yes, what is the source of the API Feedback message? – FredrikD Jul 18 '23 at 16:15
6

I came across the same problem and switched to using the https://query1.finance.yahoo.com/v8/finance/chart/{ticker} endpoint which seems to work. The response format is slightly different but seems to contain similar information.

E.g. to get the current price:

Old endpoint: quoteResponse.result[0].regularMarketPrice

New endpoint: chart.result[0].meta.regularMarketPrice

bugflux
  • 123
  • 1
  • 6
  • 1
    Confirmed this endpoint is working. Doesn't seem to return as much metadata but at least you get currency and the exchange. – davidf2281 May 30 '23 at 16:37
4

If you try to go to a quote api endpoint such as: https://query2.finance.yahoo.com/v7/finance/quote?symbols=AAL

You end up getting this: {"finance":{"result":null,"error":{"code":"Unauthorized","description":"Invalid Crumb. For Developers - https://docs.google.com/forms/d/e/1FAIpQLSeyb7xMtZFjoNYI7XG1rjlhUopKAxdLAfSRcaPxg9p-9ii-_g/viewform?fbzx=-7189957683680596558"}}} (i replaced the bitly link for posting)

Yahoo Finance | API Feedback

Where they explain how they've disabled access to quote data.

The v6 endpoint was killed off entirely.

TheKrush
  • 81
  • 1
  • 6
2

I just checked and v7 is now working again.

papa_k
  • 21
  • 1
  • 3
    As of yesterday and today, v7 is failing again. But I just stumbled upon this post, and v6 works. Yeehaw! – Ben Kennedy May 06 '23 at 18:20
  • 4
    according to a non-answer posted as ananswer, v7 and v6 are failing today. – starball May 24 '23 at 06:07
  • Today (May 26, 2023 8am CEST), neither v6 nor v7 is working. v6 returns 404 not found, v7 returns "invalid cookie". – Ultra Junkie May 26 '23 at 06:09
  • This one still works: "https://query1.finance.yahoo.com/v11/finance/quoteSummary/" & sShare & "?modules=financialData" but it retrieves a lot of data I am not at all interested in, and I can't query all symbols together. – Ultra Junkie May 26 '23 at 06:16
  • I have found and tested a library yesterday that is working: github.com/karlwancl/YahooFinanceApi/tree/…. Be sure to use the pull request 55 which contains the fix. – emoreau99 May 27 '23 at 09:44
1

The only option that I've found is to use a different service. I have a paid subscription to Financial Modeling Plus (https://site.financialmodelingprep.com/developer/docs/pricing/)

They have a free tier that provides 250 quotes a day. That might be adequate for some people that only want daily updates for their portfolio.

rabinnh
  • 178
  • 1
  • 8
  • Great suggestion. I looked at their specs, seems better than the Yahoo. Also, in the long run, it is more sustainable to pay for the access – FredrikD Jul 18 '23 at 14:52
  • In my experience Yahoo has better data quality at least for European stocks. – nordic70 Aug 08 '23 at 04:48
1

An alternative I found on https://cryptocointracker.com/yahoo-finance/yahoo-finance-api#26cc3f3f62db4567857919c2653fab33 is to use https://query1.finance.yahoo.com/v7/finance/options/{symbol}
It has quote value-pair containing:

{
   "quote":{
      "language":"en-US",
      "region":"US",
      "quoteType":"EQUITY",
      "typeDisp":"Equity",
      "quoteSourceName":"Delayed Quote",
      "triggerable":true,
      "customPriceAlertConfidence":"HIGH",
      "exchange":"NMS",
      "currency":"USD",
      "earningsTimestamp":1691092800,
      "earningsTimestampStart":1691092800,
      "earningsTimestampEnd":1691092800,
      "trailingAnnualDividendRate":0.92,
      "trailingPE":32.131535,
      "dividendRate":0.96,
      "trailingAnnualDividendYield":0.004847974,
      "dividendYield":0.51,
      "epsTrailingTwelveMonths":5.93,
      "epsForward":6.58,
      "epsCurrentYear":5.98,
      "priceEpsCurrentYear":31.862875,
      "sharesOutstanding":15728700416,
      "bookValue":3.953,
      "fiftyDayAverage":180.4268,
      "fiftyDayAverageChange":10.11319,
      "fiftyDayAverageChangePercent":0.05605148,
      "twoHundredDayAverage":156.0571,
      "twoHundredDayAverageChange":34.482895,
      "marketCap":2996946599936,
      "twoHundredDayAverageChangePercent":0.22096333,
      "forwardPE":28.957447,
      "priceToBook":48.201363,
      "sourceInterval":15,
      "exchangeDataDelayedBy":0,
      "averageAnalystRating":"2.0 - Buy",
      "shortName":"Apple Inc.",
      "longName":"Apple Inc.",
      "messageBoardId":"finmb_24937",
      "exchangeTimezoneName":"America/New_York",
      "exchangeTimezoneShortName":"EDT",
      "gmtOffSetMilliseconds":-14400000,
      "market":"us_market",
      "esgPopulated":false,
      "marketState":"POSTPOST",
      "regularMarketChangePercent":0.40574852,
      "regularMarketPrice":190.54,
      "tradeable":false,
      "cryptoTradeable":false,
      "firstTradeDateMilliseconds":345479400000,
      "priceHint":2,
      "postMarketChangePercent":-0.11545396,
      "postMarketTime":1689292799,
      "postMarketPrice":190.32,
      "postMarketChange":-0.21998596,
      "regularMarketChange":0.769989,
      "regularMarketTime":1689278404,
      "regularMarketDayHigh":191.19,
      "regularMarketDayRange":"189.78 - 191.19",
      "regularMarketDayLow":189.78,
      "regularMarketVolume":38321242,
      "regularMarketPreviousClose":189.77,
      "bid":190.34,
      "ask":190.38,
      "bidSize":10,
      "askSize":10,
      "fullExchangeName":"NasdaqGS",
      "financialCurrency":"USD",
      "regularMarketOpen":190.5,
      "averageDailyVolume3Month":56677663,
      "averageDailyVolume10Day":51027070,
      "fiftyTwoWeekLowChange":66.369995,
      "fiftyTwoWeekLowChangePercent":0.5345091,
      "fiftyTwoWeekRange":"124.17 - 194.48",
      "fiftyTwoWeekHighChange":-3.9400024,
      "fiftyTwoWeekHighChangePercent":-0.020259166,
      "fiftyTwoWeekLow":124.17,
      "fiftyTwoWeekHigh":194.48,
      "fiftyTwoWeekChangePercent":26.882862,
      "dividendDate":1684368000,
      "displayName":"Apple",
      "symbol":"AAPL"
   }
}
Nathan
  • 449
  • 1
  • 7
  • 23
  • You never know when the end-point is no longer working as I have experience on the two of their APIs. – vic Jul 18 '23 at 03:30
0

This is my working version that I am using it in a .Net 7 API project. I've solved the problem with the cookie and crumb by keeping them in cache and I have a sync/retry mechanism when the cache expires. This works well for 1 server instance but for scale situation it should be rethink. This is using Yahoo V10 without problems. There is no requests limiter here but I advise you to use one. In my case I have something build in UI (not very efficient, but is good enough for my case).

using Microsoft.Extensions.Caching.Memory;
using System.Net;

namespace WorkbenchAPI.Features.ServiceDelivery.StockMarket.SymbolsParsers
{
   public class YahooManager
   {
    private static readonly object yahooCredentialsLocker = new object();

    private const string STOCK_MARKET_URL_SUMMARY = "https://query1.finance.yahoo.com/v10/finance/quoteSummary/{0}?formatted=true&lang=en-US&region=US&modules=assetProfile%2CbalanceSheetHistory%2CbalanceSheetHistoryQuarterly%2CcalendarEvents%2CcashflowStatementHistory%2CcashflowStatementHistoryQuarterly%2CdefaultKeyStatistics%2Cearnings%2CearningsHistory%2CearningsTrend%2CesgScores%2CfinancialData%2CfundOwnership%2CincomeStatementHistory%2CincomeStatementHistoryQuarterly%2CindexTrend%2CindustryTrend%2CinsiderHolders%2CinsiderTransactions%2CinstitutionOwnership%2CmajorDirectHolders%2CmajorHoldersBreakdown%2CnetSharePurchaseActivity%2Cprice%2CrecommendationTrend%2CsecFilings%2CsectorTrend%2CsummaryDetail%2CsummaryProfile%2CupgradeDowngradeHistory%2Cpageviews%2Cquotetype&ssl=true";

    private const string YahooFcUrl = "https://fc.yahoo.com";
    private const string YahooGetCrumbUrl = "https://query2.finance.yahoo.com/v1/test/getcrumb";
    private const string CacheKeyCookieContainer = "YahooCookieContainer";
    private const string CacheKeyCrumb = "YahooCrumb";

    private readonly IHttpClientFactory _httpClientFactory;
    private readonly IMemoryCache _memCache;

    public YahooManager(IHttpClientFactory httpClientFactory, IMemoryCache memCache)
    {
        _httpClientFactory = httpClientFactory;
        _memCache = memCache;
    }


    public async Task<string> GetYahooSymbolSummay(string symbol)
    {
        return await WebRequestGet(string.Format(STOCK_MARKET_URL_SUMMARY, symbol));
    }

    public async Task<string> WebRequestGet(string url)
    {
        (CookieContainer cookie, string crumb) credentials = new(null, null);
        lock (yahooCredentialsLocker)
        {
            int tryCounter = 0;
            while ((credentials.crumb == null || credentials.cookie == null) && tryCounter < 10)
            {
                Task.Delay(1000 * tryCounter).Wait();
                credentials = GetYahooCookie().ConfigureAwait(false).GetAwaiter().GetResult();
                tryCounter++;
            }//while
        }//lock

        string sAgent = $"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36";
        var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, url + "&crumb=" + credentials.crumb)
        {
            Headers =
                        {
                            { "Cookie",  credentials.cookie.GetCookieHeader(new Uri(YahooFcUrl))},
                            { "User-Agent",sAgent }
                        }
        };
        var httpClient = _httpClientFactory.CreateClient();
        var webResponse = await httpClient.SendAsync(httpRequestMessage);
        //webResponse.EnsureSuccessStatusCode();
        string responseContent = await webResponse.Content.ReadAsStringAsync();
        return responseContent;
    }//WebRequestGet

    private async Task<(CookieContainer cookie, string crumb)> GetYahooCookie()
    {
        CookieContainer m_cookieContainer = null;
        string m_crumb = null;
        _memCache.TryGetValue(CacheKeyCookieContainer, out m_cookieContainer);
        _memCache.TryGetValue(CacheKeyCrumb, out m_crumb);

        if (m_cookieContainer == null || m_crumb == null)
        {               
            string sAgent = $"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36";

            m_cookieContainer = new CookieContainer();
            var uri = new Uri(YahooFcUrl);
            var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, YahooFcUrl)
            {
                Headers =
                        {
                            { "User-Agent", sAgent }
                        }
            };
            var httpClient = _httpClientFactory.CreateClient();
            var httpResponseMessage = await httpClient.SendAsync(httpRequestMessage);
            IEnumerable<string> cookies;
            httpResponseMessage.Headers.TryGetValues("Set-Cookie", out cookies);
            if (cookies == null)                                    
                return (null, null);
            
            foreach (var cookieValue in cookies)
                m_cookieContainer.SetCookies(uri, cookieValue);
            httpResponseMessage.Dispose();

            httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, YahooGetCrumbUrl)
            {
                Headers =
                        {
                            { "Cookie",  m_cookieContainer.GetCookieHeader(uri) },
                            { "User-Agent",sAgent}
                        }
            };
            httpClient = _httpClientFactory.CreateClient();
            var crumbResponse = await httpClient.SendAsync(httpRequestMessage);
            crumbResponse.EnsureSuccessStatusCode();
            string responseContent = await crumbResponse.Content.ReadAsStringAsync();
            m_crumb = responseContent.Trim('"');

            var cacheEntryOptions = new MemoryCacheEntryOptions()
                .SetSlidingExpiration(TimeSpan.FromSeconds(60*5))
                .SetAbsoluteExpiration(TimeSpan.FromSeconds(60*10))
                .SetPriority(CacheItemPriority.Normal);
            _memCache.Set(CacheKeyCookieContainer, m_cookieContainer, cacheEntryOptions);
            _memCache.Set(CacheKeyCrumb, m_crumb, cacheEntryOptions);
        }//endif
        return (m_cookieContainer, m_crumb);
    }//GetYahooCookie


  }
}
D A
  • 1,724
  • 1
  • 8
  • 19
-1

I suspect there are some rate limiting at work. If you are making too many calls too quickly, the endpoint will treat the caller as an automated program instead of a human users. I started getting a lot of Unauthorized after calling one of the endpoints a few thousand times. Tried again after a few minutes and the request went through.

dayfine
  • 27
  • 1
  • 4
  • This is not rate limiting related. The error is related to Yahoo Finance aiming to stop illegal API usage and requesting feedback on the intended API usage. – nordic70 Aug 08 '23 at 06:08