# Discourse Forum Monitor — Mentions & Feedback (`bikram07/discourse-forum-monitor`) Actor

Monitor any Discourse-powered forum for new topics, feature requests, and brand mentions — by latest or keyword search, across one or many forums at once. Keyless official Discourse JSON. Zero-config: latest topics from meta.discourse.org.

- **URL**: https://apify.com/bikram07/discourse-forum-monitor.md
- **Developed by:** [Bikram](https://apify.com/bikram07) (community)
- **Categories:** Social media, Automation, Lead generation
- **Stats:** 2 total users, 1 monthly users, 66.7% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

## Discourse Forum Monitor — Mentions & Feedback

Monitor **any Discourse-powered forum** for new topics, feature requests, and brand mentions — by **latest** or by **keyword search**, across **one or many forums at once**. It reads the official JSON that every Discourse forum already serves, so there's no API key, no login, and no browser scraping. Run it with **zero configuration** to get the latest topics from [meta.discourse.org](https://meta.discourse.org/), or point it at your own community, your competitors', and your category's forums and search them all in a single pass.

### What it does

Discourse powers thousands of developer, SaaS, crypto, gaming, and open-source communities — `meta.discourse.org`, `community.openai.com`, `forum.cursor.com`, and countless others. Every one exposes machine-readable JSON for any page simply by appending `.json` to the URL.

This Actor uses that to pull the **latest topics** from each forum's front page, or **search** each forum for a keyword (a product name, a competitor, "feature request", a bug phrase). It then normalizes every topic into one clean schema, deduplicates on `forum_host` + `topic_id`, sorts newest-first, and writes the result to your dataset — ready to export as JSON, CSV, or Excel, pipe into a webhook, or query from an AI agent over MCP.

### Why monitor Discourse forums

Community feedback is scattered across forums you don't own, and it moves fast. PMs, developer-relations, growth, and competitive-intelligence teams use this to catch **feature requests** the moment they're posted, track **brand and competitor mentions** across multiple forums, spot **bugs and complaints early** by searching their product name where users actually hang out, and mine **voice-of-customer** for content and roadmap.

Think of it as a DIY, self-hosted version of social-listening tools like Octolens or feedback boards like Canny — pointed at the Discourse forums you care about, on your own schedule, paying only per topic returned.

### Input

Every field is optional. **Empty input `{}` returns the latest topics from `meta.discourse.org`.**

| Field | Type | Default | Description |
|---|---|---|---|
| `forums` | array | `["meta.discourse.org"]` | One or more Discourse forum hostnames. Protocol and trailing slashes are stripped automatically, so `https://forum.cursor.com/` and `forum.cursor.com` both work. |
| `mode` | enum | `"latest"` | `latest` = newest topics from each forum. `search` = topics matching `keyword`. |
| `keyword` | string | — | Search term used when `mode = "search"`. Matches topic titles and post bodies. Ignored in latest mode. |
| `maxTopics` | integer | `100` | Max total topics output across all forums, after dedupe and sorting. With multiple forums the budget is shared so no single busy forum starves the others. |

**Zero-config (latest from meta.discourse.org):**
```json
{}
````

**Latest topics from several forums:**

```json
{
    "forums": ["community.openai.com", "forum.cursor.com"],
    "mode": "latest",
    "maxTopics": 50
}
```

**Cross-forum mention / feature-request monitor (the differentiator):**

```json
{
    "forums": ["community.openai.com", "forum.cursor.com", "meta.discourse.org"],
    "mode": "search",
    "keyword": "feature request",
    "maxTopics": 150
}
```

Searching a keyword across a **list** of forums in one run is what turns this from a single-forum dumper into a mention monitor — set `keyword` to your product, a competitor, or a problem phrase and watch every forum at once.

### Output schema

One normalized item per topic. Missing fields are `null` or empty — never fabricated.

| Field | Type | Description |
|---|---|---|
| `forum_host` | string | Forum hostname, e.g. `meta.discourse.org`. |
| `topic_id` | integer | Discourse topic id (unique within a forum). |
| `topic_title` | string | Topic title. |
| `topic_url` | string | Canonical link, `https://{forum}/t/{slug}/{id}`. |
| `category_id` | integer / null | Discourse category id the topic belongs to. |
| `author_username` | string / null | Original Poster's username. |
| `created_at` | string / null | When the topic was created, ISO 8601. |
| `last_posted_at` | string / null | When the most recent post was made, ISO 8601. |
| `reply_count` | integer / null | Number of replies. |
| `views` | integer / null | View count (present in latest mode; usually absent in search). |
| `like_count` | integer / null | Likes on the topic / matched post. |
| `tags` | array | Topic tags. |
| `excerpt` | string / null | Short excerpt / blurb of the opening post. |
| `is_solved` | bool / null | `true` if the topic has an accepted answer (Discourse Solved plugin); `null` if the forum doesn't expose it. |
| `matched_keyword` | string / null | The search term, in `search` mode only; `null` in latest mode. |

**Sample item (latest mode):**

```json
{
    "forum_host": "meta.discourse.org",
    "topic_id": 1,
    "topic_title": "New to Discourse? Start here!",
    "topic_url": "https://meta.discourse.org/t/new-to-discourse-start-here/1",
    "category_id": 67,
    "author_username": "Discourse",
    "created_at": "2013-02-01T04:52:28.073Z",
    "last_posted_at": "2013-02-01T04:52:28.397Z",
    "reply_count": 5,
    "views": 116216,
    "like_count": 433,
    "tags": [],
    "excerpt": "We're so glad you're here! This is our official community…",
    "is_solved": false,
    "matched_keyword": null
}
```

### How it works — the Discourse `.json` pattern

Discourse serves the same data to humans and machines. Append `.json` to any page URL:

| Page | JSON endpoint |
|---|---|
| Latest topics | `https://{forum}/latest.json?page=N` |
| Search | `https://{forum}/search.json?q={term}` |
| Category | `https://{forum}/c/{slug}/{id}.json` |
| Topic detail | `https://{forum}/t/{id}.json` |

These are first-party, federation-grade endpoints the Discourse software itself uses — not a scraper hitting HTML. This Actor reads `latest.json` and `search.json`, pages through results, resolves each topic's author from the response's user table, and maps everything into the schema above. Anonymous JSON is rate-limited (~60 requests/minute); the Actor honors `Retry-After` on `429`.

### Use cases

- **Product feedback monitoring** — daily run with `mode: search`, `keyword: "feature request"` across your community and adjacent ones.
- **Brand & competitor listening** — search your product and competitors' names across a forum list; pipe matches to Slack via a webhook.
- **DevRel triage** — surface the newest unanswered topics (`is_solved: false`) so your team can jump in fast.
- **AI agents (MCP)** — let an agent answer "what are people saying about us on the OpenAI forum this week?" by calling this Actor live.

### Run on a schedule (mention alerts)

1. Set `forums`, `mode`, and `keyword`.
2. Create an [Apify Schedule](https://docs.apify.com/platform/schedules) — a daily run catches new topics within ~24h.
3. Add a [webhook](https://docs.apify.com/platform/integrations/webhooks) to push results to email, Slack, Teams, or your own system.

### Use from Claude, Cursor & AI agents (MCP)

```json
{
    "mcpServers": {
        "apify": {
            "url": "https://mcp.apify.com/sse?actors=bikram07/discourse-forum-monitor",
            "headers": { "Authorization": "Bearer YOUR_APIFY_TOKEN" }
        }
    }
}
```

Or call the API directly:

```bash
curl -X POST "https://api.apify.com/v2/acts/bikram07~discourse-forum-monitor/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"forums":["community.openai.com"],"mode":"search","keyword":"agent"}'
```

### What it is NOT

- **Public Discourse forums only.** It reads what anonymous visitors can read. Forums that require login (`login_required`) are **skipped cleanly** — they're reported as skipped in the run status, never as an error, and never with fabricated data.
- **Not a private-content scraper.** It does not log in, bypass paywalls, or access gated categories. It uses the same JSON an anonymous browser would receive.
- **Not a generic single-forum dumper.** The point is breadth: searching a keyword across a **list** of forums to monitor mentions and feature requests. You can run it on one forum, but the differentiator is the cross-forum view.
- **Discourse only.** It works with forums running the Discourse platform. It does not cover phpBB, Reddit, Slack, Discord, or other systems.
- **Not real-time to the second.** Freshness is whatever the forum has published when you run it; schedule it as often as you need within rate limits.
- **Not affiliated with Discourse** or any forum it reads. Independent tool built on Discourse's public JSON endpoints.

***

Built on the public JSON endpoints that every [Discourse](https://www.discourse.org/) forum serves. Not affiliated with or endorsed by Discourse or any forum operator.

**Related searches:** Discourse forum scraper · Discourse API · forum monitoring · community feedback monitor · feature request tracker · brand mention monitoring · competitor mention tracker · Discourse search API · cross-forum monitor · developer community listening · Octolens alternative · DIY social listening for forums

# Actor input Schema

## `forums` (type: `array`):

One or more Discourse forum hostnames to monitor. Just the host — protocol and trailing slashes are stripped automatically. Examples: <b>meta.discourse.org</b>, <b>community.openai.com</b>, <b>forum.cursor.com</b>. In <b>search</b> mode with multiple forums, this becomes a cross-forum mention / feature-request monitor.

## `mode` (type: `string`):

<b>latest</b> — newest topics from each forum's front page. <b>search</b> — topics matching the keyword below (use this for mention/feature-request monitoring across a forum list).

## `keyword` (type: `string`):

Search term used when <b>mode = search</b>. Matches topic titles and post bodies. Example: <b>your product name</b>, <b>feature request</b>, or a competitor's name. Ignored in latest mode.

## `maxTopics` (type: `integer`):

Maximum total topics to output across all forums, after dedupe and sorting. Default 100.

## Actor input object example

```json
{
  "forums": [
    "meta.discourse.org"
  ],
  "mode": "latest",
  "maxTopics": 100
}
```

# 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 = {
    "forums": [
        "meta.discourse.org"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("bikram07/discourse-forum-monitor").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 = { "forums": ["meta.discourse.org"] }

# Run the Actor and wait for it to finish
run = client.actor("bikram07/discourse-forum-monitor").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "forums": [
    "meta.discourse.org"
  ]
}' |
apify call bikram07/discourse-forum-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=bikram07/discourse-forum-monitor",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Discourse Forum Monitor — Mentions & Feedback",
        "description": "Monitor any Discourse-powered forum for new topics, feature requests, and brand mentions — by latest or keyword search, across one or many forums at once. Keyless official Discourse JSON. Zero-config: latest topics from meta.discourse.org.",
        "version": "0.1",
        "x-build-id": "vnfWtGTPz0P6qaRAo"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/bikram07~discourse-forum-monitor/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-bikram07-discourse-forum-monitor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/bikram07~discourse-forum-monitor/runs": {
            "post": {
                "operationId": "runs-sync-bikram07-discourse-forum-monitor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/bikram07~discourse-forum-monitor/run-sync": {
            "post": {
                "operationId": "run-sync-bikram07-discourse-forum-monitor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "forums": {
                        "title": "Forums (hostnames)",
                        "type": "array",
                        "description": "One or more Discourse forum hostnames to monitor. Just the host — protocol and trailing slashes are stripped automatically. Examples: <b>meta.discourse.org</b>, <b>community.openai.com</b>, <b>forum.cursor.com</b>. In <b>search</b> mode with multiple forums, this becomes a cross-forum mention / feature-request monitor.",
                        "items": {
                            "type": "string"
                        },
                        "default": [
                            "meta.discourse.org"
                        ]
                    },
                    "mode": {
                        "title": "Mode",
                        "enum": [
                            "latest",
                            "search"
                        ],
                        "type": "string",
                        "description": "<b>latest</b> — newest topics from each forum's front page. <b>search</b> — topics matching the keyword below (use this for mention/feature-request monitoring across a forum list).",
                        "default": "latest"
                    },
                    "keyword": {
                        "title": "Keyword (search mode)",
                        "type": "string",
                        "description": "Search term used when <b>mode = search</b>. Matches topic titles and post bodies. Example: <b>your product name</b>, <b>feature request</b>, or a competitor's name. Ignored in latest mode."
                    },
                    "maxTopics": {
                        "title": "Max topics",
                        "minimum": 1,
                        "maximum": 5000,
                        "type": "integer",
                        "description": "Maximum total topics to output across all forums, after dedupe and sorting. Default 100.",
                        "default": 100
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
