# Mastodon Instance Hashtag Monitor (`automation-lab/mastodon-instance-hashtag-monitor`) Actor

Monitor public Mastodon hashtag timelines and enrich public profiles or statuses on one instance without login.

- **URL**: https://apify.com/automation-lab/mastodon-instance-hashtag-monitor.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** Social media
- **Stats:** 2 total users, 1 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## 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/docs.md):

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

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.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/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

## Mastodon Instance Hashtag Monitor

Monitor public Mastodon conversations from a specific instance without a login.

### What does it do?

This Actor collects public hashtag timelines and enriches explicit public account or status URLs.
It uses Mastodon's documented v1 API endpoints rather than a browser.
Choose an HTTPS instance such as `https://mastodon.social` and export structured data.

### Who is it for?

- Social-listening agencies tracking recurring topics.
- Researchers studying public Fediverse conversations.
- Brand-safety teams reviewing public discussion and engagement.
- Analysts who need repeatable, instance-scoped exports.

### Why use it?

Mastodon is federated, so public content lives on individual instances.
This Actor keeps the instance visible on every record and follows public timeline pagination.
It does not require credentials, cookies, DMs, or remote federated search.

### Supported public data

| Input | Result |
| --- | --- |
| Hashtag | Recent public statuses from that instance |
| Account URL | Public profile fields and counts |
| Status URL | One public status with author and media |

### Unified output dataset

All results are saved to the default dataset. Filter the required `recordType` column:
`post` is a normalized public status and `account` is an explicitly requested public
profile. This makes mixed monitoring runs exportable without hiding either entity type.

Post rows include `contentText`, `hashtags`, `mediaAttachments`, `repliesCount`,
`reblogsCount`, `favouritesCount`, author details, public URL, instance, and timestamp.
Account rows include public handle, `displayName`, bio, profile fields, public counts,
bot/locked flags, avatar, header, source URL, and instance. Entity-specific columns are
blank when they do not apply. HTML is retained in `contentHtml`; plain text is available
in `contentText` or `noteText`.

### Quick start

1. Select an HTTPS Mastodon instance.
2. Enter one or more hashtag names without `#`.
3. Start with a low `maxItems` value such as 10.
4. Run the Actor, then filter the default dataset by `recordType` before exporting posts or accounts.
5. Schedule the input for recurring monitoring when the output fits your workflow.

### Input: instance URL

`instanceUrl` must be a plain HTTPS origin, for example `https://mastodon.social`.
All account and status URLs must belong to this same instance.
This prevents accidental remote-resolution calls that may require authentication.

### Input: hashtags

Use `hashtags` for public timeline monitoring.
Enter `technology`, not `#technology`.
The Actor requests up to 40 records at a time and follows Mastodon's next-page link
until it reaches `maxItems` or there are no additional public records.

### Input: explicit URLs

Use `accountUrls` for profile links like `https://mastodon.social/@Mastodon`.
Use `statusUrls` for status links like `https://mastodon.social/@name/123456`.
These are optional and can be combined with hashtags within the shared result cap.

### Input: maximum records

`maxItems` caps combined saved posts and accounts from 1 to 1,000.
Keep test runs small, then increase only after confirming your target instance's policies.
The cap makes scheduled monitoring predictable and cost-aware.

### How much does it cost to monitor Mastodon hashtags?

The Actor charges a small start event and a tiered event for each saved public record.
Pricing follows your Apify subscription tier; the current run page is authoritative.
A record is charged only after it has been saved to the unified default dataset.
Start with a small run to estimate the volume from your selected instance.

### Pagination and freshness

Hashtag timelines use Mastodon's public `max_id` pagination exposed through Link headers.
Results are newest-first as supplied by the instance at run time.
The Actor does not deduplicate across separate scheduled runs; use status IDs downstream.
Every output record has a `scrapedAt` timestamp for auditability.

### Errors and rate limits

