
Backtesting a trading strategy, building a research database, or analyzing price behavior all depend on reliable historical market data. Alpaca’s Market Data API provides historical bars, trades, and quotes for stocks, crypto, and options, accessible via REST endpoints and streaming services. You can access this data programmatically using the alpaca-py Python SDK or direct HTTP requests.
This guide covers every historical market data endpoint available through the SDK, organized by asset class. For official endpoint behavior, parameters, and response schemas, keep the Historical API documentation, Alpaca's Trading API Reference, and alpaca-py SDK documentation nearby as you work through the examples. For latest/real-time data and snapshots, see the Real-Time and Snapshot Data documentation.
Prerequisites
You need the following before starting:
- An Alpaca Trading API account (paper trading works for all examples)
- uv Python package manager
- Python 3.10 or later
- Your Alpaca Trading API key and secret key from the Alpaca dashboard
- Google Colab or Code Editor (IDE)
Step 0: Install Dependencies and Import Libraries
Install the alpaca-py SDK and python-dotenv for environment variable management:
!uv pip install alpaca-py python-dotenvStep 1: Set Up Alpaca API Access Using Environment Variables
import os
from dotenv import load_dotenv
import sys
if "google.colab" in sys.modules:
from google.colab import userdata
ALPACA_API_KEY = userdata.get("ALPACA_API_KEY")
ALPACA_SECRET_KEY = userdata.get("ALPACA_SECRET_KEY")
else:
load_dotenv()
ALPACA_API_KEY = os.environ.get("ALPACA_API_KEY")
ALPACA_SECRET_KEY = os.environ.get("ALPACA_SECRET_KEY")Step 2: Set Up the SDK Clients
Alpaca uses separate client classes for each asset class. Initialize them with your credentials:
from alpaca.data.historical.stock import StockHistoricalDataClient
from alpaca.data.historical.crypto import CryptoHistoricalDataClient
from alpaca.data.historical.option import OptionHistoricalDataClient
from alpaca.data.historical.corporate_actions import CorporateActionsClient
stock_data_client = StockHistoricalDataClient(ALPACA_API_KEY, ALPACA_SECRET_KEY, paper=True)
crypto_data_client = CryptoHistoricalDataClient(ALPACA_API_KEY, ALPACA_SECRET_KEY, paper=True)
option_data_client = OptionHistoricalDataClient(ALPACA_API_KEY, ALPACA_SECRET_KEY, paper=True)All endpoints accept symbol_or_symbols as either a single string or a list of strings for multi-symbol queries.
One pattern to note: for stock endpoints, the data feed is passed inside the request object (feed=DataFeed.IEX). For crypto endpoints, the feed is passed as a separate method argument (feed=CryptoFeed.US).
For SDK method details, see the alpaca-py historical stock data reference, the alpaca-py historical crypto data reference, and the alpaca-py GitHub repository.
Stock Endpoints
Stock endpoints use the /v2 path prefix. The Historical Stock Data documentation explains stock feed availability, while the API reference provides endpoint-level details for stock bars, stock trades, and stock quotes. If your workflow needs consolidated US equity coverage through SIP rather than IEX, or overnight historical data through BOATS, review the Market Data API plan comparison before choosing a feed.
Historical Stock Bars
Bars are OHLCV aggregates, the most common data type for charting and backtesting. Timeframes range from one-minute to 12-month intervals. Each bar includes timestamp, open, high, low, close, volume, trade count, and volume-weighted average price (VWAP).
from alpaca.data.requests import StockBarsRequest
from alpaca.data.timeframe import TimeFrame, TimeFrameUnit
from alpaca.data.enums import DataFeed
request = StockBarsRequest(
symbol_or_symbols=["AAPL", "TSLA"],
timeframe=TimeFrame(1, TimeFrameUnit.Day),
start="2024-01-01",
end="2024-01-31",
limit=1000,
feed=DataFeed.IEX,
)
bars = stock_data_client.get_stock_bars(request)For stock-split-adjusted or dividend-adjusted prices, set the adjustment parameter to split, dividend, or all. The default is raw, which returns unadjusted values.
Historical Stock Trades
Historical stock trades return individual executions with price, size, exchange, and condition flags. Use trades when you need the transaction tape for intraday research, volume analysis, or event-level validation instead of pre-aggregated OHLCV bars.
from alpaca.data.requests import StockTradesRequest
trades = stock_data_client.get_stock_trades(
StockTradesRequest(
symbol_or_symbols=["AAPL"],
start="2024-01-03T09:30:00Z",
end="2024-01-03T16:00:00Z",
limit=100,
feed=DataFeed.IEX,
)
)Historical Stock Quotes
Historical stock quotes return bid and ask updates, including National Best Bid and Offer (NBBO) data when available through the selected feed. Use quotes when spread, liquidity, or quote-driven execution context matters more than executed trade prints.
from alpaca.data.requests import StockQuotesRequest
quotes = stock_data_client.get_stock_quotes(
StockQuotesRequest(
symbol_or_symbols=["AAPL"],
start="2024-01-03T09:30:00Z",
end="2024-01-03T16:00:00Z",
limit=1000,
feed=DataFeed.IEX,
)
)24/5 Overnight Historical Stock Data
For a broader walkthrough of overnight trading behavior, see How to Use 24/5 Trading with Alpaca's Trading API and Dashboard. For the feed-specific rules, including BOATS and Overnight feed usage, see the 24/5 Trading API documentation.
Alpaca's 24/5 overnight session runs from 8:00 PM to 4:00 AM ET and is powered by the Blue Ocean Alternative Trading System (BOATS). For historical overnight stock bars, quotes, and trades, use the BOATS feed by setting feed=DataFeed.BOATS in the request object.
This differs from some latest/real-time overnight endpoints, where free plan users may use feed=overnight for certain data types. For delayed historical overnight requests, use feed=boats; the 24/5 API docs state that feed=overnight will return an error for delayed historical overnight data.
from alpaca.data.requests import StockBarsRequest
from alpaca.data.enums import DataFeed
from alpaca.data.timeframe import TimeFrame, TimeFrameUnit
overnight_bars = stock_client.get_stock_bars(
StockBarsRequest(
symbol_or_symbols=["SPY"],
timeframe=TimeFrame(1, TimeFrameUnit.Hour),
start="2026-01-28T01:00:00Z",
end="2026-01-28T09:00:00Z",
limit=1000,
feed=DataFeed.BOATS,
)
)Use overnight historical data when your research or analytical workflows need to include price action outside regular, pre-market, and after-hours sessions. Overnight liquidity can be lower and spreads can be wider, and price volatility can increase relative to regular-hours trading, so overnight-session data should be evaluated separately from regular-session market activity.
Crypto Endpoints
Crypto endpoints use the /v1beta3 path prefix. Symbols use slash notation (for example, BTC/USD, ETH/USD). The data feed is passed as a method argument rather than inside the request object.
The Historical Crypto Data documentation explains crypto-specific feed behavior and data construction. For endpoint-level parameters and response fields, see the API reference pages for crypto bars, crypto trades, and crypto quotes.
Historical Crypto Bars
Historical crypto bars return OHLCV aggregates for crypto pairs such as BTC/USD over a selected timeframe. Use bars for charting, backtesting, and time-series analysis when you need normalized candles rather than individual trades or bid/ask updates.
Unlike trade data, crypto bars can still be populated during intervals with no executions. When no trades occur within a bar interval, bar prices are derived from quote midpoints rather than trade prices.
from alpaca.data.requests import CryptoBarsRequest
from alpaca.data.enums import CryptoFeed
bars = crypto_data_client.get_crypto_bars(
CryptoBarsRequest(
symbol_or_symbols=["BTC/USD", "ETH/USD"],
timeframe=TimeFrame(1, TimeFrameUnit.Hour),
start="2024-01-01",
end="2024-01-31",
),
feed=CryptoFeed.US,
)Historical Crypto Trades
Historical crypto trades return individual executed transactions with price, size, timestamp, and related trade fields. Use trades for tick-level backtests, volume studies, or market microstructure analysis where each execution matters.
from alpaca.data.requests import CryptoTradesRequest
trades = crypto_data_client.get_crypto_trades(
CryptoTradesRequest(
symbol_or_symbols=["BTC/USD"],
start="2024-01-03T00:00:00Z",
end="2024-01-04T00:00:00Z",
limit=1000,
),
feed=CryptoFeed.US,
)Historical Crypto Quotes
Historical crypto quotes return bid and ask updates over time, not executed trades. Use quotes to analyze spreads, liquidity, and quote midpoint behavior, or to understand how quote data differs from bars and trades.
from alpaca.data.requests import CryptoQuoteRequest
quotes = crypto_data_client.get_crypto_quotes(
CryptoQuoteRequest(
symbol_or_symbols=["BTC/USD"],
start="2024-01-03T00:00:00Z",
end="2024-01-04T00:00:00Z",
limit=1000,
),
feed=CryptoFeed.US,
)Options Endpoints
Options market data endpoints use the /v1beta1 path prefix. Historical options data has been available since February 2024. See the Historical Option Data documentation for coverage and feed details, and the API reference pages for option chain and historical option bars for endpoint-level parameters. Option contract metadata is different: it is a Trading API endpoint under /v2/options/contracts. For OPRA access and options market data plan differences, compare the available Market Data API plans.
Option contract symbols follow the OCC format: underlying symbol, expiration date (YYMMDD), call or put indicator (C/P), and strike price (eight digits, multiplied by 1,000). For example, SPY250613C00700000 represents an SPY call expiring June 13, 2025, with a $700 strike.
Option Chain
The option chain endpoint returns data for all contracts matching your filter criteria. You can filter by contract type, strike price range, and expiration date range.
from alpaca.data.requests import OptionChainRequest
from alpaca.data.enums import OptionsFeed
from alpaca.trading.enums import ContractType
chain = option_data_client.get_option_chain(
OptionChainRequest(
underlying_symbol="SPY",
feed=OptionsFeed.INDICATIVE,
type=ContractType.CALL,
expiration_date_gte="2025-06-01",
expiration_date_lte="2025-07-01",
strike_price_gte=680.0,
strike_price_lte=720.0,
)
)Option Contracts (Metadata)
Option contract metadata (expiration, strike, type, status) is available through the TradingClient rather than the data clients. This endpoint returns contract definitions, not market data.
from alpaca.trading.client import TradingClient
from alpaca.trading.requests import GetOptionContractsRequest
from alpaca.trading.enums import ContractType
trade_client = TradingClient(ALPACA_API_KEY, ALPACA_SECRET_KEY, paper=True)
response = trade_client.get_option_contracts(
GetOptionContractsRequest(
underlying_symbols=["SPY"],
expiration_date_gte="2025-06-01",
expiration_date_lte="2025-07-01",
strike_price_gte="680",
strike_price_lte="700",
type=ContractType.CALL,
limit=100,
)
)
contracts = response.option_contractsData Feeds, Pagination, and Common Parameters
Data Feeds
Different feeds offer different coverage and access levels:
- IEX (free): IEX exchange data, approximately 2.5% of US equity volume. Available to all accounts without a paid subscription.
- SIP (paid): Consolidated feed from all US exchanges, covering 100% of market volume. Requires an Algo Trader Plus subscription.
- BOATS (overnight stocks): Blue Ocean ATS data for the overnight stock session. Use
feed=boatsfor historical overnight bars, quotes, and trades. - Overnight (latest/real-time overnight stocks): Derived overnight feed used for certain latest bars, latest quotes, latest trades, and snapshots on the Free plan. Do not use it for delayed historical overnight requests.
- Indicative (free, options): Derivative of the OPRA feed with 15-minute delayed quotes.
- OPRA (paid, options): Official consolidated options pricing feed.
Free-plan users accessing SIP or OPRA data for recent timestamps receive an error. Data older than 15 minutes is accessible on all feeds. For 24/5 historical overnight stock data, use feed=boats; for certain latest/real-time overnight stock endpoints, the correct feed depends on your market data plan. If you need higher market data limits, SIP stock data, OPRA options data, overnight BOATS access, or expanded real-time access, use the Market Data API plans page to confirm which plan matches your use case before changing the feed value in your requests.
Pagination
When a response exceeds the limit, a next_page_token is included. Pass it as page_token in the next request to retrieve the following page. Repeat until no token is returned. The limit parameter accepts values from 1 to 10,000.
Other Shared Parameters
- timeframe:
1Minto59Min,1Hourto23Hour,1Day,1Week,1Monthto12Month - adjustment (stocks only):
raw,split,dividend,all - sort:
ascordesc - asof: Date used for symbol mapping when tickers change (for example, FB renamed to META on 2022-06-09)
- currency: ISO 4217 format for non-USD pricing
Conclusion
With your Alpaca Market Data API configured, you can now:
- Fetch historical bars, trades, and quotes across stocks, crypto, and options
- Include 24/5 overnight stock data in historical research by using the BOATS feed
- Backtest trading strategies using minute-level to monthly aggregates
- Access option chains and contract metadata for derivatives research
- Paginate through large datasets using
next_page_token
If you choose to integrate historical data into a live workflow, the next step is to combine these endpoints with Alpaca's order submission and streaming capabilities. If your strategy depends on broader stock coverage, OPRA options data, more API calls, or real-time market data, review Alpaca's Market Data API plans before moving from research to production.
If you would like to learn more about trading algorithmically with Alpaca's Trading API, explore the resources below:
To understand more about Alpaca's Trading API capabilities, explore the following resources:
- How to Start Paper Trading with Alpaca's Trading API
- Build a Free RSI and MACD Trading Bot with ChatGPT and Alpaca
- MCP-Driven Trading Workflow with Claude, Alpaca, and Google Sheets
- Trading API 30 Common Errors Explained and Troubleshooting
- Alpaca-py GitHub Page
- Alpaca-py Documentation
- Alpaca's Trading API Reference
Frequently Asked Questions
What historical market data can I access for free with Alpaca?
Eligible Alpaca accounts can access historical stock data through the IEX exchange feed and historical options data through the Indicative feed (15-minute delayed). Crypto data is also available to all users. SIP stock data and OPRA options data require an Algo Trader Plus subscription, though data older than 15 minutes is accessible on all feeds.
How do I fetch historical stock price bars using the alpaca-py Python SDK?
Import StockHistoricalDataClient and StockBarsRequest from the alpaca-py SDK. Create a client with your API key and secret, then call get_stock_bars() with a StockBarsRequest that specifies your symbols, timeframe, start date, end date, and data feed. Each bar includes timestamp, open, high, low, close, volume, trade count, and VWAP.
Does Alpaca provide historical data for crypto and options?
Yes. Crypto historical data (bars, trades, and quotes) is available through the /v1beta3 endpoint for pairs like BTC/USD and ETH/USD. Options historical data (option chains and contract metadata) is available through the /v1beta1 endpoint for contracts in OCC format. Options data has been available since February 2024.
What is the difference between SIP and IEX data feeds?
IEX provides data from the IEX exchange only, covering approximately 2.5% of US equity volume. It is free for all Alpaca users. SIP is the consolidated feed from all US exchanges, covering 100% of market volume. SIP requires an Algo Trader Plus subscription for real-time access.
How do I fetch historical overnight stock data for 24/5 trading?
Use the stock historical bars, quotes, or trades endpoints with feed=DataFeed.BOATS. BOATS is the feed used for historical overnight stock market data. Do not use feed=DataFeed.OVERNIGHT for delayed historical overnight requests; the 24/5 docs specify that delayed historical overnight data should use feed=boats.
How do I paginate through large historical data responses?
When a response contains more records than the limit parameter allows, Alpaca includes a next_page_token in the response. Pass that token as the page_token parameter in your next request to retrieve the following page. Repeat until no next_page_token is returned.
What timeframes are available for historical bar data?
Alpaca supports timeframes ranging from one-minute to 12-month intervals. Minute-level bars range from 1Min to 59Min, hourly bars from 1Hour to 23Hour, and calendar-based bars include 1Day, 1Week, and 1Month through 12Month.
Related Articles
- How to Get Alpaca's Trading API Key and Start Connecting
- How to Start Paper Trading with Alpaca's Trading API
- How to Fund Your Alpaca Live Trading Account
- How to Use 24/5 Trading with Alpaca's Trading API and Dashboard
- Alpaca Launches 24/5 Trading For Trading API Providing Near Round-the-Clock Access
- How to Build a Free RSI and MACD Trading Bot with ChatGPT and Alpaca
- Backtesting 0DTE Options: The Complete Guide to Strategy, Setup & Performance
- How to Fix Common Trading API Errors at Alpaca
- 13 Order Types You Should Know About
Backtesting a trading strategy, building a research database, or analyzing price behavior all depend on reliable historical market data.
This content is for informational and educational purposes only, and the examples provided are illustrative in nature and should not be construed as investment advice, trading recommendations, or an endorsement of any security, strategy, or market participant. Historical market behavior and backtesting results have inherent limitations and do not guarantee future performance or outcomes.
All investments involve risk, and the past performance of a security, or financial product does not guarantee future results or returns. There is no guarantee that any investment strategy will achieve its objectives. Please note that diversification does not ensure a profit, or protect against loss. There is always the potential of losing money when you invest in securities, or other financial products. Investors should consider their investment objectives and risks carefully before investing.
The Paper Trading API is offered by AlpacaDB, Inc. and does not require real money or permit a user to transact in real securities in the market. Providing use of the Paper Trading API is not an offer or solicitation to buy or sell securities, securities derivatives, or futures products of any kind, or any type of trading or investment advice, recommendation, or strategy, given or in any manner endorsed by AlpacaDB, Inc. or any AlpacaDB, Inc. affiliate and the information made available through the Paper Trading API is not an offer or solicitation of any kind in any jurisdiction where AlpacaDB, Inc. or any AlpacaDB, Inc. affiliate (collectively, "Alpaca") is not authorized to do business.
Orders placed outside regular trading hours (9:30 a.m. – 4:00 p.m. ET) may experience price fluctuations, partial executions, or delays due to lower liquidity and higher volatility. Orders not designated for extended hours execution will be queued for the next trading session. Additionally, fractional trading may be limited during extended hours. For more details, please review Alpaca Extended Hours & Overnight Trading Risk Disclosure.
Options trading is not suitable for all investors due to its inherent high risk, which can potentially result in significant losses. Please read Characteristics and Risks of Standardized Options before investing in options.
Commission free trading is available to Alpaca's retail customers. Commission free trading means that there are no commission charges for Alpaca self-directed individual cash brokerage accounts that trade U.S.-listed securities and options through an API. However, certain arrangements with authorized business partners or the use of the Elite Smart Router as part of the Alpaca Elite offering may preclude commission free trades by Alpaca Securities. Please refer to the Brokerage Fee Schedule for more information. Relevant regulatory fees may apply. Alpaca reserves the right to charge additional fees if it is determined that order flow is non-retail in nature.
Cryptocurrency is highly speculative in nature, involves a high degree of risks, such as volatile market price swings, market manipulation, flash crashes, and cybersecurity risks. Cryptocurrency regulations are continuously evolving, and it is your responsibility to understand and abide by them. Cryptocurrency trading can lead to large, immediate and permanent loss of financial value. You should have appropriate knowledge and experience before engaging in cryptocurrency trading. For additional information, please click here.