Skip to main content
NOTE: This is the documentation for the websocket channel stock_screener. Websocket access for personal use is only available through the Advanced plan. You can find fully-functional examples that stream data from many channels here: Connect to the websocket URI: wss://api.unusualwhales.com/socket?token=<YOUR_API_TOKEN> then join the stock_screener channel. Each message carries the latest stock screener row for one ticker. This channel is the live counterpart of the /screener/stocks endpoint. A field has the same name and meaning here as in that endpoint’s rows, so see the endpoint for what each field measures.

Delivery characteristics

Read these before writing a client, they are not obvious from the payload:
  • Every message is a complete row. The newest message for a ticker and date replaces every earlier one. The channel never sends a message that removes a row. Key your rows by ticker and date, and drop the rows of an earlier date once a newer one arrives.
  • A ticker is sent up to once a second, whenever any of its inputs updates. A new bid or ask quote counts as an update, so during market hours most actively quoted tickers are sent every second.
  • The channel sends nothing when you join. Load the current rows from /screener/stocks first, and again after every reconnect, then apply the messages from this channel on top.
  • This is a high volume channel. It covers every ticker the screener tracks, and each message is about 5 KB of JSON. When the screener service restarts, every ticker is sent at once, and when the premarket session opens at 04:00 ET most tickers are.
  • Keep this channel on its own connection. A client that does not read the socket fast enough is not disconnected, but frames it cannot keep up with are dropped. The drops hit every channel joined on that connection, not only this one. Enable permessage-deflate if your websocket client supports it.
  • Index prices are withheld. For an index ticker (is_index is true), the channel sends null for the same price fields as /screener/stocks: open, close, high, low, prev_close, intraday_change, week_52_high, week_52_low, bid, ask, the reference closes one_week_close, one_month_close, three_month_close, six_month_close, ytd_close, one_year_close, five_year_close and last_earnings_price, and the returns one_day_perc, one_week_perc, one_month_perc, three_month_perc, six_month_perc, ytd_perc, one_year_perc, five_year_perc and earnings_perc.
  • The channel is global only. There is no stock_screener:<TICKER> variant.

Values

Decimal values are sent as strings, as on /screener/stocks. The technical indicators are JSON numbers. Dates use the YYYY-MM-DD format, and quote_time is a Unix timestamp in milliseconds. Every field is present in every message. An unavailable value is null, with two exceptions. call_volume, put_volume, call_premium, put_premium, bullish_premium, bearish_premium and the six insider_* volumes read 0 (or "0" for the decimals) when no data is available. is_index is false when the issue type is unknown. The technical indicators are flat fields, as on /screener/stocks. For example, MACD is sent as macd_12_26_9, macd_12_26_9_signal and macd_12_26_9_histogram, while the ta_1d_live channel sends one nested macd_12_26_9 object.

Differences from /screener/stocks

  • full_name is always null.
  • These fields of /screener/stocks are not sent: net_premium, z_score, steepness_180_30, missing_periscope and the twelve gex_daily_* fields.
  • net_premium is net_call_premium minus net_put_premium, so you can compute it from this channel.
Payload format (shortened, a real message carries every field listed below):

Fields

Last modified on September 28, 2026