# Matrix Public Rooms Extractor (`datamule/matrix-publicrooms-extractor`) Actor

Point at ANY Matrix homeserver and extract its public room directory over the Client-Server API. One row per room: room ID, name, topic, member count, canonical alias, avatar, join rule, room type. Opaque next\_batch pagination; optional token unlocks search/space filters.

- **URL**: https://apify.com/datamule/matrix-publicrooms-extractor.md
- **Developed by:** [Datamule](https://apify.com/datamule) (community)
- **Categories:** Developer tools, Social media
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.35 / 1,000 room records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Matrix Public Rooms Extractor

Point at **any Matrix homeserver** and extract its **public room directory** — the
list of rooms that homeserver publishes to the federation — over the Matrix
Client-Server API (`GET /_matrix/client/v3/publicRooms`). One structured row per
public room, paginated through the server's own opaque `next_batch` cursor.

Works against any Matrix homeserver (Synapse, Dendrite, Conduit, …) — they all
speak the same Client-Server directory contract, so one actor reads them all:
matrix.org, matrix.tchncs.de, gnome.modular.im, mozilla.modular.im,
fedora.ems.host, and thousands more.

### What you get

One row per public room, keyed on the always-present `room_id`:

| Field | Description |
|-------|-------------|
| `room_id` | Canonical room ID (e.g. `!abc:matrix.org`) — always present |
| `name` | Room display name (nullable — many rooms are unnamed) |
| `topic` | Room topic / description (nullable) |
| `canonical_alias` | Human alias, e.g. `#community:matrix.org` (nullable) |
| `num_joined_members` | Joined member count (may be 0) |
| `avatar_url` | Room avatar `mxc://` URI (nullable) |
| `world_readable` | Whether history is world-readable |
| `guest_can_join` | Whether guests may join |
| `join_rule` | e.g. `public`, `knock`, `invite` (nullable) |
| `room_type` | e.g. `m.space` for spaces; null for regular rooms |
| `_homeserverUrl` / `_server` / `_page` / `_rowIndex` / `_totalRoomCountEstimate` | Provenance |

### Input

| Field | Required | Description |
|-------|----------|-------------|
| `homeserverUrl` | ✅ | Homeserver base URL, e.g. `https://matrix.org` |
| `server` | | Query a **different** server's directory through this homeserver (`?server=`) — usually needs a token |
| `search` | | Full-text filter over name/alias/topic — uses POST, usually needs a token |
| `roomType` | | `all` (default) · `spaces` (m.space only) · `rooms` (exclude spaces) |
| `accessToken` | | Matrix access token — unlocks search / room-type filters / federated queries |
| `maxRecords` | | Stop after N rooms (default 2000) |
| `pageSize` | | Rooms per page (default 100; server may cap lower) |

#### Anonymous vs authenticated

The **anonymous `GET` listing works on any homeserver that publishes its
directory publicly** — no token needed. The Matrix spec routes full-text
**search**, **room-type filters**, and **federated `?server=` queries** through
the `POST` endpoint, which **most homeservers gate behind an access token**
(they return `M_MISSING_TOKEN`). Supply `accessToken` to use those; leave it
empty for a plain public-directory listing.

### Example

```json
{
  "homeserverUrl": "https://matrix.org/",
  "maxRecords": 100
}
```

### Use cases

- **Federation monitoring** — track which rooms a homeserver publishes over time.
- **Community discovery** — enumerate spaces and rooms across the Matrix network.
- **Moderation intelligence** — surface newly-published rooms, aliases, topics.
- **Directory research** — member-count and room-type distributions per server.

### How it works

- Anonymous `GET /_matrix/client/v3/publicRooms` by default; `POST` with a
  `filter` only when `search` / `roomType` is set.
- Opaque-cursor pagination: the response `next_batch` is echoed as the next
  request's `since`; the walk stops when the server omits it. The
  `total_room_count_estimate` is treated as a hint, never a page terminator.
- Rate limits (`M_LIMIT_EXCEEDED`) are honored via `retry_after_ms` backoff.
- Fails fast (never a fabricated empty success) if the homeserver is unreachable,
  rejects the query (auth/forbidden), or the directory matched zero rooms.

### Pricing

Pay-per-event: **$0.0005 per room record** (tiered volume discount by
subscription tier). You pay only for rooms actually emitted.

# Actor input Schema

## `homeserverUrl` (type: `string`):

Base URL of ANY Matrix homeserver (Synapse / Dendrite / Conduit / …). Its public-room directory is read via the Client-Server API GET /\_matrix/client/v3/publicRooms. Examples: https://matrix.org · https://matrix.tchncs.de · https://gnome.modular.im · https://fedora.ems.host. The anonymous GET listing works on any server that publishes its directory publicly.

## `server` (type: `string`):

Optional. Query a DIFFERENT server's published directory THROUGH the homeserver above (the ?server= parameter). NOTE: most homeservers gate remote/federated directory queries behind an access token and return M\_FORBIDDEN / M\_MISSING\_TOKEN anonymously — provide 'Access token' when using this. Leave empty to read the homeserver's own directory.

## `search` (type: `string`):

Optional full-text search over room name / alias / topic (the directory filter's generic\_search\_term). Using search switches to the POST endpoint, which most homeservers require an access token for — provide 'Access token' if the server rejects it anonymously. Leave empty to list the whole directory.

## `roomType` (type: `string`):

Filter the directory by type. 'all' = every entry (anonymous GET). 'spaces' = only m.space entries. 'rooms' = only regular rooms (exclude spaces). A type filter uses the POST endpoint, which most homeservers require an access token for.

## `accessToken` (type: `string`):

Optional Matrix access token (Bearer). Anonymous GET listing needs none, but POST search / room-type filters and federated ?server= queries are commonly auth-gated (M\_MISSING\_TOKEN) — supply a token to unlock them. Never required for a plain public-directory listing.

## `maxRecords` (type: `integer`):

Stop after emitting this many room rows. Opaque next\_batch pagination halts early once reached. Each emitted room is billed as one record.

## `pageSize` (type: `integer`):

Rooms requested per directory page (the API 'limit'). The server may cap this below your value. Larger pages = fewer round-trips.

## `userAgent` (type: `string`):

Override the default descriptive User-Agent header. Many homeservers are volunteer / community deployments — please keep a descriptive agent.

## `timeoutSecs` (type: `integer`):

Per-request timeout in seconds for each directory-page fetch.

## Actor input object example

```json
{
  "homeserverUrl": "https://matrix.org/",
  "roomType": "all",
  "maxRecords": 2000,
  "pageSize": 100,
  "timeoutSecs": 60
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "homeserverUrl": "https://matrix.org/"
};

// Run the Actor and wait for it to finish
const run = await client.actor("datamule/matrix-publicrooms-extractor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "homeserverUrl": "https://matrix.org/" }

# Run the Actor and wait for it to finish
run = client.actor("datamule/matrix-publicrooms-extractor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "homeserverUrl": "https://matrix.org/"
}' |
apify call datamule/matrix-publicrooms-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,datamule/matrix-publicrooms-extractor"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/xbD0uhh4bGwvoQ5Lq/builds/s1qMLUzxmx255iP9P/openapi.json
