Polymarket.Client.Websocket
1.1.1
dotnet add package Polymarket.Client.Websocket --version 1.1.1
NuGet\Install-Package Polymarket.Client.Websocket -Version 1.1.1
<PackageReference Include="Polymarket.Client.Websocket" Version="1.1.1" />
<PackageVersion Include="Polymarket.Client.Websocket" Version="1.1.1" />
<PackageReference Include="Polymarket.Client.Websocket" />
paket add Polymarket.Client.Websocket --version 1.1.1
#r "nuget: Polymarket.Client.Websocket, 1.1.1"
#:package Polymarket.Client.Websocket@1.1.1
#addin nuget:?package=Polymarket.Client.Websocket&version=1.1.1
#tool nuget:?package=Polymarket.Client.Websocket&version=1.1.1

Polymarket websocket API client
This is a C# implementation of the Polymarket websocket APIs:
License
Apache License 2.0
Features
- installation via NuGet (Polymarket.Client.Websocket)
- public market API, authenticated user API, sports API, and RTDS
- targets
netstandard2.0,netstandard2.1,net6.0,net7.0,net8.0,net9.0,net10.0 - built on Websocket.Client 5.5.0 for websocket transport, reconnects, and lower-allocation message handling
- typed response models: Polymarket stringified prices/sizes are parsed to
decimal, timestamps to integer values, and known sides/statuses/topics to enums - reactive extensions (Rx.NET)
- file communicator for replay/backtesting and data collection pipelines, with tests covering collected public market and RTDS websocket frames
Usage
Market channel:
var assetIds = new[] { "217...token-id" };
var url = PolymarketValues.MarketWebsocketApiUrl;
using var communicator = new PolymarketWebsocketCommunicator(url);
using var client = new PolymarketWebsocketClient(communicator);
client.Streams.OrderBookStream.Subscribe(book =>
{
Console.WriteLine($"Book {book.AssetId}: bids={book.Bids.Length}, asks={book.Asks.Length}");
});
client.Streams.PriceChangeStream.Subscribe(change =>
{
Console.WriteLine($"Price changes for {change.Market}: {change.PriceChanges.Length}");
});
await communicator.Start();
client.Send(new MarketSubscriptionRequest(assetIds, customFeatureEnabled: true));
client.StartHeartbeat(TimeSpan.FromSeconds(10));
RTDS crypto prices:
var url = PolymarketValues.RtdsWebsocketApiUrl;
using var communicator = new PolymarketWebsocketCommunicator(url);
using var client = new PolymarketWebsocketClient(communicator);
client.Streams.RtdsCryptoPriceStream.Subscribe(price =>
{
Console.WriteLine($"{price.Symbol}: {price.Value}");
});
await communicator.Start();
client.Send(RtdsSubscriptionRequest.Subscribe(RtdsSubscription.CryptoPrices("btcusdt", "ethusdt")));
client.StartHeartbeat(TimeSpan.FromSeconds(5));
User channel:
var auth = new UserAuth("api-key", "secret", "passphrase");
var url = PolymarketValues.UserWebsocketApiUrl;
using var communicator = new PolymarketWebsocketCommunicator(url);
using var client = new PolymarketWebsocketClient(communicator);
client.Streams.UserOrderStream.Subscribe(order =>
{
Console.WriteLine($"{order.Status} {order.Side} order {order.Id}");
});
await communicator.Start();
client.Send(new UserSubscriptionRequest(auth));
client.StartHeartbeat(TimeSpan.FromSeconds(10));
More usage examples:
API coverage
CLOB market channel
| Event | Covered |
|---|---|
book |
yes |
price_change |
yes |
last_trade_price |
yes |
tick_size_change |
yes |
best_bid_ask |
yes |
new_market |
yes |
market_resolved |
yes |
CLOB user channel
| Event | Covered |
|---|---|
order |
yes |
trade |
yes |
Sports channel
| Event | Covered |
|---|---|
| sports result update | yes |
server ping auto-response |
yes |
RTDS
| Topic | Covered |
|---|---|
crypto_prices |
yes |
crypto_prices_chainlink |
yes |
equity_prices live update |
yes |
equity_prices historical snapshot |
yes |
comments |
yes |
Reconnecting
There is a built-in reconnection which invokes after 1 minute (default) of not receiving any messages from the server. It is possible to configure that timeout via communicator.ReconnectTimeout. There is also a stream ReconnectionHappened which sends information about the reconnection type.
You need to resubscribe after reconnection happens. Subscribe to communicator.ReconnectionHappened and send the same subscription request again from that handler.
Polymarket expects client heartbeats:
- market and user channels: send
PINGevery 10 seconds - RTDS: send
PINGevery 5 seconds - sports: server sends
ping; this client automatically responds withpongby default
Use client.StartHeartbeat(...) for market, user, and RTDS channels.
Backtesting
The library is prepared for backtesting and data collection. The dependency between Client and Communicator is via abstraction IPolymarketCommunicator. There are two communicator implementations:
PolymarketWebsocketCommunicator- realtime communication with Polymarket websocket APIsPolymarketFileCommunicator- simulated communication, raw data are loaded from files and streamed
Usage:
var communicator = new PolymarketFileCommunicator
{
FileNames = new[] { "data/polymarket_raw_sample.txt" },
Delimiter = ";;"
};
using var client = new PolymarketWebsocketClient(communicator);
client.Streams.PriceChangeStream.Subscribe(change =>
{
// do something with price changes
});
await communicator.Start();
Multi-threading
Observables from Reactive Extensions are single threaded by default. Your code inside subscriptions is called synchronously as soon as a message comes from the websocket API. If your subscription handler takes a long time, it blocks the receiving method, buffers messages, and can eventually lose messages.
Handle messages on another thread when your processing is expensive:
client
.Streams
.PriceChangeStream
.ObserveOn(TaskPoolScheduler.Default)
.Subscribe(change => { /* process */ });
If you need parallel processing while preserving order for a stream, use synchronization:
private static readonly object Gate = new object();
client
.Streams
.PriceChangeStream
.ObserveOn(TaskPoolScheduler.Default)
.Synchronize(Gate)
.Subscribe(change => { /* process */ });
Pull Requests are welcome!
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 is compatible. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Newtonsoft.Json (>= 13.0.4)
- System.Reactive (>= 6.1.0)
- Websocket.Client (>= 5.5.0)
-
.NETStandard 2.1
- Newtonsoft.Json (>= 13.0.4)
- System.Reactive (>= 6.1.0)
- Websocket.Client (>= 5.5.0)
-
net10.0
- Newtonsoft.Json (>= 13.0.4)
- System.Reactive (>= 6.1.0)
- Websocket.Client (>= 5.5.0)
-
net6.0
- Newtonsoft.Json (>= 13.0.4)
- System.Reactive (>= 6.1.0)
- Websocket.Client (>= 5.5.0)
-
net7.0
- Newtonsoft.Json (>= 13.0.4)
- System.Reactive (>= 6.1.0)
- Websocket.Client (>= 5.5.0)
-
net8.0
- Newtonsoft.Json (>= 13.0.4)
- System.Reactive (>= 6.1.0)
- Websocket.Client (>= 5.5.0)
-
net9.0
- Newtonsoft.Json (>= 13.0.4)
- System.Reactive (>= 6.1.0)
- Websocket.Client (>= 5.5.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Add collected public websocket replay coverage for market and RTDS streams, and use a NuGet.org-compatible README logo URL.