The short answer: no, Twitter does not use WebSockets
The official X (Twitter) API does not use WebSockets for its streaming endpoints. Instead, it uses HTTP streaming — a long-lived HTTP connection where the server sends data incrementally using chunked transfer encoding. This is a fundamentally different protocol from WebSocket (RFC 6455).
This distinction matters for developers building real-time applications. The protocol you use affects latency, reconnection behavior, bidirectional communication, and how you architect your client code.
How Twitter's HTTP streaming works
When you connect to the X API's filtered stream endpoint (GET /2/tweets/search/stream), your client opens a standard HTTP request. The server responds with status 200 and begins writing newline-delimited JSON — one tweet per line, indefinitely. Think of it as downloading an infinitely long file.
Between tweets, X sends keep-alive signals (empty newlines) approximately every 20 seconds. If your client does not receive any data for 20+ seconds, it should assume the connection is stalled and reconnect.
- Protocol: HTTP/1.1 with chunked transfer encoding
- Data format: Newline-delimited JSON (NDJSON)
- Direction: Server to client only (unidirectional)
- Keep-alive: Empty newlines every ~20 seconds
- Authentication: Bearer token in HTTP Authorization header
- Connection: One long-lived HTTP response, never closes (until error or disconnect)
How WebSocket differs from HTTP streaming
WebSocket (RFC 6455) is a separate protocol that starts as an HTTP upgrade request and then switches to a framed, bidirectional communication channel. Unlike HTTP streaming, WebSocket supports both server-to-client and client-to-server messages on the same connection.
| Feature | HTTP Streaming (X API) | WebSocket (RFC 6455) |
|---|---|---|
| Initial handshake | Standard HTTP request | HTTP Upgrade → ws:// protocol switch |
| Direction | Server → Client only | Bidirectional |
| Data framing | Newline-delimited chunks | Binary/text frames with length headers |
| Keep-alive | Empty newlines (~20s) | Ping/pong frames (built into protocol) |
| Client can send data | No (new HTTP request required) | Yes (same connection) |
| Disconnect detection | Timeout-based (manual) | Close frames + ping/pong (automatic) |
| Browser support | Requires ReadableStream API | Native WebSocket API |
| Reconnection | Manual implementation required | Application-managed: reconnect with backoff when the socket closes |
Why this matters for real-time applications
For trading bots and alert systems, the protocol choice has practical consequences:
- Latency: Both protocols deliver data with similar raw latency. The difference is overhead. WebSocket frames add 2 to 14 bytes each, while HTTP chunked encoding adds a variable amount.
- Reconnection: HTTP streaming has no built-in mechanism to detect stalled connections, so you implement timeout logic. WebSocket ping/pong frames detect dead connections, but your application still reconnects with backoff when the socket closes.
- Bidirectional: With HTTP streaming, subscribing to new accounts or changing filters requires a separate HTTP request. With WebSocket, you can send subscription changes on the same connection.
- Browser compatibility: HTTP streaming requires the ReadableStream API for incremental parsing. WebSocket has native browser support and a simpler API.
- Infrastructure: HTTP streaming connections can be interrupted by proxies, load balancers, and CDNs that expect standard request/response patterns. WebSocket connections are designed for long-lived use.
Code comparison: HTTP streaming vs WebSocket
// HTTP streaming — X API filtered stream
const needle = require('needle');
const STREAM_URL = 'https://api.x.com/2/tweets/search/stream';
function connect() {
const stream = needle.get(STREAM_URL, {
headers: { Authorization: `Bearer ${BEARER_TOKEN}` },
});
// Must parse incrementally — standard fetch() won't work
stream.on('data', (chunk) => {
const line = chunk.toString().trim();
if (!line) return; // Keep-alive newline
const tweet = JSON.parse(line);
console.log(tweet.data.text);
});
// No built-in reconnect — you must handle this yourself
stream.on('error', () => {
console.error('Connection lost, reconnecting...');
setTimeout(connect, 5000);
});
}
connect();// WebSocket — TweetStream (from $199/mo)
function connect() {
const ws = new WebSocket('wss://ws-global.tweetstream.io/ws', [
'tweetstream.v1',
`tweetstream.auth.token.${API_KEY}`,
]);
ws.onmessage = (event) => {
const envelope = JSON.parse(event.data);
if (envelope.t === 'tweet' && envelope.op === 'content') {
console.log(envelope.d.text);
// Enrichment data (tokens, OCR, prices) in meta messages
}
};
// Reconnect in application code when the socket closes
ws.onclose = () => {
console.log('Reconnecting...');
setTimeout(connect, 1000);
};
}
connect();X filtered stream vs a WebSocket feed for trading bots
X's filtered stream sends posts that match rules you write over one long-lived HTTP connection and bills each Post read on pay-per-use. TweetStream sends posts from the X accounts you track over WebSocket for a flat monthly price, with enrichment added to each post. The table compares the parts a trading bot depends on, using X's public docs as checked on 2026-09-30.
| Criterion | X filtered stream (pay-per-use) | TweetStream WebSocket feed |
|---|---|---|
| Connection model | One long-lived HTTP response of newline-delimited JSON; pay-per-use allows 1 connection | WebSocket with JSON envelopes; 3 connections on Minimum and 10 on Pro |
| How you choose accounts | Rules built from operators such as from:username; pay-per-use allows 1,000 rules of up to 1,024 characters | Add X handles in the dashboard, the Discord bot, or the accounts API, up to your plan's account limit |
| Reconnect and backfill | Reconnect when no data or keep-alive arrives for 20 seconds; backfill and recovery of missed posts require Enterprise access | Reconnect with backoff when the socket closes; Pro, Scale, and Ultra Speed can fetch missed posts from the History API |
| Cost basis | $0.005 per Post read, capped at 3M Post reads per billing cycle | Flat monthly plan: $199/mo for 50 accounts on Minimum, $499/mo for 250 on Pro |
| Enrichment | Post fields and expansions you request | OCR text, detected tokens and contracts, token prices, and prediction-market context in follow-up meta envelopes |
The Twitter WebSocket API page covers the payload format and setup steps.
WebSocket services as Twitter streaming alternatives
Several third-party services relay Twitter data over true WebSocket connections, bridging the gap between Twitter's HTTP streaming and the WebSocket protocol that most real-time applications prefer.
TweetStream, for example, delivers monitored X/Twitter alerts to your application over a standard WebSocket connection. This gives you the familiar WebSocket API (onopen, onmessage, onclose) plus content/update/delete/pin/unpin events, profile/follow/unfollow events, and enrichment like OCR, token detection, and live prices.
- Standard WebSocket API — no HTTP streaming parsing required
- Straightforward reconnect handling in client code
- Rolling server detection before enrichment updates
- Starts at $199/month
- Bidirectional: subscribe to accounts and change filters on the same connection
Put this workflow into production faster
This guide covers the workflow. TweetStream handles monitored-post ingestion, token detection, and OCR, then delivers posts, updates, deletes, pins, profile changes, follows, unfollows, and enriched JSON payloads over WebSocket. Supported plans also include history. Your client reconnects the WebSocket as documented and routes received events downstream. Start a 3-day trial with your own accounts.
Start 3-day trial