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

KeyError on login #511

Open
cameronray357 opened this issue Dec 5, 2024 · 91 comments
Open

KeyError on login #511

cameronray357 opened this issue Dec 5, 2024 · 91 comments

Comments

@cameronray357
Copy link

When running the login protocol, I am getting a KeyError that shows this:

KeyError Traceback (most recent call last)
Cell In[6], line 3
1 import robin_stocks.robinhood as r
----> 3 login = r.login(username, password)

File ~/Library/jupyterlab-desktop/jlab_server/lib/python3.8/site-packages/robin_stocks/robinhood/authentication.py:190, in login(username, password, expiresIn, scope, by_sms, store_session, mfa_code, pickle_name)
185 pickle.dump({'token_type': data['token_type'],
186 'access_token': data['access_token'],
187 'refresh_token': data['refresh_token'],
188 'device_token': payload['device_token']}, f)
189 else:
--> 190 raise Exception(data['detail'])
191 else:
192 raise Exception('Error: Trouble connecting to robinhood API. Check internet connection.')

KeyError: 'detail'

@hokeihero
Copy link

I am also having the same issue. I digged a little deeper. Seems like the return is some sort of verification issue. I have no idea how to fix this.
Here is the response I got:
{'verification_workflow': {'id': '21d5649d-1a75-4358-98ec-c3d742b7c926', 'workflow_status': 'workflow_status_internal_pending'}}
Traceback (most recent call last):
File "/Users/hokeihero/PycharmProjects/RobinhoodTest/.venv/main.py", line 31, in
rh.login(USERNAME, PASSWORD,mfa_code=MFA_CODE,by_sms=False)
File "/Users/hokeihero/PycharmProjects/RobinhoodTest/.venv/lib/python3.11/site-packages/robin_stocks/robinhood/authentication.py", line 201, in login
raise Exception(data['detail'])
~~~~^^^^^^^^^^
KeyError: 'detail'

@ahaggard2013
Copy link

ahaggard2013 commented Dec 5, 2024

have the same issue. Wondering if the API responses changed, but haven't had a chance to look into it at all yet.

@Kr1msonReaper
Copy link

I have the same issue, unfortunately. It would be on a day where a stock is up 200%+. If anyone figures it out let me know! I'll take a look myself when I have the time.

@ravi-bharadwaj
Copy link
Contributor

I am getting error message of unsupported_grant_type errors with a status code 403(had to modify my fork to get the error codes) #510

@Varun-Poondi
Copy link

Getting the same error here, I used the otp code to see if it would work in robin and it seems to work fine.

@HitoJima
Copy link

HitoJima commented Dec 5, 2024

So you were able to verify the API or only that the OTP was working?

@doormat-1010
Copy link

doormat-1010 commented Dec 5, 2024

@ravi-bharadwaj
After implementing

I am getting error message of unsupported_grant_type errors with a status code 403(had to modify my fork to get the error codes) #510

I get error response of:
workflow_status: workflow_status_internal_pending

@hokeihero
Copy link

@doormat-1010 I got the exact same error message. check out my comment.

@Varun-Poondi
Copy link

I was only able to veryify that the otp was working.
totp = pyotp.TOTP(os.environ['robin_mfa']).now()
This works for me. I pasted the otp in robinhood and I was able to verify. Issue occures when I login programmatically (data['details'] KeyError).

@ahaggard2013
Copy link

anyone try it without an authenticator app 2FA enabled? Have a feeling that may be the issue.. but going to investigate tomorrow when I have time.

@hokeihero
Copy link

anyone try it without an authenticator app 2FA enabled? Have a feeling that may be the issue.. but going to investigate tomorrow when I have time.

I think the 2FA is mandatory in Robinhood now.

@cameronray357
Copy link
Author

@ahaggard2013 Yeah I'm thinking the structure has changed in the request somehow based on the error type.

@HitoJima
Copy link

HitoJima commented Dec 5, 2024

Is it possible the endpoint changed?

@Kr1msonReaper
Copy link

