A modern, reliable Python client for the Robinhood API
Project description
pyhood
A modern, reliable Python client for the Robinhood API.
Built for automated trading — with auth that doesn't break, proper error handling, and sane defaults.
Why pyhood?
- 🔐 Auth that just works — Login with timeouts, automatic token refresh, and session persistence. Authenticate once, stay connected for days. No more scripts that hang forever waiting for device approval.
- 🔄 Automatic token refresh — pyhood uses OAuth refresh tokens to renew your session silently — no credentials, no device approval, no human in the loop. Built for unattended automation.
- 🏷️ Type hints everywhere — Full type annotations, dataclass responses, IDE-friendly. No more guessing what's in a dict.
- 🛡️ Built-in rate limiting — Automatic request throttling and retry logic so you don't get locked out.
- 📊 Options-first — Deep options chain support with Greeks, volume/OI analysis, and earnings integration.
- 🧪 Tested and maintained — 58+ tests, CI across Python 3.10-3.13, linted with ruff. If it breaks, we know immediately.
Quick Start
import pyhood
from pyhood.client import PyhoodClient
# Login (with timeout — never hangs)
session = pyhood.login(username="you@email.com", password="...", timeout=90)
client = PyhoodClient(session)
# Stock data
quote = client.get_quote("AAPL")
print(f"AAPL: ${quote.price:.2f} ({quote.change_pct:+.1f}%)")
# Options chains
chain = client.get_options_chain("AAPL", expiration="2026-04-17")
for option in chain.calls:
print(f" {option.strike} call | IV: {option.iv:.0%} | Delta: {option.delta:.2f}")
# Account
positions = client.get_positions()
balance = client.get_buying_power()
Authentication
Robinhood requires device approval on first login. After that, hood keeps your session alive automatically.
First Login
- Have the Robinhood mobile app open on your phone
- Call
pyhood.login()— it will trigger a device approval request - Tap "Yes, it's me" in the Robinhood app when prompted
- pyhood saves the session token to
~/.pyhood/session.jsonfor reuse
import pyhood
# First login — will wait up to 90s for you to approve on phone
session = pyhood.login(
username="you@email.com",
password="your_password",
timeout=90, # seconds to wait for device approval
)
Staying Authenticated
Once you've approved the device, pyhood handles the rest:
# Reuses cached session — no approval needed
session = pyhood.login(username="you@email.com", password="your_password")
# Or refresh explicitly — no credentials needed at all
session = pyhood.refresh()
Sessions last several days (observed 5-8 days). When the access token expires, pyhood automatically refreshes it using the stored refresh token — no device approval, no credentials, no human interaction. This is what makes pyhood safe for automated scripts and cron jobs.
Device approval is only needed again if the refresh token itself expires (typically much longer than the access token).
Error Handling
pyhood raises specific exceptions so you know exactly what went wrong:
from pyhood.exceptions import (
LoginTimeoutError, # Timed out waiting for device approval
DeviceApprovalRequiredError, # Approval prompt sent but not completed
MFARequiredError, # SMS/email code needed — pass mfa_code parameter
TokenExpiredError, # Refresh token expired — full re-login needed
AuthError, # Generic auth failure
)
try:
session = pyhood.login(username="...", password="...", timeout=90)
except LoginTimeoutError:
print("Open Robinhood app and approve the device, then try again")
except MFARequiredError:
code = input("Enter the code from SMS/email: ")
session = pyhood.login(username="...", password="...", mfa_code=code)
except AuthError as e:
print(f"Login failed: {e}")
⚠️ Rate Limits
Robinhood aggressively rate-limits authentication. If login fails:
- Do NOT retry immediately — wait at least 5 minutes
- 2-3 failed attempts will lock out your account's API access for 5-10 minutes
- Each login attempt generates a new device approval — old approvals don't carry over
- See the Rate Limits documentation for details
Install
pip install pyhood
Status
🚧 Early development — Core auth, token refresh, and market data modules are functional. Options trading and full order management in progress.
Acknowledgments
hood stands on the shoulders of the community that figured out Robinhood's unofficial API:
- robin_stocks by Josh Fernandes — The most widely used Python library for Robinhood. Its auth flow, endpoint mapping, and API patterns laid the groundwork that hood builds from.
- pyrh by Robinhood Unofficial — An early Python client that pioneered OAuth token refresh and session management patterns for the Robinhood API.
- Robinhood by Sanko — The original unofficial API documentation that mapped out Robinhood's endpoints and made all of these libraries possible.
These projects made Robinhood accessible to developers. hood continues that mission with a focus on reliability and automation.
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pyhood-0.1.0.tar.gz.
File metadata
- Download URL: pyhood-0.1.0.tar.gz
- Upload date:
- Size: 30.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
67c7ed1f588752026e126074347707c4d4b2a9dc1c42f7fa58bb8bbc0696c61d
|
|
| MD5 |
4c5c5cf3d8df12091c6069b35f73adf8
|
|
| BLAKE2b-256 |
f1b199fdd2c7eb6cc9aea9cb614da89afb4c20a5160408c071c3f7409409acb8
|
File details
Details for the file pyhood-0.1.0-py3-none-any.whl.
File metadata
- Download URL: pyhood-0.1.0-py3-none-any.whl
- Upload date:
- Size: 16.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
db1fdb33335bd9f59063085c80a1b6693caf218dc9680cb2278bd6e6eded0a7e
|
|
| MD5 |
ccad5c8c80cffba8e1b2ac1ada121739
|
|
| BLAKE2b-256 |
c2db52cb4cc945f47d589ebfe44a558b95d6dd282959ce6e52962950915976b0
|