Client SDK

Client SDK

The Client SDK provides everything you need to connect to a Colyseus server from your game or application.


Client Setup

The Client instance is your entry point to connect to the server.

client.ts
import { Client } from "@colyseus/sdk";
const client = new Client("http://localhost:2567");
 
// ... with full-stack type safety (optional)
import type { server } from "../../server/src/app.config.ts";
const client = new Client<typeof server>("http://localhost:2567");

Joining Rooms

Once you have a client, you can join rooms. Choose the method that best fits your matchmaking needs.

The most common way to connect. Joins an existing room if available, or creates a new one.

client.ts
try {
  const room = await client.joinOrCreate("battle", {/* options */});
  console.log("joined successfully", room);
 
} catch (e) {
  console.error("join error", e);
}

Locked or private rooms are ignored by this method.

Other Join Methods

These methods use the same pattern as joinOrCreate. Replace the method name accordingly.

MethodSignatureDescription
createclient.create(roomName, options)Always creates a new room, even if others exist.
joinclient.join(roomName, options)Joins an existing room. Fails if none available. Locked/private rooms are ignored.
joinByIdclient.joinById(roomId, options)Joins a specific room by its unique ID. Private rooms can be joined by ID. Useful for invite links.
consumeSeatReservationclient.consumeSeatReservation(reservation)Joins using a pre-reserved seat from the server. See Matchmaker → Reserve Seat For.

You may disallow the client from creating rooms. See Matchmaker → Restricting the frontend from creating rooms

Example: Creating an invite link with joinById

client.ts
// Share the room ID with other players
const inviteLink = `https://mygame.com/join?roomId=${room.roomId}`;
 
// On the receiving end, parse the room ID and join
const params = new URLSearchParams(window.location.search);
const room = await client.joinById(params.get("roomId"));

Send and Receive Messages

Once connected to a room, you can send and receive messages in real-time, including raw byte payloads and request/response. See Sending & Receiving Messages for the full reference.


Sending Input (Netcode)

For prediction-ready rooms (rooms that call defineInput() on the server), room.input() returns a typed input channel: stage fields on input.data, then input.send() once per fixed step.

client.ts
const input = room.input();   // input schema arrives from the server's defineInput()
 
input.data.moveX = 1;
input.data.jump = true;
input.send();

Inputs are buffered and acknowledged, and power client-side prediction and lag compensation. See room.input(options) for the full reference: reliability modes, redundancy, and the InputHandle surface.

The netcode APIs (room.input(), room.clock, Predict) are available in Colyseus 0.18+ across the official SDKs. See Client Prediction.


State Synchronization

The room state is automatically synchronized from the server to all connected clients. The room.state property always contains the latest state.

Use Callbacks to listen for specific property changes with fine-grained control.

client.ts
import { Callbacks } from "@colyseus/sdk";
 
const callbacks = Callbacks.get(room);
 
callbacks.listen("currentTurn", (currentValue, previousValue) => {
    console.log("Turn changed:", previousValue, "->", currentValue);
});
 
callbacks.onAdd("players", (player, sessionId) => {
    console.log("Player joined:", sessionId);
 
    callbacks.listen(player, "hp", (currentHp, previousHp) => {
        console.log("Player", sessionId, "hp:", currentHp);
    });
});
 
callbacks.onRemove("players", (player, sessionId) => {
    console.log("Player left:", sessionId);
});

See the full State Sync Callbacks documentation for all available methods including listen, onAdd, onRemove, and more.

On State Change

The onStateChange event fires whenever the server synchronizes state updates. Use this when you need to know something changed, without tracking individual properties.

room.onStateChange((state) => {
    console.log("the room state has been updated:", state);
});

Read more about State Synchronization


Connection Lifecycle

Leaving a room, automatic and manual reconnection, error handling, and removing listeners. See Connection Lifecycle & Reconnection for the full reference.


Latency & Server Selection

Measure network latency and choose optimal servers for your players.

Measuring Latency

Before Joining

Create a temporary connection to measure latency before joining a room.

Parameters

  • options.pingCount: Number of pings to send (default: 1). Returns the average latency when greater than 1.
client.ts
const latency = await client.getLatency();
console.log("Latency:", latency, "ms");
 
// With multiple pings for a more accurate average
const avgLatency = await client.getLatency({ pingCount: 5 });
console.log("Average Latency:", avgLatency, "ms");

During a Room Connection

Measure round-trip time on an existing connection.

client.ts
room.ping((latency) => {
  console.log("Latency:", latency, "ms");
});

If the connection is not open, calling ping() has no effect.

Multi-Region Server Selection

Automatically connect to the server with the lowest latency from a list of endpoints.

Parameters

  • endpoints: Array of server endpoints (URLs or endpoint settings objects).
  • options: Optional client options to pass to each client instance.
  • latencyOptions.pingCount: Number of pings to send per endpoint (default: 1).
client.ts
import { Client } from "@colyseus/sdk";
 
// Select the best server from multiple regions
const client = await Client.selectByLatency([
  "https://us-east.gameserver.com",
  "https://eu-west.gameserver.com",
  "https://asia.gameserver.com",
]);
 
// Now use the client with the lowest latency
const room = await client.joinOrCreate("game");

The method logs the latency for each endpoint to the console for debugging purposes. If all endpoints fail to respond, an error is thrown.


HTTP Requests

The client.http utility performs HTTP requests to your server endpoint. The client.auth.token is sent automatically as an Authorization header.

// GET
const response = await client.http.get("/profile");
 
// POST
const response = await client.http.post("/profile", { body: { name: "Jake" } });
 
// PUT
const response = await client.http.put("/profile", { body: { name: "Jake" } });
 
// DELETE
const response = await client.http.delete("/profile");

See Server → HTTP Routes for setting up HTTP endpoints on your server, and Authentication → HTTP Middleware for securing them.


Room Reference

Quick reference for room properties.

PropertyTypeDescription
stateanyThe synchronized room state from the server
sessionIdstringUnique identifier for the current client connection
roomIdstringUnique room ID (shareable for direct joins)
namestringName of the room type (e.g., "battle")
reconnectionTokenstringToken for manual reconnection
reconnectionReconnectionOptionsAutomatic reconnection configuration
clockRoomClockServer time & latency estimates (serverNow(), rtt()). See room.clock

Next Steps