If the structure of the request has changed, we should be able to use the DevTools network listener to view the new structure. I don't have time at the moment, but if anyone else does go for it!

@Kr1msonReaper
Copy link

Alright, I've taken a look at it. Granted, I'm not the most experienced with this sort of thing but I've compared the payload sent by the browser to login to the one robin_stocks sends. It seems to me that the difference is that the payload used to include a header called mfa_code, but now the code may be received differently and is no longer a part of the same login request.

When the browser sends the login payload even it receives the internal pending message which suggests to me that it's still waiting for the 2FA code to be entered. After that request, my machine sent a second payload consisting of my device_id, a value called flow and the workflow_id.

Anyone have any ideas?

@Kr1msonReaper
Copy link

Okay, yeah, there's a second payload sent titled "response" that contains the 2FA value once entered and submitted. Not sure if it can be included in the original login request, but it's being sent to a URL that I'm not sure how to use. It doesn't seem like it would be static.

@ahaggard2013
Copy link

Alright, I've taken a look at it. Granted, I'm not the most experienced with this sort of thing but I've compared the payload sent by the browser to login to the one robin_stocks sends. It seems to me that the difference is that the payload used to include a header called mfa_code, but now the code may be received differently and is no longer a part of the same login request.

When the browser sends the login payload even it receives the internal pending message which suggests to me that it's still waiting for the 2FA code to be entered. After that request, my machine sent a second payload consisting of my device_id, a value called flow and the workflow_id.

Anyone have any ideas?

sounds like something changed. A few things, you could try the flow with device verification and sms verification instead of an authenticator. They may differ slightly and align with the current robin_stock flow. It's also likely the mobile api could use slightly different endpoints than the browser. You may have have to bypass certificate pinning to intercept robinhood mobile requests to compare them which can sometimes be tricky. The other option is modify the library to work with the new flow. A lot of work, but a few things I would like to try soon. not home so unable to debug atm

@altanalytics
Copy link

I have been digging into this. I have two accounts with Robinhood. Originally both were failing when I logged in programmatically. I added a user-agent and that fixed my problem for one but not the other. Looking into the api calls through the website, I see that my account logs in no issue where as my second one gets the red token with the same error message I saw and everyone else has been reporting.

I am not sure what the problem is here but hopefully it's a temporary outage. I don't see any other way to code around this right now. See attached for photos. I don't have time to dig into this further right now but hopefully this helps someone figure out what the issue is

My login works now with user-agent in API call in first account
Screenshot 2024-12-05 at 15 35 18
My second account does not but can still login through website but gets this api call
Screenshot 2024-12-05 at 15 36 02

I checked all the normal things like settings, security, etc. I cannot see a difference.

@Kr1msonReaper
Copy link

Seems to me that we just have to whip up a new snippet that sends the mfa code to the new end-point under the "response" header. My lack of knowledge prevents me from quickly figuring out how to consistently have access to the correct end-point.

@HitoJima
Copy link

HitoJima commented Dec 5, 2024

There are two forks addressing it, has anyone checked them?

@erchen7
Copy link

erchen7 commented Dec 5, 2024

Is it fixed ? not sure why, I reinstalled the robin_stocks and now it works

@altanalytics
Copy link

Is it fixed ? not sure why, I reinstalled the robin_stocks and now it works

I have not seen any commits to main and I tried on mine and it did not work

@HitoJima
Copy link

HitoJima commented Dec 6, 2024

Is it fixed ? not sure why, I reinstalled the robin_stocks and now it works

I have not seen any commits to main and I tried on mine and it did not work

When it fixed, were you using mfa?

@erchen7
Copy link

erchen7 commented Dec 6, 2024

I am using mfa

@HitoJima
Copy link

HitoJima commented Dec 6, 2024

I am using mfa

Could you check the version.. I updated to 3.2.1 and didnt work.

@erchen7
Copy link

erchen7 commented Dec 6, 2024

it is 3.2.1 but I delete the original venv and create a new one to reinstall it. because I found pip uninstall will not remove old files in my machine