Instances can disable public endpoints or apply their own rate limits.
The Actor reports the endpoint and HTTP status for 401, 403, 429, and other failures.
A 429 means wait before retrying with fewer inputs; it is not solved by authentication here.
Do not use this Actor for private, follower-only, or direct-message data.

### Integrations

- Filter `recordType=post` and send those records to a warehouse for topic trend analysis.
- Use a scheduled task and webhooks to flag new posts mentioning a campaign keyword.
- Join `accountAcct` and engagement fields in a BI dashboard.
- Filter `mediaAttachments` before passing candidate posts to a moderation workflow.

### API usage: Node.js

```js
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/mastodon-instance-hashtag-monitor').call({
  instanceUrl: 'https://mastodon.social', hashtags: ['technology'], maxItems: 25,
});
console.log(await client.dataset(run.defaultDatasetId).listItems());
````

### API usage: Python

```python
from apify_client import ApifyClient
client = ApifyClient('APIFY_TOKEN')
run = client.actor('automation-lab/mastodon-instance-hashtag-monitor').call(run_input={
    'instanceUrl': 'https://mastodon.social', 'hashtags': ['technology'], 'maxItems': 25,
})
print(list(client.dataset(run['defaultDatasetId']).iterate_items()))
```

### API usage: cURL

```bash
curl "https://api.apify.com/v2/acts/automation-lab~mastodon-instance-hashtag-monitor/runs?token=$APIFY_TOKEN" \
  -H 'content-type: application/json' \
  -d '{"instanceUrl":"https://mastodon.social","hashtags":["technology"],"maxItems":25}'
```

### MCP

Use this Actor from Claude Desktop or Claude Code through Apify MCP.
Add it in Claude Code with:

```bash
claude mcp add --transport http apify https://mcp.apify.com?tools=automation-lab/mastodon-instance-hashtag-monitor
```

For a JSON configuration, use:

```json
{"mcpServers":{"apify":{"type":"http","url":"https://mcp.apify.com?tools=automation-lab/mastodon-instance-hashtag-monitor"}}}
```

Example prompt: “Monitor public `technology` and `opensource` posts on mastodon.social and summarize engagement.”
Only submit public, instance-scoped URLs and hashtags.

### Responsible use and legality

Collect only public data you are entitled to process.
Respect instance rules, applicable privacy law, and the context of profile information.
Do not use this tool to access private content, bypass access controls, or identify people.
Review and comply with each target instance's terms before scheduling large exports.

### Limitations

Mastodon is federated: endpoint availability, retention, and rate limits vary by instance.
This MVP intentionally does not authenticate, search remote federated resources, read DMs,
or request follower-only statuses. A successful public API response is not a completeness claim.
Content can be deleted or edited after collection.

### Tips for reliable monitoring

Keep one instance per run and retain `id`, `url`, `instance`, and `scrapedAt` downstream.
Use exact public URLs rather than attempting account discovery.
Schedule several focused hashtag inputs instead of a single oversized catch-all run.
If a timeline is empty, verify the tag has public posts on the chosen instance first.

### Troubleshooting

**Why did I get HTTP 401 or 403?** The selected instance has restricted that endpoint;
choose public content on an instance that permits it rather than adding credentials.

**Why did I get HTTP 429?** The instance rate-limited the request. Wait and retry later
with a smaller input. The Actor does not bypass rate limits.

**Why are account URLs rejected?** Account and status URLs must be HTTPS and on `instanceUrl`.
This is intentional so a run never invokes unauthenticated remote search.

### FAQ

**Does it search all of Mastodon?** No. It monitors one explicit instance per run.

**Can it read private posts or DMs?** No. It only calls public v1 API endpoints.

**Can I use a hashtag with #?** Yes, the Actor removes a leading `#` automatically.

**Are media files downloaded?** No. Public media metadata and URLs are saved.

### Related scrapers

For other public social workflows, browse [Automation Lab actors](https://apify.com/automation-lab).
This Actor is purpose-built for instance-scoped Mastodon monitoring rather than broad
cross-network discovery. Use it alongside your approved analytics and moderation tools.

### Changelog

See [the actor changelog](.actor/CHANGELOG.md) for user-facing release notes.

### Support boundaries

When reporting a problem, include the instance origin, endpoint type, HTTP status, and a
sanitized example input. Never include access tokens or private content in a support request.
Public endpoint behavior is ultimately controlled by each Mastodon instance administrator.

### Data retention

Save only the fields required for your approved research or monitoring purpose.

# Actor input Schema

## `instanceUrl` (type: `string`):

HTTPS origin only. Public endpoints differ by instance; start with mastodon.social.

## `hashtags` (type: `array`):

One or more public hashtags, without #. Timeline pages are followed until max items is reached.

## `accountUrls` (type: `array`):

Optional explicit URLs such as https://mastodon.social/@Mastodon. Must be on the selected instance.

## `statusUrls` (type: `array`):

Optional explicit URLs such as https://mastodon.social/@name/123. Must be on the selected instance.

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

Combined cap across posts and accounts. Keep the first run small.

## Actor input object example

```json
{
  "instanceUrl": "https://mastodon.social",
  "hashtags": [
    "technology"
  ],
  "accountUrls": [],
  "statusUrls": [],
  "maxItems": 10
}
```

# Actor output Schema

## `records` (type: `string`):

Posts and public account profiles share the default dataset. Filter rows by recordType and use the Overview view for their relevant fields.

# 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 = {
    "instanceUrl": "https://mastodon.social",
    "hashtags": [
        "technology"
    ],
    "accountUrls": [],
    "statusUrls": [],
    "maxItems": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/mastodon-instance-hashtag-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 = {
    "instanceUrl": "https://mastodon.social",
    "hashtags": ["technology"],
    "accountUrls": [],
    "statusUrls": [],
    "maxItems": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/mastodon-instance-hashtag-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 '{
  "instanceUrl": "https://mastodon.social",
  "hashtags": [
    "technology"
  ],
  "accountUrls": [],
  "statusUrls": [],
  "maxItems": 10
}' |
apify call automation-lab/mastodon-instance-hashtag-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=automation-lab/mastodon-instance-hashtag-monitor",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Mastodon Instance Hashtag Monitor",
        "description": "Monitor public Mastodon hashtag timelines and enrich public profiles or statuses on one instance without login.",
        "version": "0.1",
        "x-build-id": "7UAQxoXT6Xo9ffogA"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/automation-lab~mastodon-instance-hashtag-monitor/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-automation-lab-mastodon-instance-hashtag-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/automation-lab~mastodon-instance-hashtag-monitor/runs": {
            "post": {
                "operationId": "runs-sync-automation-lab-mastodon-instance-hashtag-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/automation-lab~mastodon-instance-hashtag-monitor/run-sync": {
            "post": {
                "operationId": "run-sync-automation-lab-mastodon-instance-hashtag-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": {
                    "instanceUrl": {
                        "title": "🏠 Mastodon instance URL",
                        "type": "string",
                        "description": "HTTPS origin only. Public endpoints differ by instance; start with mastodon.social.",
                        "default": "https://mastodon.social"
                    },
                    "hashtags": {
                        "title": "#️⃣ Hashtags to monitor",
                        "type": "array",
                        "description": "One or more public hashtags, without #. Timeline pages are followed until max items is reached.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "accountUrls": {
                        "title": "👤 Public account URLs",
                        "type": "array",
                        "description": "Optional explicit URLs such as https://mastodon.social/@Mastodon. Must be on the selected instance.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "statusUrls": {
                        "title": "📝 Public status URLs",
                        "type": "array",
                        "description": "Optional explicit URLs such as https://mastodon.social/@name/123. Must be on the selected instance.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxItems": {
                        "title": "Maximum records",
                        "minimum": 1,
                        "maximum": 1000,
                        "type": "integer",
                        "description": "Combined cap across posts and accounts. Keep the first run small.",
                        "default": 10
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
