Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

API calls returning 'Invalid Cookie' #203

Open
benhowell opened this issue Jul 13, 2023 · 106 comments
Open

API calls returning 'Invalid Cookie' #203

benhowell opened this issue Jul 13, 2023 · 106 comments

Comments

@benhowell
Copy link

Describe the bug
API calls returning 'Invalid Cookie'

To Reproduce

from yahooquery import Ticker
aapl = Ticker('aapl')
x = aapl.price
print(x)
{'aapl': 'Invalid Cookie'}

Desktop (please complete the following information):

  • OS: Linux
  • Browser: None
  • Version 2.3.1
@o-oayda
Copy link

o-oayda commented Jul 13, 2023

I can confirm I have the same issue (macOS 13.4.1, Python 3.9.10 and yahooquery 2.3.1).

@EmirEgilli
Copy link

image

Looks about the same with me as well. Didn't have this issue yesterday. Also made sure that yahooquery is up-to-date (2.3.1).

@jfreidkes
Copy link

Same here both in Linux and macOS, every ticker returns Invalid Cookie

@staper1960
Copy link

Same here too. Yesterday it was fine. However, the day before yesterday, yahooquery was very unstable. Sometimes it returned correct results, sometimes no attributes were returned. The whole yahoo service is becoming unreliable. Any suggestions?

@weiguang-zz
Copy link

same result for me

@james-stevens
Copy link

same, here's the smallest code I have to reproduce

#! /usr/bin/python3

import json

from yahooquery import Ticker

tickers = Ticker(["JD.L","TSLA"])
print(json.dumps(tickers.price,indent=3))

this outputs

{
   "JD.L": "Invalid Cookie",
   "TSLA": "Invalid Cookie"
}

Seemed ok till about 8pm UTC

@dpguthrie
Copy link
Owner

dpguthrie commented Jul 13, 2023

Looks like it's back, at least using the examples from above. Curious if you're all seeing that now? Pretty disconcerting though nonetheless as it appears they're most likely phasing these APIs out for requests without proper cookies set by the browser. I could come up with a workaround but it would most likely require selenium, which is less than ideal.

image

@b3niup
Copy link

b3niup commented Jul 13, 2023

Unfortunately it still doesn't work for me - even same example as above.

@staper1960
Copy link

Still not working for me either. I have a long list of queries on various stocks and it returns the "invalid cookie" message to the very first one.

@jirisarri10
Copy link

Hello. I just tried to connect and I also get the error "Invalid Cookie" . I have linux 6.1, python 3.11.3 and yahooquery 2.3.1. I think it is a general bug in yahoo service. I await further news. I really appreciate your project and dedication.

imagen

@staper1960
Copy link

staper1960 commented Jul 13, 2023

python 3.7, yahooquery 2.3.1, no browser, windows 11 here. Location: Greece.

@ValueRaider
Copy link

ValueRaider commented Jul 13, 2023

Given code works for @dpguthrie, I think it will be helpful if everyone adds their location to their report. Maybe Yahoo is slowly rolling out across globe. Just edit your post, don't spam the thread.

Me: UK, Invalid Cookie, Linux & everything up-to-date

@tretus222
Copy link

Same issue since yesterday (but yesterday only 10% of the requests failed)
python 3.9.2, linux, python 3.10.6, macOS, yahooquery 2.3.1, Location: Germany.

@james-stevens
Copy link

james-stevens commented Jul 13, 2023

Still not working for me too - as before 100% failure since about 8pm yesterday
Python 3.11.3, yq v2.3.1, Alpine Linux v3.18.0, UK

{
   "JD.L": "Invalid Cookie",
   "TSLA": "Invalid Cookie"
}

@kajdo
Copy link

kajdo commented Jul 13, 2023

same for me

Python 3.9.16 - location austria

{
   "JD.L": "Invalid Cookie",
   "TSLA": "Invalid Cookie"
}

I use my account cookie already for requesting other depot data calling yahoo api directly - could I use it for the calls for yahooquery as well

