How to use the Alpaca broker API with Python and alpaca-py

How to use the Alpaca broker API with Python and alpaca-py
The Alpaca broker API lets you place stock and crypto orders, read account data, and request market prices from Python without touching a web interface. If you want to automate your trading with Alpaca's Python API, this is the tool that makes it possible. You connect to Alpaca's servers with a pair of API keys, and from there your code can do everything a manual trader does.
Most existing guides on this topic are outdated. They still reference the older alpaca-trade-api package, which Alpaca has replaced with alpaca-py. The code in this article uses the current library so you don't waste time debugging deprecated imports. If you're comparing Alpaca's pricing plans or wondering about fees, those resources cover the business side. This article focuses on the technical side. It shows how to write Python that talks to the broker.
What the Alpaca broker API actually does
Alpaca is a commission-free stock and crypto broker built for developers. Unlike traditional brokers where you log into a website and click "buy," Alpaca exposes a REST API (a way for your code to communicate with its servers over the internet with standard web requests). Anything you would do by hand in the broker dashboard also has a matching API endpoint. You can use Python to place an order or check your balance the same way you'd click buttons on a website.
The API has two main parts. The Trading API handles orders, positions, and account info. The Market Data API serves historical and real-time price data. Both use the same authentication method, an API key and a secret key that you generate from your Alpaca dashboard.
Alpaca also offers paper trading, which is a simulated environment where you can test your code with fake money. The paper trading API works the same way as the live API, but it points to a different server. You can develop and test your entire system before risking real capital. You can set up Alpaca paper trading in Python in a few minutes.
One thing worth knowing up front is that Alpaca stock trading and crypto trading may require different account configurations. Check Alpaca's current documentation to confirm which products your account supports before you assume the stock examples below will work for crypto too.
Setting up your Alpaca broker API environment
Before you write code, create an Alpaca account and generate your API keys. Then install the alpaca-py package.
Create an account. Go to alpaca.markets and sign up. Alpaca supports US users and some international users, but availability depends on your country and the product you want to trade. Check their eligibility page for current details. Once you're in, navigate to the API Keys section of your dashboard and generate a new key pair. You'll get an API Key ID and a Secret Key. Copy both somewhere safe. The secret key appears only once.
Install the library. Alpaca's current official Python SDK is alpaca-py. Install it with pip.
pip install alpaca-py
Store your keys securely. Never hardcode API keys in your scripts. Use environment variables instead.
export ALPACA_API_KEY="your-api-key-here"
export ALPACA_SECRET_KEY="your-secret-key-here"
Then read them in Python.
import os
API_KEY = os.environ["ALPACA_API_KEY"]
SECRET_KEY = os.environ["ALPACA_SECRET_KEY"]
This keeps your credentials out of your source code and version control.
A complete working example
The example below starts by connecting to Alpaca's simulated account. Then it checks your balance, downloads recent stock prices, places an order, and shows your open positions. Notice that imports starting with alpaca.trading belong to the Trading API, while imports starting with alpaca.data belong to the Market Data API.
Connect and check your account
import os
from alpaca.trading.client import TradingClient
API_KEY = os.environ["ALPACA_API_KEY"]
SECRET_KEY = os.environ["ALPACA_SECRET_KEY"]
# paper=True connects to the simulated environment
trading_client = TradingClient(API_KEY, SECRET_KEY, paper=True)
account = trading_client.get_account()
print(f"Cash available: ${account.cash}")
print(f"Portfolio value: ${account.portfolio_value}")
print(f"Buying power: ${account.buying_power}")
The TradingClient handles authentication and request formatting. Setting paper=True points all requests to Alpaca's paper trading servers. The get_account() method returns your account details. That includes your cash balance and your buying power, which means how much you can spend on new trades.
Fetch historical price data
from alpaca.data.historical import StockHistoricalDataClient
from alpaca.data.requests import StockBarsRequest
from alpaca.data.timeframe import TimeFrame
from datetime import datetime
data_client = StockHistoricalDataClient(API_KEY, SECRET_KEY)
request_params = StockBarsRequest(
symbol_or_symbols="AAPL",
timeframe=TimeFrame.Day,
start=datetime(2024, 1, 1),
end=datetime(2024, 1, 31),
)
bars = data_client.get_stock_bars(request_params)
df = bars.df
print(df.head())
print(f"\nAverage closing price: ${df['close'].mean():.2f}")
The StockHistoricalDataClient is separate from the trading client because data and trading are different API services. The StockBarsRequest tells Alpaca what data to return. You choose the symbol and the time interval (daily, in this case). A bar is one time bucket of price data that contains the open, high, low, and close values for that period.
Alpaca timestamps all market data in UTC (Coordinated Universal Time), and daily bars follow actual market sessions rather than calendar days. If your date range includes weekends or holidays, you'll get fewer rows than you might expect. The result converts directly to a pandas DataFrame. If you request more than one symbol, the DataFrame will have a multi-level index, which means the symbol becomes the first index level, so keep that in mind when you expand beyond this single-stock example.
Place an order
from alpaca.trading.requests import MarketOrderRequest
from alpaca.trading.enums import OrderSide, TimeInForce
market_order_request = MarketOrderRequest(
symbol="AAPL",
qty=1,
side=OrderSide.BUY,
time_in_force=TimeInForce.DAY,
)
market_order = trading_client.submit_order(order_data=market_order_request)
print(f"Order submitted: {market_order.id}")
print(f"Status: {market_order.status}")
MarketOrderRequest creates a buy order for 1 share of AAPL at the current market price. A market order does not guarantee a specific price. It executes at the best available price when the order reaches the exchange, which may differ from the quote you saw a moment earlier. TimeInForce.DAY means the order expires at market close if it hasn't filled. Another common option is GTC (good till canceled), which keeps the order active until you cancel it.
If you want to buy a fraction of a share, Alpaca supports that for many stocks. Use the notional parameter instead of qty to specify a dollar amount. For example, notional=50.00 buys $50 worth of the stock regardless of the share price.
For limit orders, where you set the maximum price you're willing to pay, use LimitOrderRequest.
from alpaca.trading.requests import LimitOrderRequest
limit_order_request = LimitOrderRequest(
symbol="AAPL",
qty=1,
side=OrderSide.BUY,
time_in_force=TimeInForce.DAY,
limit_price=150.00,
)
limit_order = trading_client.submit_order(order_data=limit_order_request)
After you submit an order, the initial status is usually "new" or "accepted." To confirm whether it actually filled, fetch the order again by its ID.
updated_order = trading_client.get_order_by_id(market_order.id)
print(f"Current status: {updated_order.status}")
Possible statuses include new, accepted, partially_filled, filled, canceled, and rejected.
Check your positions
positions = trading_client.get_all_positions()
for position in positions:
profit_loss = float(position.unrealized_pl)
print(
f"{position.symbol}: {position.qty} shares, "
f"Unrealized profit/loss: ${profit_loss:.2f}"
)
This loops through every stock you currently hold and prints the unrealized profit or loss, which means how much you'd gain or lose if you sold right now. The unrealized_pl field is a string by default, so you cast it to float for formatting.
Cancel an order
# Cancel a specific order by ID
trading_client.cancel_order_by_id(market_order.id)
# Or cancel all open orders at once
trading_client.cancel_orders()
Handling errors from the Alpaca broker API
When something goes wrong, the API raises an exception. Missing keys, invalid symbols, and rejected orders all produce errors that will crash your script if you don't handle them. Wrap your API calls in a try/except block to catch these gracefully.
from alpaca.common.exceptions import APIError
try:
bad_order = MarketOrderRequest(
symbol="FAKESYMBOL",
qty=1,
side=OrderSide.BUY,
time_in_force=TimeInForce.DAY,
)
trading_client.submit_order(order_data=bad_order)
except APIError as e:
print(f"Alpaca rejected the request: {e}")
This prevents your program from crashing and gives you a readable error message instead.
Common mistakes and how to avoid them
Using the old library. If you see import alpaca_trade_api in a tutorial, that code is outdated. The current package is alpaca-py, imported as from alpaca.trading.client import TradingClient. The old library still installs, but Alpaca no longer maintains it.
Forgetting market hours. The US stock market is open from 9:30 AM to 4:00 PM Eastern, Monday through Friday. If you submit a market order outside those hours without enabling extended-hours trading, it will queue until the next open.
clock = trading_client.get_clock()
print(f"Market is {'open' if clock.is_open else 'closed'}")
print(f"Next open: {clock.next_open}")
Mixing up paper and live keys. Paper trading and live trading use separate API credentials. If you use live keys with paper=True, or paper keys with paper=False, your requests will fail. Make sure the key pair matches the environment you're targeting.
Not using paper trading first. Every example in this article uses paper=True. When you're ready for real money, change that to paper=False and use your live API keys. Test thoroughly before you make that switch. A bug in your order logic with real money is an expensive lesson.
Hitting rate limits. Alpaca limits how many API requests you can make per minute. If your script requests data in a loop, add a small delay between requests so Alpaca doesn't block you temporarily. Something like time.sleep(0.5) between iterations is a reasonable starting point for simple scripts, though exact limits depend on the endpoint and your plan.
If you want to build a more complete trading strategy with Alpaca, the next step is to connect the data code with the order code and write rules that decide when to buy or sell. You can also explore basic trading algorithms in Python for ideas on where to start.
Next steps
The free Algorithmic Trading With Python guides go deeper on this. They show how to write trading rules, test them against historical prices, and run them as complete programs.