Skip to main content

A modern, reliable Python client for the Robinhood API

Project description

pyhood

pyhood logo

A modern, reliable Python client for the Robinhood API.

CI PyPI Docs Python 3.10+ License: MIT Coverage Security Code style: ruff

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?

  • ๐Ÿช™ Dual API support โ€” The only Python library that wraps both Robinhood's unofficial stocks/options API and their official Crypto Trading API. One library, full coverage.

  • ๐Ÿ” 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. Supports both equity and index options (SPX, NDX, VIX, RUT).

  • ๐Ÿ“ˆ Futures trading โ€” Contract details, real-time quotes, order history, and P&L calculation for Robinhood futures.

  • ๐Ÿฆ IRA/Retirement accounts โ€” Trade stocks and options in Traditional and Roth IRAs. The only Python Robinhood library with retirement account support.

  • ๐Ÿ’ฐ Banking & dividends โ€” Query ACH transfers, linked bank accounts, debit card transactions, and dividend history.

  • ๐Ÿ“‹ Watchlists โ€” Create, manage, and modify your Robinhood watchlists programmatically.

  • ๐Ÿ” Research & discovery โ€” Analyst ratings, news feed, S&P 500 movers, trending stocks, instrument popularity, and stock splits.

  • ๐Ÿ“‘ Portfolio & documents โ€” Portfolio historicals, option historicals, account statements, and trade confirmations.

  • ๐Ÿงช Tested and maintained โ€” 212 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 (works for equities and indexes)