as prev mentioned a selenium impl might not be ideal and a bit of an overkill - I read the cookie out of firefox db and just log in from time to time - its valid for a good number of days

@louisowen6
Copy link

same for me
Python 3.9.0, yq v2.3.1, location Indonesia

{'aapl': 'Invalid Cookie'}

@ValueRaider
Copy link

@kajdo So cookie could be cached, but what about the crumb?

@dpguthrie
Copy link
Owner

dpguthrie commented Jul 13, 2023

Ya, I'm not super stoked on adding selenium either - if anyone has a better idea for getting the appropriate cookies, I'm all ears. I do think that the library itself should be responsible for setting up the request in a way that makes valid requests, which means obtaining cookies and a crumb without intervention from the user. I guess it could certainly be another argument to the Ticker initialization but I'm less enthused about that (but definitely open to the idea if others think it's valuable).

The alternative that I mentioned above is using selenium. I put together a short loom video on what that might look like (it adds a little less than 5 seconds to the Ticker initialization, which isn't terrible). You can see that after I've obtained both cookies and a crumb, I'm now able to hit the quotes endpoint, which is something they recently made unavailable to requests without cookies and/or crumb.

Also, I think using the webdriver-manager package abstracts away the requirement of a user having to download chromedriver themselves, which makes it a little bit easier to stomach.

@kajdo
Copy link

kajdo commented Jul 13, 2023

@kajdo So cookie could be cached, but what about the crumb?

@ValueRaider I messed around with crumb for the api calls ... also with the cookie itself which i see in the dev console in ff / brave

the call i make is basically against "/v7/finance/desktop/portfolio?formatted=true" and i ended up using just
header

  • authority
  • user-agent
  • accept
  • sec-gpc
  • origin
  • sec-fetch-site
  • sec-fetch-mode
  • sec-fetch-dest
  • referer
  • accept-language
  • COOKIE

urlparams:

  • lang
  • region
  • userId
  • pfIds
  • fields
  • corsDomains

to call the /portfolio endpoint it seems to be fine without crumb

@dpguthrie i do agree that its much better if the library handles it .... to reduce the +5sec the lib could cache/persist it in a .env file and load it via dotenv (https://pypi.org/project/python-dotenv/) or something like that .... so it only gets a new token with the browser-simulation if really needed ...... as mentioned the cookie is valid for days - not sure how long but for my script, i think i have to change it once every 2 weeks max

don't really have a better suggestion .... messed around a bit, but ended up reading it out from ff cookie db because i'm online on yahoo finance anyway often enough to not redo the tocken manually

@manuelwithbmw
Copy link

manuelwithbmw commented Jul 13, 2023

Me since today 13th July:
UK, Invalid Cookie, Python 3.8, Mac OS Mohave 10.14.6, yfinance version: 0.2.22, yahooquery version: 2.3.0

@jirisarri10
Copy link

It appears that the Yahooquery library attempts to access the Yahoo Finance API using authentication cookies. However, Yahoo Finance has made changes to its API, and it's possible that the authentication cookies are no longer valid or need to be updated.

@staper1960
Copy link

We are still in the dark it seems. Sorry I don't have the necessary skills to contribute to the discussion, but I sincerely hope that we will soon have a practical solution accompanied by a comprehensive explanation and we can return to our trading habits. I wish to thank Doug in advance for his superb work and his commitment to yahooquery.

@KenLee12323
Copy link

KenLee12323 commented Jul 13, 2023

just encountered this issue. utc+8.

From yfinance repo, users are also discussing this issue. Some said that "A1 and the crumb URL parameter" are needed at least for the call. I don't know how to get the crumb and cookie through python without additional libraries or tools. I would be really appreciate if anyone could give me some hints.

ps. I notice the 'https://dpguthrie-yahooquery-streamlit-app-eydpjo.streamlit.app/' website still works. I am not sure how can it still work if it is using yahooquery's api? Would anyone mind giving me some hints?

I think selenium is the right choice to adopt since yahoo is making it harder and harder for programmatic crawling. Finally, we will reach a point where crawling with a fake browser is the only choice.

Thanks a lot for the work!

**the request response now changed from 401 to 404. Also, the 'https://dpguthrie-yahooquery-streamlit-app-eydpjo.streamlit.app/' website starts getting 'invalid cookies' respond now.

@cmjordan42
Copy link

If they are rolling out the breaking change regionally, it hit EST / UTC-5 sometime between ~18:00 and ~21:00 UTC-5

I was manually running a job which I halted at 17:40 UTC-5 - upon just resuming to finish the job at 21:00 UTC-5 I now encounter this error.

@Keepcase
Copy link

I just started seeing this error today as well.

@Musa830
Copy link

Musa830 commented Jul 14, 2023

Is this error unsolvable?

@galashour
Copy link

Same issue (Israel, Python 3.11)

@jirisarri10
Copy link

import yahooquery
tub=yahooquery.Ticker("TUB.MC")
historial = tub.history(period="1d")
print (historial)
open high low close volume adjclose
symbol date
TUB.MC 2023-07-14 11:27:47+02:00 2.89 2.94 2.89 2.93 21885 2.93
tub.price
{'TUB.MC': 'Invalid Cookie'}

If you ask history it works perfectly!! But if you ask for price "Invalid Cookie".

@Musa830
Copy link

Musa830 commented Jul 14, 2023

I think this is a very unstable way of getting data. After the try is triggered, you can add the code of yfinance to the exception, so that the data can still be obtained when the exception occurs. This may require code changes, but will not delay daily backtesting.

@kajdo
Copy link

kajdo commented Jul 14, 2023

@dpguthrie maybe a crazy idea - but what if we could make the login process work with mechanize (https://mechanize.readthedocs.io/en/latest/) ... the benefit would be that no seperate browser is needed and it would run on a vps without desktop environment as well

something like:

import mechanize

# Create a browser instance
browser = mechanize.Browser()

# Open the login URL
login_url = 'https://login.yahoo.com/?done=https%3A%2F%2Fwww.yahoo.com%2F&add=1'
response = browser.open(login_url)

# Read the HTML response and decode it as a string
html = response.read().decode('utf-8')

# Find the login form with id="login-username-form"
forms = [form for form in browser.forms() if form.attrs.get('id') == 'login-username-form']
if forms:
    # Select the first form found
    form = forms[0]

    # Find the username input field
    username_field = form.find_control('username')
    if username_field:
        # Assign the value to the username input field
        username_field.value = 'USERNAME'

        # Find the submit button and directly submit the form
        submit_button = form.find_control(id='login-signin', type='submit')
        if submit_button:
            browser.form = form  # Set the form explicitly
            try:
                browser.submit()
                # Print the current URL after submitting the form
                print("Current URL:", browser.geturl())
            except mechanize.HTTPError as e:
                print(f"Failed to submit the form: {e.code} {e.msg}")
            except mechanize.URLError as e:
                print(f"Failed to submit the form: {e.reason}")
        else:
            print("The submit button was not found in the form.")
    else:
        print("The username input field was not found in the form.")
else:
    print("The form with id='login-username-form' was not found in the HTML.")

# Close the browser
browser.close()

just as an example ... it still ends up in Failed to submit the form: 403 b'request disallowed by robots.txt', but i guess i'd need to add more parameters to the form to make it work correct

@mickdewald
Copy link

mickdewald commented Jul 17, 2023

@lunarbase-ai
Copy link

lunarbase-ai commented Jul 18, 2023

A temporary (or permanent - not sure yet) alternative:

import requests
def legacy_finance_extract(symbol: str, modules: Optional[List[str]] = None):
        legacy_base_url = "https://query2.finance.yahoo.com/v6/finance/quoteSummary"
        modules_url = "&".join([f"modules={m}" for m in modules])
        extract_url = f"{legacy_base_url}/{symbol}?{modules_url}"
        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/110.0",
        }
        resp = requests.get(extract_url, headers=headers)
        data = resp.json() if resp.status_code == 200 else dict()
        return data

The available modules can be found in yahooquery.Ticker._CONFIG["quoteSummary"]["query"]["modules"]["options"]
I hope this is helpful!

@dpguthrie
Copy link
Owner

dpguthrie commented Jul 18, 2023

Working on a new fix right now that doesn't require selenium. You can test by installing from the feat/set-cookie-and-crumb branch directly. Also, the code is running (and working) on the streamlit app as well for you to test out.

@ms82494
Copy link

ms82494 commented Jul 18, 2023

I did pip install git+https://github.com/dpguthrie/yahooquery.git@feat/set-cookie-and-crumb, but still sometimes got error message Invalid credentials provided. Please check username and password and try again when trying to create a Research object.

To figure out what's going on I created an interactive selenium session and found that Yahoo! now uses occasional recaptcha challenges before the userid prompt, or before the password prompt.

@maread99
Copy link
Contributor

Just wanted to say how great it is to see such wide community participation in trying to get a timely stable resolution to all this.

A huge thank you to @dpguthrie and all those here who are contributing ideas.

@mickdewald
Copy link

Working on a new fix right now that doesn't require selenium. You can test by installing from the feat/set-cookie-and-crumb branch directly. Also, the code is running (and working) on the streamlit app as well for you to test out.

The link to the streamlit app on https://yahooquery.dpguthrie.com/ is https://share.streamlit.io/app/dpguthrie-yahooquery-streamlit-app-eydpjo/ which is broken:
Screenshot 2023-07-19 170309

@dpguthrie
Copy link
Owner

@micktg I can update the docs site. The README has been updated with the appropriate URL

Go here - https://yahooquery.streamlit.app

@cmjordan42
Copy link

Is there a permanent fix for all_modules being empty in mind?

> ticker.summary_detail
{'AAPL': {'maxAge': 1, 'priceHint': 2, 'previousClose': 193.73, 'open': 193.1, 'dayLow': 192.65, 'dayHigh': 198.22, 'regularMarketPreviousClose': 193.73, 'regularMarketOpen': 193.1, 'regularMarketDayLow': 192.65, 'regularMarketDayHigh': 198.22, 'dividendRate': 0.96, 'dividendYield': 0.005, 'exDividendDate': '2023-05-12', 'payoutRatio': 0.1559, 'fiveYearAvgDividendYield': 0.89, 'beta': 1.292349, 'trailingPE': 32.84686, 'forwardPE': 29.552189, 'volume': 57076477, 'regularMarketVolume': 57076477, 'averageVolume': 56698527, 'averageVolume10days': 48782770, 'averageDailyVolume10Day': 48782770, 'bid': 194.87, 'ask': 194.89, 'bidSize': 800, 'askSize': 900, 'marketCap': 3058499321856, 'yield': {}, 'ytdReturn': {}, 'totalAssets': {}, 'expireDate': {}, 'strikePrice': {}, 'openInterest': {}, 'fiftyTwoWeekLow': 124.17, 'fiftyTwoWeekHigh': 198.22, 'priceToSalesTrailing12Months': 7.942194, 'fiftyDayAverage': 181.9594, 'twoHundredDayAverage': 156.6873, 'trailingAnnualDividendRate': 0.92, 'trailingAnnualDividendYield': 0.0047488776, 'navPrice': {}, 'currency': 'USD', 'fromCurrency': None, 'toCurrency': None, 'lastMarket': None, 'coinMarketCapLink': None, 'volume24Hr': {}, 'volumeAllCurrencies': {}, 'circulatingSupply': {}, 'algorithm': None, 'maxSupply': {}, 'startDate': {}, 'tradeable': False}}

> ticker.all_modules
{'AAPL': {}}

I'm trying to avoid swapping it out for an extensive get_modules request as it can only be less efficient, as someone previously noted. But if that's the fix for the foreseeable future, I'll make the change. Although if that's the case, it would probably be better to make that change underneath all_modules so it can still be quitely improved in the future.

@dpguthrie
Copy link
Owner

@cmjordan42 Ya, I'm trying to work on a solution in #205 . There appears to be some issues though - I've been able to get it to work locally and in the streamlit app but others who have installed it are running into errors.

TLDR:

  • The fix in 2.3.2 was to change the endpoint to one that didn't require cookies and a crumb to be set
  • That new endpoint doesn't appear to accept multiple modules, which is the reason for the empty dict
  • The fix in that PR is to find ways to retrieve the relevant cookies as well as the crumb that's needed as a query parameter

@caliskanuzay
Copy link

Dear all,
Thanks a lot for the great work Doug, @dpguthrie. I updated the 2.3.2 version and that solved the "invalid cookie" issue. However, when I read tickers from wikipedia S&P500 webpage using the following code (sorry I don't know how to quote code, I am very very new into coding):

<ticker_SP500 = pd.read_html('https://en.wikipedia.org/wiki/List_of_S%26P_500_companies')[0]
<symbols = ticker_SP500["Symbol"]

When I call "ticker.summary_detail" key, I get the following errors which I did not get before this issue and the 2.3.2 update:

< File ~...\yahooquery\base.py:1217 in _construct_data
< data = json[response_field]["result"][0][addl_key]
<KeyError: 'summaryDetail'
<During handling of the above exception, another exception occurred:
.....
<File ~...\yahooquery\base.py:1224 in _construct_data
< json[response_field]["result"][addl_key]
<TypeError: list indices must be integers or slices, not str

FYI, instead of S&P500, if I read into Nasdaq100 tickers using the following code, everything works fine:

<ticker_Nasdaq100 = pd.read_html('https://en.wikipedia.org/wiki/Nasdaq-100')[4]
<symbols = ticker_Nasdaq100["Ticker"]

I cannot figure out what is the problem with the S&P500 ticker or symbol list. Thanks a lot!
Ahmet

@sanderlenselink
Copy link

Dear all, Thanks a lot for the great work Doug, @dpguthrie. I updated the 2.3.2 version and that solved the "invalid cookie" issue. However, when I read tickers from wikipedia S&P500 webpage using the following code (sorry I don't know how to quote code, I am very very new into coding):

<ticker_SP500 = pd.read_html('https://en.wikipedia.org/wiki/List_of_S%26P_500_companies')[0]%5B0%5D) <symbols = ticker_SP500["Symbol"]

When I call "ticker.summary_detail" key, I get the following errors which I did not get before this issue and the 2.3.2 update:

< File ~...\yahooquery\base.py:1217 in _construct_data < data = json[response_field]["result"][0][addl_key] <KeyError: 'summaryDetail' <During handling of the above exception, another exception occurred: ..... <File ~...\yahooquery\base.py:1224 in _construct_data < json[response_field]["result"][addl_key] <TypeError: list indices must be integers or slices, not str

FYI, instead of S&P500, if I read into Nasdaq100 tickers using the following code, everything works fine:

<ticker_Nasdaq100 = pd.read_html('https://en.wikipedia.org/wiki/Nasdaq-100')[4]%5B4%5D) <symbols = ticker_Nasdaq100["Ticker"]

I cannot figure out what is the problem with the S&P500 ticker or symbol list. Thanks a lot! Ahmet

= = = =
@caliskanuzay

I tried you S&P500 example and get for the Ticker the lists op the S&P500 companies

Regarding "ticker.summary_detail" I'm a bit confused . . . maybe you have to write a capital "T"
The output is a property object.

It might be related with the "Invalid cookie" issues?????

In general . . . as a non-technician I'm a bit lost how to solve the "Invalid cookie" problem
@dpguthrie . . . is it correct that you are working on a solution in an update?
If not can someone give a step by step overview how to solve the "Invalid cookie" issue. I work with version 2.3.2 but it seems this is not enough (a single solution for one company is cumbersome because I work with a list of 600+ companies)

Many thnx in advance

image

@caliskanuzay
Copy link

For those of you who stumble upon the same problem like me with S&P500 tickers, the problem arises from those tickers that include a dot in it: BRK.B and BF.B, particularly the latter. To solve it, needed some help with coding from a friend who deployed a "try" and "except" loop across tickers. If anyone is interested, I can copy the code here. Thanks!

@cmjordan42
Copy link

I'd suggest Stack Exchange for coding help, it's geared towards that whereas this is more for investigating and addressing the issue/bug at hand.

I'm not sure what you're trying to do, but it may help to know that "BRK.B" can be queried as "BRK-B" to get that security's data.

@Courvoisier13
Copy link

use VPN connect to USA.

@ValueRaider
Copy link

I tried yahooquery from UK/EU and this error has gone.

@Courvoisier13
Copy link

@ValueRaider
it actually returns empty dictionnary now:

import pandas as pd
from yahooquery import Ticker

tickers_dict = Ticker(['SPY', 'QQQ'], formatted=True, asynchronous=True, validate=True, progress=True).get_modules(['assetProfile', 'quoteType', 'fundProfile', 'summaryDetail', 'defaultKeyStatistics'])
print(tickers_dict)

I get :
{'QQQ': {}, 'SPY': {}}

@ValueRaider
Copy link

Simplify your code

len(yq.Ticker('AMZN').summary_detail['AMZN'])

54

@Courvoisier13
Copy link

ah, something broke then with the new version:
this gives empty dic:
tickers_dict = Ticker(['SPY', 'QQQ']).get_modules(['assetProfile','summaryDetail'])

while each on their own work:

tickers_dict = Ticker(['SPY', 'QQQ']).get_modules(['assetProfile'])
tickers_dict = Ticker(['SPY', 'QQQ']).get_modules(['summaryDetail'])

because there was a cookie error as well for a while, I thought the two issues were connected.

@KingTurbo
Copy link

I found a "solution" --> if you are not in the US, just try to connect with a VPN from the USA

@0zd3m1r
Copy link

0zd3m1r commented Nov 1, 2023

python v3.11
yahooquery v2.3.3

from Germany

{'AMZN': 'Invalid Cookie'}

@0zd3m1r
Copy link

0zd3m1r commented Nov 14, 2023

python v3.11 yahooquery v2.3.3

from Germany

{'AMZN': 'Invalid Cookie'}

fc.yahoo.com blocked by my adlists. i fixed it!

sed -i '/fc\.yahoo\.com/d' /etc/hosts

@portefeuille
Copy link

Python 3.9.6
Yahooquery 2.3.5
from France

stock=Ticker('GRVO.PA')
data=stock.summary_detail
data
{'GRVO.PA': 'Invalid Cookie'}

@danielegramola
Copy link

danielegramola commented Dec 7, 2023

Same error here (Italy):

stock = Ticker('UCG.MI')
print(stock.key_stats)
{'UCG.MI': 'Invalid Cookie'}

Python 3.11.7, Yahooquery 2.3.5

Update:
After upgrading to 2.3.6:
stock = Ticker('UCG.MI')
print(stock.key_stats)
Failed to obtain crumb. Ability to retrieve data will be significantly limited.
{'UCG.MI': 'Invalid Cookie'}

@qkxie
Copy link

qkxie commented Dec 28, 2023

@danielegramola same error in version 2.3.7,region:Taiwan

@staper1960
Copy link

So, back to square one? I am also getting invalid cookie in my program, which used to work after installing 2.3.2.

@galashour
Copy link

galashour commented Jan 12, 2024

So, back to square one? I am also getting invalid cookie in my program, which used to work after installing 2.3.2.

current version is > 2.3.5 (2.3.5 seems to work fine for me)

@staper1960
Copy link

So, back to square one? I am also getting invalid cookie in my program, which used to work after installing 2.3.2.

current version is > 2.3.5 (2.3.5 seems to work fine for me)

I am in Greece, none of the versions seems to be working. I see other Europeans complaining. Is there an update that works in Europe?

@maread99
Copy link
Contributor

As people have suggested elsewhere, in Europe looks like it's necessary to pass the 'asynchronous' argument to Ticker as False.

Certainly try that if you haven't already. Works for me.

@staper1960
Copy link

It works now. Thank you very much!

As people have suggested elsewhere, in Europe looks like it's necessary to pass the 'asynchronous' argument to Ticker as False.

Certainly try that if you haven't already. Works for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests