Matrix JavaScript SDK
The Matrix JavaScript SDK (`matrix-js-sdk`) is the official client-server SDK for interacting with the Matrix open standard for secure, decentralized communication. It provides a comprehensive API for building Matrix clients, bots, and integrations, supporting both browser and Node.js environments. The current stable version is 41.3.0, with frequent release candidates like 41.4.0-rc.0 incorporating the latest Matrix specification updates and features. The project is actively maintained and sponsored by Element, who leverage it in their flagship web and desktop clients. Key differentiators include its robust end-to-end encryption support, comprehensive implementation of the Matrix client-server API, and its role as the foundational library for numerous Matrix ecosystem projects.
Common errors
-
TypeError: client.publicRooms is not a function
cause The `client` object was not correctly initialized, or `createClient` did not return a valid instance. This can happen if `createClient` fails or is not correctly imported.fixEnsure `import { createClient } from 'matrix-js-sdk';` or `import * as sdk from 'matrix-js-sdk';` is used and `sdk.createClient({...})` is called with valid configuration parameters. -
Error: XMLHttpRequest is not defined
cause Attempting to run browser-specific code in a Node.js environment without appropriate polyfills or a custom HTTP client configured. `matrix-js-sdk` by default tries to detect the environment.fixEnsure your Node.js environment is configured correctly. If you're encountering this, you might be using an outdated version of `matrix-js-sdk` in Node.js, or trying to use a browser-specific build. Check the SDK's documentation for Node.js setup specifics, which might involve configuring a Node.js-specific HTTP client. -
Error: Sync state: ERROR
cause The client failed to complete its initial sync or encountered a persistent error during synchronization with the Matrix home server. This can be due to network issues, invalid credentials, server errors, or misconfigured `baseUrl`.fixCheck your `baseUrl` for correctness. Verify network connectivity to the Matrix home server. If using authentication, ensure user ID and access token are valid. Inspect the `res` object passed to the `ClientEvent.sync` listener for more specific error details from the server. -
Failed to decrypt message
cause This common error in E2E-enabled rooms indicates that the client could not decrypt an incoming message. Reasons include missing encryption keys, unverified devices, corrupted device lists, or an improperly configured `cryptoStore`.fixEnsure `cryptoStore` is provided during `createClient` initialization. Verify all participating devices in the room are cross-signed and trusted. If a device is new, it might need to wait for key sharing or be verified. Check key backups if applicable.
Warnings
- breaking Version 41.0.0 introduced support for Matrix Specification v1.13, which may involve breaking changes to API endpoints or expected data structures due to underlying spec updates. Developers should review the Matrix spec changes for v1.13 and test their applications thoroughly when upgrading from pre-v41.0.0 versions.
- gotcha The SDK guarantees feature support for at least 4 Matrix spec releases. Features removed from the Matrix spec may be eligible for removal from the SDK after this grace period, even without being explicitly marked as 'breaking changes' in the SDK's changelog. This means long-term applications might need to periodically review their usage of older Matrix features.
- gotcha Using authenticated media endpoints requires explicit configuration. If not configured, requests for media (images, files, avatars) might fail or result in unauthenticated access errors.
- gotcha End-to-End Encryption (E2E) support is robust but not enabled by default and requires proper setup, including providing a `cryptoStore` during client creation. Incorrect or incomplete E2E setup can lead to message decryption failures or inability to participate in encrypted rooms.
- gotcha The SDK requires Node.js version 22.0.0 or higher for Node.js environments. Using older Node.js versions may lead to unexpected errors, build failures, or runtime inconsistencies.
Install
-
npm install matrix-js-sdk -
yarn add matrix-js-sdk -
pnpm add matrix-js-sdk
Imports
- sdk
const sdk = require('matrix-js-sdk');import * as sdk from 'matrix-js-sdk';
- createClient
import createClient from 'matrix-js-sdk';
import { createClient, ClientEvent, RoomEvent } from 'matrix-js-sdk'; - MatrixClient
import type { MatrixClient } from 'matrix-js-sdk';
Quickstart
import * as sdk from "matrix-js-sdk";
import { ClientEvent, RoomEvent } from 'matrix-js-sdk';
const client = sdk.createClient({
baseUrl: "https://matrix.org",
// Store client data in local storage or a custom store
// localStorage is often used in browsers, for Node.js consider 'matrix-js-sdk/lib/nodejs-sdk/src/node-crypto-store'
store: new sdk.MemoryStore(),
// For E2E, a crypto store is essential
cryptoStore: new sdk.MemoryCryptoStore(),
});
client.once(ClientEvent.SYNC_STATE, async (state, prevState, res) => {
if (state === "PREPARED") {
console.log("Client prepared and synced.");
// Example: Listen for new messages
client.on(RoomEvent.Timeline, function (event, room, toStartOfTimeline) {
if (event.getType() !== "m.room.message" || toStartOfTimeline) {
return; // Only process new messages, not historical ones on initial sync
}
console.log(`[${room.name || room.roomId}] <${event.getSender()}> ${event.getContent().body}`);
});
// Example: Get public rooms
client.publicRooms(function (err, data) {
if (err) {
console.error("Error fetching public rooms:", err);
return;
}
console.log("Public Rooms:", data.chunk.map(r => r.name));
});
// To send a message (requires authentication and a joined room)
// const roomId = "!yourroomid:matrix.org";
// const content = {
// body: "Hello from matrix-js-sdk!",
// msgtype: "m.text",
// };
// try {
// await client.sendEvent(roomId, "m.room.message", content, "");
// console.log("Message sent!");
// } catch (e) {
// console.error("Error sending message:", e);
// }
} else {
console.log(`Sync state changed to: ${state}`);
}
});
console.log("Starting client...");
client.startClient({
initialSyncLimit: 10,
// Set `syncFromTokens` to `false` for new clients, `true` for resuming existing sessions
syncFromTokens: false,
}).catch(e => console.error("Failed to start client:", e));