@altanalytics
Copy link

altanalytics commented Dec 6, 2024 via email

@HitoJima
Copy link

HitoJima commented Dec 6, 2024

I am fairly certain this is a Robinhood issue and not an issue with the python package since one of my accounts worked and one did not. Just my 2 cents On Dec 5, 2024, at 20:05, erchen7 @.> wrote: it is 3.2.1 but I delete the original venv and create a new one to reinstall it. because I found pip uninstall will not remove old files in my machine —Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you commented.Message ID: @.>

Could it be an account configuration issue?

@jtovar2
Copy link

jtovar2 commented Dec 6, 2024

seems like the flow has changed, first it calls token then pathfinder/user_machine and then user_view then you can call the /respond endpoint. I have been able to successfully call the /user_machine but its not working for /user_view

@altanalytics
Copy link

I use R instead of Python, but it's all the same. I used the logic from above and rebuilt the login mechanism. you can see the code change here: altanalytics/RobinHood@bf41654

You shouldn't need to change anything on the Robinhood side. It just looks like they changed the authentication process and now require further levels of validation before logging you in. Good luck and let me know if you need any help.

@Varun-Poondi
Copy link

seems like ravi's solution works for some but doesn't for others. it didn't work for me at first but i've managed to make it work, maybe it helps someone.

  1. i'd fully reinstall, so: pip install --force-reinstall robin-stocks
  2. take ravi's auth file and paste it into robin-stocks/robinhood/authentication.py. make sure it's the one inside the robinhood folder and not the one inside the robin-stocks folder.
  3. generate a new device approval code (the one that looks something like ORFHG6RSMM7B9023), make sure you save that and add it to something like authy. also make sure to verify that approval code with robinhood by putting in the 6 digit code into the app to verify it.
  4. run your script and log into robinhood using a hardcoded 6 digit code from authy on a new session like:
def login_to_robinhood():
    username = config.LOGIN
    password = config.PASS
    # totp = pyotp.TOTP(config.KEY).now()
    login = rh.login(username, password, mfa_code='123456', store_session=False)
    return login

after i did all of that, it was able to login and execute orders. afterwards, i ran an entirely separate script without a hardcoded mfa_code, just using totp and the device approval code from earlier as the key and it was able to login just fine.

I just tried this and it worked. Thanks for the help and great work Ravi.

This is what I did, worked for me.

@Adelantado
Copy link

I do appreciate everyone's input and effort and I do wish I was smart enough to contribute, but I am not.
So far I've tried every possible fix mentioned and none did work. I am freaking out cause we have been thru a lot over the past four years or so,, but not being able to just log in tops it all.
Oh please all mighty Master Fernandes ... please help us !

@quikksilver1
Copy link

quikksilver1 commented Dec 7, 2024

I have been working on my code for the last 2.5 years and have tried all your changes and have not come up successful.

Current State:
robinstocks == 3.2.1. (Started with 1.5.4)
pip install --force-reinstall robin-stocks
removed mobile device from robinhood
logged back in on mobile device
changed 2fa to authenticator app
have otp 6 digit code autogenerating on microsoft authenticator app for robinhood account
Have ravi-bharadwaj authentication.py script in robin-stocks/robinhood/authentication.py

Still getting following error:
'''Traceback (most recent call last):
File "C:\Users\jonat\PycharmProjects\pythonStonks_improving_model_active_b4_day_loop_debug_robinstocks\Daily Report.py", line 17, in
login = r.login(username=username, password=password,store_session=True)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\jonat\PycharmProjects\pythonStonks\venv\Lib\site-packages\robin_stocks\robinhood\authentication.py", line 194, in login
_validate_sherrif_id(device_token=device_token, workflow_id=workflow_id, mfa_code=mfa_code)
File "C:\Users\jonat\PycharmProjects\pythonStonks\venv\Lib\site-packages\robin_stocks\robinhood\authentication.py", line 235, in _validate_sherrif_id
if challenge_response["status"] == "validated":
~~~~~~~~~~~~~~~~~~^^^^^^^^^^
KeyError: 'status''''

