Receive real-time marketplace events over WebSocket using the OpenSea Stream API and the @opensea/sdk/stream client.
What is the Stream API?
The OpenSea Stream API is a WebSocket service that delivers marketplace events in real time, without polling. Subscribe globally or per-collection to receive:
- Item listed, sold, transferred, metadata updated, cancelled
- Item received bid / offer
- Collection offers and trait offers
- Order invalidation and revalidation
Streamed events do not count toward your API rate limits.
The client ships inside
@opensea/sdkat the@opensea/sdk/streamsubpath.The standalone
@opensea/stream-jspackage is deprecated and will not receive further releases. Every event type, payload, andon*method is the same, so migrating is mostly an import change. See the migration guide.
Getting started
Requires Node.js 22 or newer, or any browser. Older Node versions need a WebSocket implementation passed in, see below.
npm install @opensea/sdkNo other dependencies are needed. Earlier versions of this page told Node users to install ws and node-localstorage; neither is required.
Browser and Node.js
The same code works in both. A global WebSocket is used automatically.
import { OpenSeaStreamClient } from '@opensea/sdk/stream';
const client = new OpenSeaStreamClient({
apiKey: 'YOUR_OPENSEA_API_KEY'
});On a runtime older than Node 22, supply an implementation:
import { OpenSeaStreamClient } from '@opensea/sdk/stream';
import { WebSocket } from 'ws';
const client = new OpenSeaStreamClient({
apiKey: 'YOUR_OPENSEA_API_KEY',
connectOptions: { transport: WebSocket }
});Subscribe to events
// Listen to listings for a specific collection
client.onItemListed('collection-slug', (event) => {
// handle event
});
// Listen to all bids across all collections
client.onItemReceivedBid('*', (event) => {
// handle event
});
// Unsubscribe
const unsubscribe = client.onItemMetadataUpdated('collection-slug', handler);
unsubscribe();Several event types at once, filtered server-side, with one callback:
import { OpenSeaStreamClient, EventType } from '@opensea/sdk/stream';
client.onEvents(
'collection-slug',
[EventType.ITEM_SOLD, EventType.ITEM_CANCELLED],
(event) => {
// event.event_type tells you which arrived
}
);The client reconnects with backoff and re-subscribes to every topic it was watching, so a dropped connection recovers on its own.
Using without the SDK
Any language with a WebSocket client can connect directly.
- Endpoint:
wss://stream-api.opensea.io/socket/websocket?token=<API_KEY>&vsn=2.0.0 - Subscribe: send
["1", "1", "collection:<slug>", "phx_join", {}] - Unsubscribe: send the same frame with
"phx_leave"in place of"phx_join" - Heartbeat: send
[null, "2", "phoenix", "heartbeat", {}]every 30 seconds, and reconnect if a reply does not arrive before the next one is due
Frames are JSON arrays of [join_ref, ref, topic, event, payload]. The server answers a join with a reply frame carrying a status:
["1", "1", "collection:doodles-official", "phx_reply", {"status": "ok", "response": {}}]Events then arrive on the same topic, with the event name in the fourth position:
["1", null, "collection:doodles-official", "item_listed", {"event_type": "item_listed", "sent_at": "...", "payload": {}}]Note that the server replies with array frames whether or not you pass vsn=2.0.0, so parse responses as arrays either way. Restrict a subscription to specific event types by sending {"event_types": ["item_listed"]} as the join payload instead of {}.
Documentation
Full documentation including event types, example payloads, and configuration options is maintained in the GitHub repository:
github.com/ProjectOpenSea/opensea-sdk
FAQs
Do I need an API key? Yes. Get one at Settings -> Developer.
Do streamed events count toward rate limits? No.
Can events arrive out of order? Yes. Use the event_timestamp field to determine ordering.
Can events be missed? The Stream API is best-effort delivery. Messages lost during connection errors are not re-sent.
I was using @opensea/stream-js. What changes? Install @opensea/sdk, import from @opensea/sdk/stream, and pass apiKey instead of token. Drop ws and node-localstorage if you installed them. The migration guide covers the rest.
