Free learning tools Test your finance and trading knowledge before you build, buy, or automate.
Charles Schwab API · Python

schwabdev vs schwab-py

Both wrap the same Schwab API. The difference is what they make easy — and what they force you to own.

There is no official Charles Schwab Python SDK. The two projects that matter are schwabdev (Tyler Bowers) and schwab-py (Alex Golec). Both are MIT-licensed, both are unofficial, and both speak to api.schwabapi.com. Choosing between them is an architecture decision, not a loyalty test.

At a glance

Dimensionschwabdev 4.0.0schwab-py 1.5.1
DesignBatteries included: client, token manager, streamerThin, unopinionated endpoint wrapper
Python3.11+3.10+
HTTPrequests (sync), aiohttp (async)httpx (sync/async)
Token storageSQLite at ~/.schwabdev/tokens.dbJSON token file
EncryptionOptional Fernet encryptionCustom access functions; encrypt the file yourself
RefreshAutomatic access refresh; refresh-token renewal flowAutomatic refresh via authlib; 6.5-day proactive token age
Order constructionRaw Schwab order dictionariesEquity/options builders, enums, generic builder
StreamingStream/StreamAsync with reconnect/backoff and start_auto()Async StreamClient with per-service handlers
Type safetyRuntime validation in method wrappersStrict enum enforcement by default
Paper tradingNot supported by SchwabNot supported by Schwab
Historical optionsNot provided by APINot provided by API

Authentication and token lifecycle

schwabdev is the lower-friction option. It creates a SQLite database, coordinates refresh across multiple client instances with an exclusive transaction, and can encrypt tokens with a Fernet key. The access token is treated as a 30-minute credential and the refresh token as a seven-day credential; the client refreshes the access token near expiry and renews the refresh token through the authorization flow when it is close to its deadline.

schwab-py is the more transparent option. easy_client() loads or creates a JSON token file, the token includes creation metadata, and the client refreshes it through authlib. The default max_token_age is 6.5 days, so a token close to the seven-day boundary is proactively replaced. For headless deployments, client_from_token_file() is the clean path; for serverless/custom storage, client_from_access_functions() lets you plug in a database or secret manager.

Security is not automatic. Neither library can protect a leaked app secret or a world-readable token file. Use restrictive permissions, encrypt at rest, and never commit credentials.

Market data and options

Both expose the same endpoints: quotes, price history, option chains, expiration chains, movers, market hours and instruments. schwabdev returns a requests.Response; schwab-py returns an httpx.Response. In both cases you call .json() and handle the status yourself (schwab-py users usually call raise_for_status()).

schwab-py adds convenience methods such as get_price_history_every_minute(), get_price_history_every_five_minutes() and get_price_history_every_day(). schwabdev uses a single price_history() with explicit period/frequency arguments. Neither provides historical option pricing; collect forward snapshots if you need an options dataset.

Orders

This is where the libraries diverge most.

# schwab-py: typed builder
from schwab.orders.equities import equity_buy_limit
order = equity_buy_limit("AAPL", 1, 100.00)
client.place_order(account_hash, order)

# schwabdev: raw Schwab payload
order = {
    "orderType": "LIMIT", "session": "NORMAL", "duration": "DAY",
    "orderStrategyType": "SINGLE", "price": "100.00",
    "orderLegCollection": [{
        "instruction": "BUY", "quantity": 1,
        "instrument": {"symbol": "AAPL", "assetType": "EQUITY"},
    }],
}
client.place_order(account_hash, order)

schwab-py wins for order-heavy systems: builders, enums, vertical spreads and a generic builder for complex orders. schwabdev wins when you already generate the exact Schwab JSON or need to pass fields the builder does not expose. In both cases: preview, persist the order ID, reconcile after timeouts, never blind-retry a POST.

Streaming

schwabdev gives you a managed streamer: Stream(client), start(handler), send(level_one_equities(...)), reconnect/backoff, and start_auto() around market hours. It supports level-one equities/options/futures/forex, books, charts, screeners and account activity.

schwab-py gives you an async protocol client: StreamClient(client, account_id=...), one handler per service, await login(), subscription methods, and a handle_message() loop you control. That is better when the stream is one component of a larger asyncio service.

Which should you choose?

If you are building…Choose
A quick quote/option scanner or dashboardschwabdev
A long-running streamer with reconnect logicschwabdev
Async fan-out over many symbolsschwabdev ClientAsync or schwab-py async client
A typed order engine with options spreadsschwab-py
Custom token storage in a secret managerschwab-py access functions
Migrating from tda-apischwab-py
Raw endpoint access with minimal abstractionschwab-py

A practical pattern is to use schwab-py for typed order construction and schwabdev for the streamer, but running two token managers against the same app adds refresh complexity. Pick one primary wrapper unless you have a clear reason to split.

FAQ

Is one more reliable?

Both are thin over the same API. Reliability comes from your retry, reconciliation and token handling, not from the wrapper name. Pin versions and test upgrades.

Which has better documentation?

schwab-py has ReadTheDocs and a migration guide from tda-api. schwabdev has a setup guide, examples, a Discord and a YouTube series. Both are usable; the choice depends on learning style.

Do both support options orders?

Yes, but schwab-py provides explicit vertical-spread builders and enum validation, while schwabdev expects the raw order payload.

Schwab API Python series: Hub | Full tutorial | Setup & OAuth | schwabdev | schwab-py | Comparison

Need a Schwab or Multi-Broker Architecture?

We build Python execution, data and streaming layers for Schwab, Interactive Brokers and MT5 — including token security, reconciliation and risk controls.

Discuss Your Build

Sources: schwabdev and schwab-py. Versions referenced: schwabdev 4.0.0, schwab-py 1.5.1. Both are unofficial, MIT-licensed and not affiliated with Charles Schwab. Not financial advice.

🚀 Invite friends — Earn $5 You both get $5 credit on Go Ad · opencode.ai AI-Powered Coding Agent — Try Free Build apps, fix bugs & ship faster with opencode. Get $5 free credit when you join. × Ad · quo.com QuoPhone — $20 Visa Gift Card Free Sign up to Quo, subscribe 3 months, get a $20 Visa gift card. Atif's referral gift for you. ×