@kitsu-labs
Copy link

I have been working on my code for the last 2.5 years and have tried all your changes and have not come up successful.

Current State: robinstocks == 3.2.1. (Started with 1.5.4) pip install --force-reinstall robin-stocks removed mobile device from robinhood logged back in on mobile device changed 2fa to authenticator app have otp 6 digit code autogenerating on microsoft authenticator app for robinhood account Have ravi-bharadwaj authentication.py script in robin-stocks/robinhood/authentication.py

Still getting following error: '''Traceback (most recent call last): File "C:\Users\jonat\PycharmProjects\pythonStonks_improving_model_active_b4_day_loop_debug_robinstocks\Daily Report.py", line 17, in login = r.login(username=username, password=password,store_session=True) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\jonat\PycharmProjects\pythonStonks\venv\Lib\site-packages\robin_stocks\robinhood\authentication.py", line 194, in login _validate_sherrif_id(device_token=device_token, workflow_id=workflow_id, mfa_code=mfa_code) File "C:\Users\jonat\PycharmProjects\pythonStonks\venv\Lib\site-packages\robin_stocks\robinhood\authentication.py", line 235, in _validate_sherrif_id if challenge_response["status"] == "validated": ~~~~~~~~~~~~~~~~~~^^^^^^^^^^ KeyError: 'status''''

it appears you have store_session=True. try setting it to false to skip the cached login and force a new login.

@aLearningProcess
Copy link

Thank to all as well. This situation is a stretch beyond my knowledge. I as other have been putting in years on building a platform using this tool and have appreciated it so much. So I look forward when a fix can be merged.

@Tan-TanDesign
Copy link

Tan-TanDesign commented Dec 8, 2024

def td_rh_login(account):
totp = pyotp.TOTP(bah_device).now()
print(totp)
rs.robinhood.login(username=account.username, password=account.password, mfa_code=totp, store_session=False)

Is my final fix to the below solution:
I used Microsoft Authentication APP on iPhone to verify Robinhood device code. Then hardcoded the value to 'bah_device', use pyotp.TOP to generate the six digit code as before, set mfa_code

To get the device code. Log into RobinHood, account, settings, security and privacy, Two-Factor Authentication, then Authentication app -> select Update. You can add an account to MS Authentication app (verify method) and/or select can't read barcode to copy then paste in your python code (my case is bah_device = 'copied device code'

seems like ravi's solution works for some but doesn't for others. it didn't work for me at first but i've managed to make it work, maybe it helps someone.

  1. i'd fully reinstall, so: pip install --force-reinstall robin-stocks
  2. take ravi's auth file and paste it into robin-stocks/robinhood/authentication.py. make sure it's the one inside the robinhood folder and not the one inside the robin-stocks folder.
  3. generate a new device approval code (the one that looks something like ORFHG6RSMM7B9023), make sure you save that and add it to something like authy. also make sure to verify that approval code with robinhood by putting in the 6 digit code into the app to verify it.
  4. run your script and log into robinhood using a hardcoded 6 digit code from authy on a new session like:
def login_to_robinhood():
    username = config.LOGIN
    password = config.PASS
    # totp = pyotp.TOTP(config.KEY).now()
    login = rh.login(username, password, mfa_code='123456', store_session=False)
    return login

after i did all of that, it was able to login and execute orders. afterwards, i ran an entirely separate script without a hardcoded mfa_code, just using totp and the device approval code from earlier as the key and it was able to login just fine.

@nur-cde
Copy link

nur-cde commented Dec 8, 2024

Is there any solution for the robinhood two factor authentication type -- Device approval ? .. I tried the above solution with the device approval authentication type, but getting the error 'status'..

@Gates8911
Copy link