chain = client.get_options_chain("SPX", 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()

IRA Trading

pyhood can discover and trade in IRA/retirement accounts โ€” something no other Python Robinhood library supports.

# Discover all accounts (including IRA)
accounts = client.get_all_accounts()

# Check IRA buying power
bp = client.get_buying_power(account_number="YOUR_IRA_ACCOUNT")

# Buy options in your Roth IRA
order = client.buy_option(
    symbol="NKE", strike=55.0, expiration="2026-04-02",
    option_type="call", quantity=3, price=1.60,
    account_number="YOUR_IRA_ACCOUNT",
)

See the Account documentation for details on IRA account discovery and limitations.

Authentication

Robinhood requires device approval on first login. After that, pyhood keeps your session alive automatically.

First Login

  1. Have the Robinhood mobile app open on your phone
  2. Call pyhood.login() โ€” it will trigger a device approval request
  3. Tap "Yes, it's me" in the Robinhood app when prompted
  4. pyhood saves the session token to ~/.pyhood/session.json for 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

Crypto Trading (Official API)

pyhood also supports Robinhood's official Crypto Trading API โ€” no device approval needed, just API keys.

from pyhood.crypto import CryptoClient

# API key auth โ€” generate keys at robinhood.com/account/crypto
crypto = CryptoClient(api_key="rh-api-...", private_key_base64="...")

# Market data
quotes = crypto.get_best_bid_ask("BTC-USD", "ETH-USD")
price = crypto.get_estimated_price("BTC-USD", "buy", 0.001)

# Historical OHLCV data
candles = crypto.get_historicals("BTC-USD", interval="hour", span="week")
for c in candles:
    print(f"{c.begins_at}  O:{c.open_price}  H:{c.high_price}  L:{c.low_price}  C:{c.close_price}")

# Account & holdings
account = crypto.get_account()
holdings = crypto.get_holdings(account.account_number, "BTC")

# Place an order
order = crypto.place_order(
    account_number=account.account_number,
    side="buy",
    order_type="market",
    symbol="BTC-USD",
    order_config={"asset_quantity": "0.001"},
)

Generate your API keys at robinhood.com/account/crypto. See the Crypto documentation for full details.

Futures Trading

pyhood supports Robinhood's futures API โ€” contracts, quotes, orders, and P&L tracking.

client = PyhoodClient(session)

# Contract details
contract = client.get_futures_contract("ESH26")
print(f"{contract.name} โ€” multiplier: {contract.multiplier}")

# Real-time quote
quote = client.get_futures_quote("ESH26")
print(f"Last: {quote.last_price}  Bid: {quote.bid}  Ask: {quote.ask}")

# P&L across all closed futures trades
pnl = client.calculate_futures_pnl()
print(f"Realized P&L: ${pnl:.2f}")

See the Futures documentation for full details.

Banking & Dividends

# Check linked bank accounts
accounts = client.get_bank_accounts()

# View transfer history
transfers = client.get_transfers()

# Initiate a deposit
transfer = client.initiate_transfer(
    amount=500.00,
    direction="deposit",
    ach_relationship_url=accounts[0].url,
)

# Debit card transactions (Cash Management)
txns = client.get_card_transactions()
pending = client.get_card_transactions(card_type="pending")

# Dividend history
dividends = client.get_dividends()
aapl_divs = client.get_dividends_by_symbol("AAPL")

Watchlists

# Get all watchlists
watchlists = client.get_watchlists()

# Get a specific watchlist
default = client.get_watchlist("Default")
print(default.symbols)  # ['AAPL', 'MSFT', ...]

# Add / remove symbols
client.add_to_watchlist(["NVDA", "TSLA"])
client.remove_from_watchlist(["TSLA"])

Markets & Trading Hours

# List available exchanges
markets = client.get_markets()

# Check if NYSE is open on a specific date
hours = client.get_market_hours("XNYS", "2026-03-30")
print(f"Open: {hours.is_open}, {hours.opens_at} โ€” {hours.closes_at}")

Research & Discovery

# Analyst ratings
rating = client.get_ratings("AAPL")
print(f"Buy: {rating.num_buy}, Hold: {rating.num_hold}, Sell: {rating.num_sell}")

# News articles
articles = client.get_news("AAPL")
for a in articles:
    print(f"{a.source}: {a.title}")

# S&P 500 movers
movers = client.get_movers("up")

# Trending stocks (100 most popular on Robinhood)
popular = client.get_tags("100-most-popular")

# How many RH users hold a stock
count = client.get_popularity("AAPL")

# Stock split history
splits = client.get_splits("AAPL")

Portfolio & Option Historicals

# Portfolio value over time
history = client.get_portfolio_historicals(
    account_number="123456", interval="day", span="year",
)
for candle in history:
    print(f"{candle.begins_at}: ${candle.adjusted_close_equity:.2f}")

# Historical option pricing
candles = client.get_option_historicals("option-id-here", interval="day", span="month")

# Account documents (statements, trade confirms, tax docs)
docs = client.get_documents(doc_type="account_statement")

Development Status

  • โœ… Stocks/options market data (unofficial API) โ€” functional (equity + index options)
  • โœ… Futures trading (contracts, quotes, orders, P&L) โ€” functional
  • โœ… Crypto trading (official API) โ€” functional
  • โœ… Authentication with automatic token refresh โ€” functional
  • โœ… Full order management for stocks/options โ€” functional
  • โœ… Banking (ACH transfers, deposits/withdrawals) โ€” functional
  • โœ… Watchlists (create/manage) โ€” functional
  • โœ… Dividends (query history) โ€” functional
  • โœ… Markets/Trading Hours (exchange schedules) โ€” functional
  • โœ… User profile & notification settings โ€” functional
  • โœ… Research & discovery (ratings, news, movers, tags, popularity) โ€” functional
  • โœ… Portfolio historicals & option historicals โ€” functional
  • โœ… Documents & statements โ€” functional
  • โœ… Day trades, margin calls, deposit schedules โ€” functional

Acknowledgments

pyhood 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 pyhood 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. pyhood 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

pyhood-0.7.0.tar.gz (6.9 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyhood-0.7.0-py3-none-any.whl (45.1 kB view details)

Uploaded Python 3

File details

Details for the file pyhood-0.7.0.tar.gz.

File metadata

  • Download URL: pyhood-0.7.0.tar.gz
  • Upload date:
  • Size: 6.9 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pyhood-0.7.0.tar.gz
Algorithm Hash digest
SHA256 4b5e861135ab00742d3508e9eddb142892516340e29e79f133c22d9c0c871e17
MD5 7a80104fb6bf446bf88c6be02ce63db2
BLAKE2b-256 757592b124f92b82c70fa76f31f5c32c06a0487f4f560b4f123e86d510fb190b

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyhood-0.7.0.tar.gz:

Publisher: publish.yml on jamestford/pyhood

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyhood-0.7.0-py3-none-any.whl.

File metadata

  • Download URL: pyhood-0.7.0-py3-none-any.whl
  • Upload date:
  • Size: 45.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pyhood-0.7.0-py3-none-any.whl
Algorithm Hash digest
SHA256 44943cb86dd8a14ce112ee3b6ff88bde91f8b110ef3b32231036daa8a4871cd8
MD5 7c5cefa1f58a3e0046dc69e6fc60993f
BLAKE2b-256 ecc9732fdf173c2e82970f761e14f76475346a92945b87395e039caf7c5dcdac

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyhood-0.7.0-py3-none-any.whl:

Publisher: publish.yml on jamestford/pyhood

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page