Stream API

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/sdk at the @opensea/sdk/stream subpath.

The standalone @opensea/stream-js package is deprecated and will not receive further releases. Every event type, payload, and on* 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/sdk

No 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.