For Anyone still troubleshooting: try this
totp_secret = os.environ['mfa_code'] # set with code
you used when you set up 3rd party app to
communicate with RobinH
totp = pyotp.TOTP(totp_secret).now()
username = os.environ['your_username']
password = os.environ['your_password']
login_data = robinhood.login(username, password,
expiresIn=86400, scope='internal',
store_session=True, mfa_code=totp,
pickle_name="Name_file_optional")
rs.update_session("access_token",
login_data["access_token"]) # manually updates
the session instead of relying on auth func
rs.update_session("refresh_token",
login_data.get("refresh_token")) # my current workaround for the updated api, for me after updating the authenticator module to handle the new authentication for whatever reason it would save the pickle file and everything as normal, the bot would run but couldnt make calls, well if you set 3rd party verification (i used google authentication app) and then use this code (i used pc environment variables to prevent hard coding). Ensure the 3rd party app is set up right a communicates with robinhood, the beginning of this is the totp_secret which is the code you used to set up the 2 factor auth app, originally copied from robinhood, after setting this up that value is what mfa_code expects, regular device approvals will not work, i learned this the hard way troubleshooting for 16 hours straight b4 trying the otp method, which ran into new issue, but then realized the module wasnt keeping me logged in is all, so i added update lines to ensure login state is saved

@gianpierre2024
Copy link

For those who are still having a problem, I recommend following the steps above using Ravi's authentification.py file,

But the issue that I was having was I was pasting Ravi's authentification file into the wrong location. I was using some location where I downloaded the robinstock-API from git but not where my computer was pulling the git files which was from an old location I have used in the past. This true location is given in the error message when I try to run my script. That is the location where you want to paste Ravi's change.

Also as for the authentification app, I am just using a text file where I pull the MFA code from and run it through python otp module. See this old video for how I do that:

https://www.youtube.com/watch?v=C5buU4zjjx0&t=339s

@gianpierre2024
Copy link

For those who are still having a problem, I recommend following the steps above using Ravi's authentification.py file,

But the issue that I was having was I was pasting Ravi's authentification file into the wrong location. I was using some location where I downloaded the robinstock-API from git but not where my computer was pulling the git files which was from an old location I have used in the past. This true location is given in the error message when I try to run my script. That is the location where you want to paste Ravi's change.

Also as for the authentification app, I am just using a text file where I pull the MFA code from and run it through python otp module. See this old video for how I do that:

https://www.youtube.com/watch?v=C5buU4zjjx0&t=339s

Is this the safest way to do authentication or is there something else I should research ?

@Gates8911
Copy link

Gates8911 commented Dec 8, 2024

@gianpierre2024
I like to set up a virtual environment first when creating a project using (python -m venv custom_name), remember to use the cd command to navigate to the directory where you want your virtual env to be, technically location only matters for easily finding it and easy activation because you can actually activate the virtual environment (after creating) from any directory on your pc and it will still work and build all dependencies youve previously installed within it while also isolating the rest of the pc (other than the directory you are actually in, and relative path can also be imported if you wish, so you can go into your projects directory, then activate your venv and then run your project) once this directory is created, activate with .\custom_name\scripts\activate assuming you are in the same directory as the venv, if not you must type the full path to the activate file with the newly created venv folder, note that when environment is activated successfully whatever you named the environment will then be in parethysis next to the interpreter line you are using, I use cmd, if active prompt may say:
(Env_name) C:\Users\current_dir>
Indicating you are in the venv, then use pip to install required packages within the venv, and makes the source code easier to change if necessary, as for accessing the api, if you use a 3rd party authentication app via option in robinhood security settings (seemingly required now given the new api update) and do not hard code any sensitive data and you can also use a vpn for extra security as well. Other than that I cant think of a way to make it safer.

@cpasean
Copy link

cpasean commented Dec 8, 2024

I've tried several of the tips mentioned above over the past few days, but I'm still encountering the error message below. Could anyone kindly provide a solution that has worked for successfully logging in? I'm currently using version 3.2.1 of robin-stocks and have attempted to reset two-factor authentication using both text messages and an authenticator app. It will be highly appreciated.


ERROR: There was an issue loading pickle file. Authentication may be expired - logging in normally.

