# Matrix Message Scraper (`jungle_synthesizer/matrix-message-scraper`) Actor

Scrape public rooms and messages from any Matrix homeserver (matrix.org, Element, or self-hosted). Discover public rooms by keyword or scrape message history from specific rooms using a Matrix access token.

- **URL**: https://apify.com/jungle\_synthesizer/matrix-message-scraper.md
- **Developed by:** [BowTiedRaccoon](https://apify.com/jungle_synthesizer) (community)
- **Categories:** Social media, Automation
- **Stats:** 3 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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 Chat Scraper — Rooms & Message History

Extract public room listings and message history from any Matrix homeserver, including `matrix.org`. Operates in two modes: discover public rooms without authentication, or retrieve full message history from specific rooms using an access token. Returns structured JSON with room metadata, message content, reply threads, and media references.

### What does the Matrix Chat Scraper do?

- **Discover mode** — Lists public rooms on any Matrix homeserver without login; returns room name, topic, member count, join rules, and encryption status
- **Scrape mode** — Retrieves message history from one or more rooms using a Matrix access token; returns messages, replies, edits, thread IDs, and media URLs
- Supports optional search filtering to narrow public room discovery by keyword
- Works with any Matrix homeserver (`matrix.org`, `mozilla.org`, self-hosted, etc.)
- Returns two record types in the same dataset: `room` and `message`

### What data does it extract?

#### Room records (`record_type: room`)

| Field | Description |
|-------|-------------|
| `record_type` | `room` |
| `room_id` | Matrix room ID (e.g. `!abc123:matrix.org`) |
| `room_name` | Display name of the room |
| `room_topic` | Room topic or description |
| `room_canonical_alias` | Canonical alias (e.g. `#roomname:matrix.org`) |
| `room_member_count` | Current member count |
| `room_is_encrypted` | Whether the room uses end-to-end encryption |
| `room_join_rule` | Join rule: `public`, `invite`, `knock`, etc. |
| `room_world_readable` | Whether history is visible without joining |
| `room_guest_can_join` | Whether guests can join |
| `room_avatar_url` | Room avatar MXC URL |
| `room_type` | Matrix room type if set |
| `homeserver` | Homeserver domain |

#### Message records (`record_type: message`)

| Field | Description |
|-------|-------------|
| `record_type` | `message` |
| `event_id` | Unique Matrix event ID |
| `event_type` | Matrix event type (e.g. `m.room.message`) |
| `event_sender` | Sender MXID (e.g. `@user:matrix.org`) |
| `event_sender_display_name` | Display name of the sender |
| `event_origin_server_ts` | Server timestamp (milliseconds since epoch) |
| `event_content_msgtype` | Message type (`m.text`, `m.image`, `m.file`, etc.) |
| `event_content_body` | Plain text message body |
| `event_content_formatted_body` | HTML-formatted body where available |
| `event_content_url` | MXC URL for media messages |
| `event_reply_to` | Event ID of the message being replied to |
| `event_thread_id` | Thread root event ID if part of a thread |
| `event_edits` | Array of edit event IDs for this message |
| `event_room_id` | Room ID this message belongs to |

### How to use it

Choose `action`: `discover_rooms` requires only a homeserver URL. `scrape_room_messages` requires an access token and at least one room ID. Access tokens do not expire by default on most homeservers but can be revoked via Element settings if needed.

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `action` | string | `discover_rooms` | `discover_rooms` or `scrape_room_messages` |
| `homeserver` | string | `https://matrix.org` | Matrix homeserver URL |
| `accessToken` | string | — | Matrix access token (required for `scrape_room_messages`). Secret field. |
| `roomIds` | array | — | List of room IDs to scrape (e.g. `!abc123:matrix.org`) |
| `searchTerm` | string | — | Keyword filter for room discovery |
| `maxItems` | integer | `10` | Maximum records to return |
| `maxMessagesPerRoom` | integer | `100` | Maximum messages to retrieve per room |
| `messageDirection` | string | `b` | Pagination direction: `b` (backwards from latest) or `f` (forwards from oldest) |

### Use cases

- **Open-source community analysis** — matrix.org alone hosts 100,000+ public rooms covering tech projects, gaming communities, and decentralized apps; map community size and topic distribution at scale.
- **Academic linguistics research** — Collect multilingual message corpora from Matrix federated servers for NLP training, sentiment analysis, or comparative linguistics studies.
- **Content moderation tooling** — Discover public rooms matching specific keywords and monitor message content for policy-violating material across open Matrix communities.
- **Competitive intelligence** — Track discussion volumes and sentiment in technology or gaming community rooms without requiring a login to join.
- **Archival and research** — Preserve message history from public rooms using the `messageDirection: f` mode to paginate from the earliest available messages forward.

### FAQ

**How do I get a Matrix access token?**
Log in to your Matrix client (e.g. Element), go to Settings > Help & About > Advanced, and copy the Access Token shown there. The token authenticates as your account on the homeserver you specify.

**Does the actor decrypt end-to-end encrypted messages?**
No. The actor retrieves events from the Matrix Client-Server API. Encrypted rooms return encrypted event payloads — the decryption keys are not accessible via the API without a full E2E key export. Use `discover_rooms` to identify whether a room is encrypted (`room_is_encrypted: true`) before attempting to scrape it.

**Can I scrape messages from a private room?**
Yes, provided your access token is for an account that is already a member of that room. The `roomIds` input accepts any room ID your account can read.

Results are available for export in JSON, CSV, and Excel formats from the Apify dataset tab.

# Actor input Schema

## `sp_intended_usage` (type: `string`):

Please describe how you plan to use the data extracted by this crawler.

## `sp_improvement_suggestions` (type: `string`):

Provide any feedback or suggestions for improvements.

## `sp_contact` (type: `string`):

Provide your email address so we can get in touch with you.

## `action` (type: `string`):

What to scrape:

- **Discover Public Rooms** – list public rooms on the homeserver (no token required)
- **Scrape Room Messages** – fetch message history for one or more rooms (access token required)

## `homeserver` (type: `string`):

Matrix homeserver base URL. Defaults to matrix.org.

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

Matrix access token. Required for 'Scrape Room Messages'. Get it from Element: Settings → Help & About → Access Token.

## `roomIds` (type: `array`):

List of Matrix room IDs to scrape messages from (e.g. !abcdef:matrix.org). Used by 'Scrape Room Messages' action.

## `searchTerm` (type: `string`):

Filter public rooms by name/topic keyword. Used by 'Discover Public Rooms' action. Leave blank to return all public rooms.

## `maxItems` (type: `integer`):

Maximum number of records to return across all rooms.

## `maxMessagesPerRoom` (type: `integer`):

Maximum number of messages to fetch per room. 0 = unlimited.

## `messageDirection` (type: `string`):

Pagination direction. 'b' (backward) fetches oldest messages first; 'f' (forward) fetches newest first.

## Actor input object example

```json
{
  "sp_intended_usage": "Describe your intended use...",
  "sp_improvement_suggestions": "Share your suggestions here...",
  "sp_contact": "Share your email here...",
  "action": "Discover Public Rooms",
  "homeserver": "https://matrix.org/",
  "maxItems": 10,
  "maxMessagesPerRoom": 100,
  "messageDirection": "b"
}
```

# 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 = {
    "sp_intended_usage": "Describe your intended use...",
    "sp_improvement_suggestions": "Share your suggestions here...",
    "sp_contact": "Share your email here...",
    "action": "Discover Public Rooms",
    "homeserver": "https://matrix.org/",
    "maxItems": 10,
    "maxMessagesPerRoom": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("jungle_synthesizer/matrix-message-scraper").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 = {
    "sp_intended_usage": "Describe your intended use...",
    "sp_improvement_suggestions": "Share your suggestions here...",
    "sp_contact": "Share your email here...",
    "action": "Discover Public Rooms",
    "homeserver": "https://matrix.org/",
    "maxItems": 10,
    "maxMessagesPerRoom": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("jungle_synthesizer/matrix-message-scraper").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 '{
  "sp_intended_usage": "Describe your intended use...",
  "sp_improvement_suggestions": "Share your suggestions here...",
  "sp_contact": "Share your email here...",
  "action": "Discover Public Rooms",
  "homeserver": "https://matrix.org/",
  "maxItems": 10,
  "maxMessagesPerRoom": 100
}' |
apify call jungle_synthesizer/matrix-message-scraper --silent --output-dataset

```

## MCP server setup

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

```

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/wbHag6ktPH5ZiRXTt/builds/czGKlMEv37Axrpaif/openapi.json
