The OpenSea Stream client now 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 shape, and on* method is unchanged. Most projects
need to change two lines.
npm uninstall @opensea/stream-js ws node-localstorage
npm install @opensea/sdk-import { OpenSeaStreamClient } from "@opensea/stream-js";
+import { OpenSeaStreamClient } from "@opensea/sdk/stream";
-const client = new OpenSeaStreamClient({ token: "YOUR_API_KEY" });
+const client = new OpenSeaStreamClient({ apiKey: "YOUR_API_KEY" });The old README told Node users to install both and pass them through
connectOptions:
// No longer necessary
import { WebSocket } from "ws";
import { LocalStorage } from "node-localstorage";
const client = new OpenSeaStreamClient({
token: "YOUR_API_KEY",
connectOptions: { transport: WebSocket, sessionStorage: LocalStorage },
});Node 22 and every browser provide a global WebSocket, which the client uses
automatically:
const client = new OpenSeaStreamClient({ apiKey: "YOUR_API_KEY" });sessionStorage was only ever read by the underlying library's long-poll
fallback, which the OpenSea stream does not use, so node-localstorage was
never doing anything.
On a runtime older than Node 22 you can still supply an implementation:
import { WebSocket } from "ws";
const client = new OpenSeaStreamClient({
apiKey: "YOUR_API_KEY",
connectOptions: { transport: WebSocket },
});token still works and behaves identically, but it is deprecated. The new name
matches OpenSeaAPIConfig.apiKey used everywhere else in the SDK.
It was Partial<SocketConnectOption> borrowed from @types/phoenix. It is now
StreamConnectOptions:
| Option | Status |
|---|---|
transport |
Kept |
params |
Kept |
timeout |
Kept |
heartbeatIntervalMs |
Kept |
reconnectAfterMs |
Kept |
sessionStorage |
Removed, only used by the unused long-poll fallback |
longPollFallbackMs |
Removed, the stream is WebSocket only |
binaryType, vsn, encode, decode |
Removed, the wire format is fixed |
Passing a removed option is a TypeScript error. At runtime unknown keys are ignored, so an unmigrated call site will not crash.
This is a bug fix, and the one behavior change that could affect working code.
Previously every on* method returned a function that left the entire channel
for that collection. Two subscriptions on the same collection meant unsubscribing
from one silently stopped the other:
const stopListings = client.onItemListed("doodles-official", onListing);
client.onItemSold("doodles-official", onSale);
stopListings();
// Before: onSale stopped firing too.
// Now: onSale keeps firing. The topic is left only when its last
// handler is removed.If you were relying on the old behavior to tear down a collection, call every
returned unsubscribe function, or call client.disconnect() to drop everything.
onEvents sends a server-side event filter in its subscription. In
@opensea/stream-js, the first subscriber to a collection fixed that filter, so
this combination silently produced a handler that never fired:
client.onEvents("doodles-official", [EventType.ITEM_SOLD], onSale);
// Before: the server kept filtering to item_sold, so onListing never fired.
// Now: the filter widens and both handlers receive their events.
client.onItemListed("doodles-official", onListing);Widening re-establishes the subscription, so a few events on that collection can be missed in the moment it takes to re-join. Subscribing with the full set up front avoids that:
client.onEvents(
"doodles-official",
[EventType.ITEM_SOLD, EventType.ITEM_LISTED],
handler,
);@opensea/sdk requires Node 22 or newer. Node 20 reached end of life in April
2026 and has no global WebSocket.
The client speaks the protocol directly, so the dependency tree for
@opensea/sdk/stream is empty. Importing the subpath pulls in no ethers, no
seaport, and no third-party runtime code.
- Every
on*method:onItemListed,onItemSold,onItemTransferred,onItemMetadataUpdated,onItemCancelled,onItemReceivedOffer,onItemReceivedBid,onCollectionOffer,onTraitOffer,onOrderInvalidate,onOrderRevalidate, andonEvents. - Every event and payload type, unchanged field for field.
EventType,LogLevel,Network,OnClientEvent, andCallback.connect(),disconnect(), theonErrorandonEventcallbacks, and the"*"wildcard for all collections.- Automatic reconnection with backoff, and re-subscription after a reconnect.
EventType, Trait, TraitOfferEvent, and CollectionOfferEvent exist in
both @opensea/sdk and @opensea/sdk/stream with different shapes. The stream
versions are only exported from the subpath. Import them from
@opensea/sdk/stream, and alias if you need both in one file:
import { EventType as StreamEventType } from "@opensea/sdk/stream";
import { AssetEventType } from "@opensea/sdk";