File ~\anaconda3\lib\site-packages\robin_stocks\robinhood\authentication.py:197, in login(username, password, expiresIn, scope, by_sms, store_session, mfa_code, pickle_path, pickle_name)
192 pickle.dump({'token_type': data['token_type'],
193 'access_token': data['access_token'],
194 'refresh_token': data['refresh_token'],
195 'device_token': payload['device_token']}, f)
196 else:
--> 197 raise Exception(data['detail'])
198 else:
199 raise Exception('Error: Trouble connecting to robinhood API. Check internet connection.')

KeyError: 'detail'

@Adelantado
Copy link

Update:
I was able to log in .... Bots are running, now let's hope Robin has not changed anything on the trade execution side.

Thank you ravi-bharadwaj for the fix and thank you Tan-TanDesign for this:

"take ravi's auth file and paste it into robin-stocks/robinhood/authentication.py. make sure it's the one inside the robinhood folder and not the one inside the robin-stocks folder."

I feel so dumb I did not realized the right path to authentication.py, hope my mistake helps another lost soul out there.

And finally, thanks to all for coming together and best wishes.

@Adelantado
Copy link

Adelantado commented Dec 9, 2024

Seems to me you are missing your 2FA, passing to the log in function just the username and password is for logging via SMS code, which I believe is no longer supported when using the API.

Notes from my code:
#---------------------------------------------------------------------------------#
#login = r.login(log_User, log_Pass) # ==> [ Simple log-in via Tx Code ]
#---------------------------------------------------------------------------------#

==> [ (2) Factor Authentication. No need for Tx. Displays Current OTP ] <==

totp = pyotp.TOTP(log_2FA).now()
login = r.login(log_User, log_Pass, mfa_code=totp)
#-------------------------------------------------
sleep(1)
print(' .')
print(" ==> [0_0] ... Current OTP:", totp)
print(" .")
print()
print()
print()
print()
sleep(4)
#---------------------------------------------------------------------------------#

Hope it helps.
PS: Hope those are not real credentials .....

@SumayKalra
Copy link

SumayKalra commented Dec 9, 2024

Is there any solution that does not require manual authentication? Aka if I have someone enter there username and password it should auto login without having to set up some version of MFA, or is this the best we have for now? also when will these changes be merged?

@Adelantado
Copy link

Is there any solution that does not require manual authentication? Aka if I have someone enter there username and password it should auto login without having to set up some version of MFA, or is this the best we have for now? also when will these changes be merged?

I would suggest, once you obtain your 2FA form robin, to just hardcode the 2FA, user_name and password; that way there is no need for human input to log in.
No clue when fix will be merged.

@ravi-bharadwaj
Copy link
Contributor

if we can get the PR merged soon, it will avoid so much confusion and unnecesary steps that so many have to take.

@Gates8911
Copy link

Gates8911 commented Dec 9, 2024

@Adelantado
Nothing has to be hardcoded, you can use your pc's environment variable (via search bar) to assign the variable and the value to the path identifier so that you can then use one of 2 different calls to access it.
For example:
Import os
Password = os.getenv('variable_name')
Or
Password = os.environ['variable_name']
Keep in mind when setting this that you do not need to make it as a string in the environment variables. Only when called within your script does it need to be a string.
If done correctly this works just fine, you can use the user variables, unless you run the bot with admin privileges, then i believe you would put it in system path instead, which is found in the same window after you open the environment variables window of your pc. I would never hard code sensitive data, that being said I kind of like this change, adds extra security and you can still get the bots to automatically sign in, ive adjusted my code to act as an app on my desktop, all i must do is double click the window and it does the rest.
On another note I noticed some people using sleep functions, which is fine in some cases but keep in mind that sleep interrupts your bot flow and can interfere depending on how it is used, ive been using a module called asyncio to accomplish a non-disruptive sleep function. The only down side is when using it you should make a new function for it, and you must use
async def function():
When creating a function that relies on this mod.

@Adelantado
Copy link

