WebSocket Stream

This API provides a WebSocket stream for real-time market data. This allows you to receive the most up-to-date market information, which can be used to power your trading strategies.

The WebSocket stream provides real-time updates of the following market data:

Steps to use the stream

To use the WebSocket stream follow these steps:


To establish a connection use the stream URL depending on the data you'd like to consume. The general schema of the URL is


Sandbox URL:


Any attempt to access a data feed not available for your subscription will result in an error during authentication.

We provide a test stream that is available all the time, even outside market hours, on this URL:


Upon successfully connecting, you will receive the welcome message:



Connection limit

The number of connections to a single endpoint from a user is limited based on the user's subscription, but in most subscriptions (including Algo Trader Plus) this limit is 1. If you try to open a second connection, you'll get this error:

[{"T":"error","code":406,"msg":"connection limit exceeded"}]


You need to authenticate yourself using your credentials. This can be done two ways

Authenticate with HTTP headers

You can set the same headers used for the historical market data and trading endpoints:


Here's an example using a WebSocket client called websocat:

$ websocat wss://stream.data.alpaca.markets/v2/test \

Authenticate with a message

Alternatively, you can authenticate with a message after connection:

{"action": "auth", "key": "{KEY_ID}", "secret": "{SECRET}"}

Keep in mind though, that you only have 10 seconds to do so after connecting.

If you provided correct credentials you will receive another success message:



Congratulations, you are ready to receive real-time market data!

You can send one or more subscription messages. The general format of the subscribe message is this:

  "action": "subscribe",
  "channel1": ["SYMBOL1"],
  "channel2": ["SYMBOL2","SYMBOL3"],
  "channel3": ["*"]

You can subscribe to a particular symbol or to every symbol using the * wildcard. A subscribe message should contain what subscription you want to add to your current subscriptions in your session so you don’t have to send what you’re already subscribed to.

For example in the test stream, you can send this message:


The available channels are described for each streaming endpoints separately.

Much like subscribe you can also send an unsubscribe message that subtracts the list of subscriptions specified from your current set of subscriptions.


After subscribing or unsubscribing you will receive a message that describes your current list of subscriptions.


You will always receive your entire list of subscriptions, as illustrated by the sample communication excerpt below:

> {"action": "subscribe", "trades": ["AAPL"], "quotes": ["AMD", "CLDR"], "bars": ["*"]}
< [{"T":"subscription","trades":["AAPL"],"quotes":["AMD","CLDR"],"bars":["*"],"updatedBars":[],"dailyBars":[],"statuses":[],"lulds":[],"corrections":["AAPL"],"cancelErrors":["AAPL"]}]
> {"action": "unsubscribe", "bars": ["*"]}
< [{"T":"subscription","trades":["AAPL"],"quotes":["AMD","CLDR"],"bars":[],"updatedBars":[],"dailyBars":[],"statuses":[],"lulds":[],"corrections":["AAPL"],"cancelErrors":["AAPL"]}]



Every message you receive from the server will be in the format:

[{"T": "{message_type}", {contents}},...]

Control messages (i.e. where T is error, success or subscription) always arrive in arrays of size one to make their processing easier.

Data points however may arrive in arrays that have a length that is greater than one. This is to facilitate clients whose connection is not fast enough to handle data points sent one by one. Our server buffers the outgoing messages but slow clients may get disconnected if their buffer becomes full.

Content type

You can use the Content-Type header to switch between text and binary message data frame:

  • Content-Type: application/json
  • Content-Type: application/msgpack

Encoding and Compression

Messages over the websocket are in encoded as clear text.

To reduce bandwidth requirements we have implemented compression as per RFC-7692. Our SDKs handle this for you so in most cases you won’t have to implement anything yourself.


You may receive an error during your session. Below are all the errors you may run into.

Error MessageDescription
[{"T":"error","code":400,"msg":"invalid syntax"}]The message you sent to the server did not follow the specification.
⚠️ This can also be sent if the symbol in your subscription message is in invalid format.
[{"T":"error","code":401,"msg":"not authenticated" }]You have attempted to subscribe or unsubscribe before authentication.
[{"T":"error","code":402,"msg":"auth failed"}]You have provided invalid authentication credentials.
[{"T":"error","code":403,"msg":"already authenticated"}]You have already successfully authenticated during your current session.
[{"T":"error","code":404,"msg":"auth timeout"}]You failed to successfully authenticate after connecting. You have a few seconds to authenticate after connecting.
[{"T":"error","code":405,"msg":"symbol limit exceeded"}]The symbol subscription request you sent would put you over the limit set by your subscription package. If this happens your symbol subscriptions are the same as they were before you sent the request that failed.
[{"T":"error","code":406,"msg":"connection limit exceeded"}]You already have an ongoing authenticated session.
[{"T":"error","code":407,"msg":"slow client"}]You may receive this if you are too slow to process the messages sent by the server. Please note that this is not guaranteed to arrive before you are disconnected to avoid keeping slow connections active forever.
[{"T":"error","code":409,"msg":"insufficient subscription"}]You have attempted to access a data source not available in your subscription package.
[{"T":"error","code":410,"msg":"invalid subscribe action for this feed"}]You tried to subscribe to channels not available in the stream, for example to bars in the option stream or to trades in the news stream.
[{"T":"error","code":500,"msg":"internal error"}]An unexpected error occurred on our end. Please let us know if this happens.