Adelantado commented Dec 9, 2024

@Gates8911
While I do appreciate the input, think we all can agree that there is a thousand ways to skin a cat.
For my purpose and the way I schedule and run my bots unattended 24/7 on AWS there is nothing more simple than to write three lines and hard code three variables, it's easy and most important it works for me.
With that said, if you a know faster way or how to simplify the writing of three variables, please share.

Regarding the sleep, I would recommend to anyone to pause their program for a few secs after cancelling or submitting orders and check it's status; before doing anything else; I always do. There is no room in my logic for unconfirmed, rejected or failed orders so Ive learned to wait, check, and loop if necessary, Robinhood has gotten better and faster over time, but I've seen orders for up to two minutes with a status of "unconfirmed". Just my $0.02

@SumayKalra
Copy link

@Adelantado I like the method you described do you have discord or some sort, where I could as you questions about the code I seem to still be struggling with your method

@Adelantado
Copy link

Adelantado commented Dec 10, 2024 via email

@Gates8911
Copy link

Gates8911 commented Dec 11, 2024

@Adelantado Oh, when you said hardcoding I thought you meant your sensitive info is literally in the script itself, yeah as long as its masked some way it doesnt matter how you do it, i considered multiple strategies for this. Would certainly agree there is always different ways of accomplishing a task especially when it comes to coding, and yeah i also have my code check for the order status as well after a non interference sleep function, but i use a loop function with limited number of checks, and if the order isnt filled after all checks are ran it will simply cancel the order, I finally got a separate self update function to work as well, so if my script buys but then gets an error or for example I manually buy or sell one of the assets, the bot can update itself and store the necessary info to sell later or delete a position when sold. Not that this is relevant but i also found a python package recently that enables audio messages through voice assistance manipulation, so that your script can announce errors and other activities so that you dont need to be right there reading it to know what is happening, probably routine to a lot of people on this thread, but figured I would still throw it out there incase someone didnt know this exists. Also, what did you mean by you do not have room for unconfirmed etc.? And this may be a stupid question but again im self taught with full time job lol, so my knowledge is likely limited compared to most developers, the only reason i share my methods on here, is the off chance that someone else beginning their learning journey may stumble upon it an give em more ideas.

@Adelantado
Copy link

@Gates8911
All is cool. Let's just focus on having our Bots up an running again, and trying to help the best we can to all of those arriving in here seeking for help ( me the first one ) . I for sure I am most great full for all the support I've received since day one.
Whit that said and like the old song says..... There is not time to waste justifying a delay ... so lets just move on.

And once again....Thanks yall

@Gates8911
Copy link

@Adelantado Assumed yall bounce ideas off eachother and what not as well, didnt mean to annoy anyone, have a good one.

@Adelantado
Copy link

@Gates8911 .... All is cool. English is not my native language and I've been told more than once to come across as a bit hurst when expressing my thoughts. I am aware and I do apologize for it.

@finlop
Copy link

finlop commented Jan 12, 2025

anyone know how to make the code work for device approvals. i only get device approvals now from my iphone robinhood app. and then the code i run waits for the device approval to be approved and then checks to see if i can log in successfully. but it never sees that i approved the device.

import random
import getpass
import os
import pickle
import requests
import time

Generate a unique device token

def generate_device_token():
"""Generates a unique device token."""
rands = []
for _ in range(16):
rand = random.randint(0, 255)
rands.append(rand)

hexa = [str(hex(i + 256)).lstrip("0x")[1:] for i in range(256)]
token = ""
for i, r in enumerate(rands):
    token += hexa[r]
    if i in [3, 5, 7, 9]:
        token += "-"
return token

Respond to challenges

def respond_to_challenge(challenge_id, sms_code):
"""Responds to a challenge with the provided code."""
url = f"https://api.robinhood.com/challenge/{challenge_id}/respond/"
payload = {"response": sms_code}
response = requests.post(url, json=payload)
return response.json()

Save and load session data

def save_session(data, pickle_name="robinhood_session.pickle"):
"""Saves session data to a pickle file."""
with open(pickle_name, "wb") as f:
pickle.dump(data, f)

def load_session(pickle_name="robinhood_session.pickle"):
"""Loads session data from a pickle file if it exists."""
if os.path.exists(pickle_name):
with open(pickle_name, "rb") as f:
return pickle.load(f)
return None

def handle_verification_workflow(device_token, workflow_id):
"""Handles verification workflow for device approval."""
print("Handling verification workflow. Please approve the login request on your device.")
url = f"https://api.robinhood.com/pathfinder/user_machine/"
payload = {
"device_id": device_token,
"flow": "suv",
"input": {"workflow_id": workflow_id}
}
response = requests.post(url, json=payload)
if response.status_code == 200:
print("Verification workflow initiated successfully. Waiting for approval...")
else:
raise Exception(f"Failed to initiate verification workflow: {response.text}")

inquiries_url = f"https://api.robinhood.com/pathfinder/inquiries/{response.json()['id']}/user_view/"
max_attempts = 5  # Increase retries to 30 attempts (5 minutes total)
delay_between_attempts = 10  # 10 seconds between checks

for attempt in range(max_attempts):
    print(f"Attempt {attempt + 1}: Checking approval status...")
    try:
        inquiry_response = requests.get(inquiries_url, timeout=10).json()
        status = inquiry_response["type_context"]["context"]["sheriff_challenge"]["status"]
        print(f"Device approval status: {status}")

        if status == "approved":
            print("Device approval successful!")
            return

        if status == "denied":
            raise Exception("Device approval was denied.")

    except Exception as e:
        print(f"Error while checking approval status: {e}")

    time.sleep(delay_between_attempts)

print("Device approval timed out. Please ensure you approved the login request.")


# Login to Robinhood

def robinhood_login(username=None, password=None, expires_in=86400, scope="internal"):
"""Logs into Robinhood and handles verification workflows."""
device_token = generate_device_token()
print("Generated Device Token:", device_token)

url = "https://api.robinhood.com/oauth2/token/"
payload = {
    "grant_type": "password",
    "scope": scope,
    "client_id": "c82SH0WZOsabOXGP2sxqcj34FxkvfnWRZBKlBjFS",
    "device_token": device_token,
    "username": username,
    "password": password,
}

session = load_session()
if session:
    print("Using saved session.")
    return session["access_token"]

response = requests.post(url, data=payload)
data = response.json()

if response.status_code == 200:
    print("Login successful.")
    save_session(data)
    return data["access_token"]

if "verification_workflow" in data:
    workflow_id = data["verification_workflow"]["id"]
    print(f"Verification workflow triggered. Workflow ID: {workflow_id}")
    handle_verification_workflow(device_token, workflow_id)
    response = requests.post(url, data=payload)
    data = response.json()
    if response.status_code == 200:
        print("Login successful after verification workflow.")
        save_session(data)
        return data["access_token"]

print("Failed to log in:", data)
return None

Main flow

if name == "main":
username = input("Enter your Robinhood username: ")
password = getpass.getpass("Enter your Robinhood password: ")
token = robinhood_login(username=username, password=password)
if token:
print("Access token:", token)
else:
print("Failed to log in.")

Verification workflow triggered. Workflow ID: 00e60f42-de4c-4282-ad7d-e9c01a0206e1
Handling verification workflow. Please approve the login request on your device.
Verification workflow initiated successfully. Waiting for approval...
Attempt 1: Checking approval status...
Device approval status: issued
Attempt 2: Checking approval status...
Device approval status: issued
Attempt 3: Checking approval status...
Device approval status: issued
Attempt 4: Checking approval status...
Device approval status: issued
Attempt 5: Checking approval status...
Device approval status: issued
Device approval timed out. Please ensure you approved the login request.
Failed to log in: {'verification_workflow': {'id': '00e60f42-de4c-4282-ad7d-e9c01a0206e1', 'workflow_status': 'workflow_status_internal_pending'}}
Failed to log in.

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