# Mastodon Scraper — Posts, Hashtags & Profiles | Any Instance (`bovi/mastodon-scraper`) Actor

Scrape any Mastodon instance: user posts, hashtag timelines, and search results. No login required. Returns post text, engagement, media, link cards, and author profiles. Pay per result.

- **URL**: https://apify.com/bovi/mastodon-scraper.md
- **Developed by:** [Vitalii Bondarev](https://apify.com/bovi) (community)
- **Categories:** Social media, Marketing, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 mastodon scraper — posts, hashtags & profiles | any instances

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

## Mastodon Scraper — Posts, Hashtags & Profiles | $1.50/1K | Any Instance

For researchers tracking decentralized social media, brand monitors watching open-source/tech communities, and anyone studying the Fediverse.

**Pricing: $1.50 per 1,000 posts** (PPE, pay per result).

Scrape any Mastodon instance without login. Collect posts from user accounts,
hashtag timelines, and search — all via the **official Mastodon REST API** with
no proxy required. Returns a clean, flat dataset with engagement metrics, media
URLs, link cards, and `parse_confidence` so you know every record is valid.

### Pricing example

**$1.50 per 1,000 posts** (PPE, pay per result, no per-run fee). 100 posts = $0.15. 1,000 posts = $1.50. A daily hashtag monitor at 200 posts/day costs ~$9/month.

### Sample output

```json
{
  "instance": "fosstodon.org",
  "account_username": "kev",
  "display_name": "Kev Quirk",
  "post_id": "110512345678901234",
  "content_text": "Just published a new post on why I switched from GitHub to Forgejo.",
  "created_at": "2026-05-21T10:14:00Z",
  "replies": 12,
  "reblogs": 34,
  "favourites": 98,
  "url": "https://fosstodon.org/@kev/110512345678901234",
  "source_mode": "account",
  "media_urls": [],
  "hashtags": ["foss", "git"],
  "parse_confidence": 1.0,
  "scraped_at": "2026-06-05T09:00:00Z"
}
```

### What you get

| Field | Description |
|---|---|
| `instance` | Mastodon instance scraped (e.g. `mastodon.social`) |
| `account_username` | Username of the post author |
| `display_name` | Display name of the author |
| `followers` / `following` / `post_count` | Author profile stats |
| `post_id` | Unique numeric post ID |
| `content_text` | Plain-text post content (HTML stripped) |
| `content_html` | Raw HTML content |
| `created_at` | Post timestamp (ISO 8601 UTC) |
| `edited_at` | Timestamp if post was edited, else null |
| `replies` / `reblogs` / `favourites` | Engagement counts |
| `is_reblog` | True if this is a boosted/reposted post |
| `in_reply_to_id` | ID of parent post for replies |
| `url` | Direct URL to the post |
| `media_urls` | List of media attachment URLs |
| `card_url` / `card_title` / `card_image_url` | Link card preview |
| `mentions` | @usernames mentioned in the post |
| `hashtags` | Hashtags used in the post |
| `source_mode` | How the post was discovered: `account`, `hashtag`, or `search` |
| `parse_confidence` | 0.0–1.0 quality score (1.0 = all fields present) |

### Why this Mastodon scraper

- **Any instance** — not locked to mastodon.social. Works with fosstodon.org,
  infosec.exchange, hachyderm.io, or any standard Mastodon server.
- **Three modes in one actor** — account posts, hashtag timelines, and search
  all in a single run.
- **Official API, zero fragility** — uses `/api/v1/accounts`, `/api/v1/timelines/tag`,
  and `/api/v2/search`. No HTML parsing that breaks on layout changes.
- **Zero proxy cost** — Mastodon public API is open to the web. Buyer pays
  nothing extra for proxy on top of compute.
- **parse\_confidence** — every record carries a quality score. A drop to < 0.8
  means a required field was missing; easy to filter in downstream pipelines.
- **Federated posts in hashtag timelines** — by default returns posts from
  across the Fediverse, not just the local instance (toggle `localOnly` for
  local-only mode).

### How to use

#### Scrape a user account

Set `instance` + `usernames`:

```json
{
  "instance": "mastodon.social",
  "usernames": ["Mastodon", "gargron"],
  "maxPosts": 200
}
```

#### Scrape a hashtag timeline

```json
{
  "instance": "mastodon.social",
  "hashtags": ["python", "foss", "ai"],
  "maxPosts": 100
}
```

#### Search for posts

```json
{
  "instance": "fosstodon.org",
  "searchQueries": ["open source LLM"],
  "maxPosts": 50
}
```

#### Combine all three in one run

```json
{
  "instance": "mastodon.social",
  "usernames": ["Mastodon"],
  "hashtags": ["fediverse"],
  "searchQueries": ["ActivityPub"],
  "maxPosts": 100,
  "includeReplies": false,
  "includeReposts": false
}
```

### Cost estimate

Pricing is **$1.50 per 1,000 posts** (PPE, pay per result).
A typical run of 1,000 posts costs approximately **$1.50** in actor charges,
plus a small amount of Apify platform compute (usually < $0.05 for this API-based actor).

### Frequently asked questions

**Do I need a Mastodon account or API key?**
No. The actor uses the public Mastodon REST API — account posts and hashtag timelines are fully public without authentication. Search may return fewer results on some instances without a token, but that is an instance policy, not a scraper limitation.

**Do I need a proxy?**
No. Mastodon's public API is open to any HTTP client. No proxy cost to you or the buyer.

**What formats does output come in?**
JSON (default), CSV, and Excel via the Apify dataset. Integrates natively with n8n, Make, and Zapier.

**What if the actor returns 0 results?**
The actor logs a warning per failed source and continues. Empty results (e.g. an account with 0 posts, or a hashtag not yet used on that instance) produce 0 records and 0 charges — not an error.

### Notes on search

The Mastodon `/api/v2/search` endpoint is public but may return fewer results
on some instances without authentication. Account and hashtag modes are fully
public and return complete results without any token.

### Which Mastodon instances work?

Any server running standard Mastodon software — this covers the vast majority
of Fediverse instances. Servers running Akkoma, Pleroma, or Misskey use a
compatible API subset; account and hashtag modes work, search behaviour varies.

### Integrations

Built for researchers and brand monitors tracking posts, hashtags, and communities across the decentralized Fediverse — the JSON/dataset output drops into the tools you already run, no glue code:

- **n8n / Make / Zapier** — trigger a run or pipe every new dataset item into 500+ apps (Google Sheets, Airtable, Slack, HubSpot, your database) with no code: [n8n](https://docs.apify.com/platform/integrations/n8n), [Make](https://docs.apify.com/platform/integrations/make), [Zapier](https://docs.apify.com/platform/integrations/zapier).
- **Webhooks** — fire your own endpoint the moment a run finishes, to push results straight into your pipeline ([docs](https://docs.apify.com/platform/integrations/webhooks)).
- **MCP server** — expose this actor as a tool to Claude, Cursor, or any [MCP client](https://mcp.apify.com) so an AI agent can pull this data mid-conversation ([guide](https://blog.apify.com/how-to-use-mcp/)).
- **API & SDKs** — fetch the dataset as JSON, CSV, or Excel through the Apify REST API or the Python / JS SDKs.

See all [Apify integrations](https://apify.com/integrations).

### Legal

Mastodon instances publish their public timelines for open access per the
ActivityPub protocol. This actor only accesses public, unauthenticated endpoints
identical to what any browser visitor would see. Always review the instance's
Terms of Service before large-scale collection.

This actor is not affiliated with Mastodon gGmbH or any specific Mastodon instance.

### Fediverse coverage

Tested and working on popular instances including **fosstodon.org** (FOSS/tech), **infosec.exchange** (security), **hachyderm.io** (tech professionals), **mas.to** (general), **mastodon.social** (largest), and **sigmoid.social** (AI/ML). Any server running standard Mastodon, Akkoma, or Pleroma software is supported.

### Compared to generic scrapers

| | This scraper | Generic Mastodon scraper |
|---|:---:|:---:|
| Any Mastodon instance | ✓ | ✗ (mastodon.social only) |
| Three modes (account/hashtag/search) | ✓ | partial |
| parse\_confidence on every record | ✓ | ✗ |
| Zero proxy cost | ✓ | ✓ |
| Official API (no HTML parsing) | ✓ | ✗ |

### Use with AI Agents (MCP)

This Mastodon scraper is callable as a **tool by AI agents** (Claude Desktop, Cursor, VS Code, n8n, or any MCP-compatible client) via Apify's hosted Model Context Protocol server.

```json
{
  "mcpServers": {
    "apify": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "https://mcp.apify.com/?tools=bovi/mastodon-scraper",
        "--header",
        "Authorization: Bearer <YOUR_APIFY_TOKEN>"
      ]
    }
  }
}
```

# Actor input Schema

## `instance` (type: `string`):

Hostname of the Mastodon instance to scrape. Example: mastodon.social, fosstodon.org, infosec.exchange. Do NOT include https://. Works with any standard Mastodon server.

## `usernames` (type: `array`):

Usernames to scrape posts for (without @). Example: \['Mastodon', 'gargron']. For users on other instances include domain: user@fosstodon.org.

## `accountIds` (type: `array`):

Numeric Mastodon account IDs (alternative to usernames). Useful when you already know the ID from a previous run.

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

Hashtags to scrape the public timeline for (without #). Example: python, foss, ai.

## `searchQueries` (type: `array`):

Free-text search queries. Returns public posts matching the query via /api/v2/search.

## `maxPosts` (type: `integer`):

Maximum number of posts to return per username, hashtag, or search query. 0 means no limit.

## `includeReplies` (type: `boolean`):

If enabled, includes posts that are replies to other users. Off by default to return only original posts.

## `includeReposts` (type: `boolean`):

If enabled, includes boosted/reposted content. Off by default.

## `localOnly` (type: `boolean`):

For hashtag timelines only: if enabled, returns posts from the selected instance only (not federated posts from other instances).

## Actor input object example

```json
{
  "instance": "mastodon.social",
  "usernames": [
    "Mastodon"
  ],
  "maxPosts": 100
}
```

# Actor output Schema

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

Dataset containing Mastodon Scraper records (account\_username, display\_name, instance, content\_text, replies, reblogs, favourites, url, created\_at, parse\_confidence).

# 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 = {
    "instance": "mastodon.social",
    "usernames": [
        "Mastodon"
    ],
    "maxPosts": 100,
    "includeReplies": false,
    "includeReposts": false,
    "localOnly": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("bovi/mastodon-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 = {
    "instance": "mastodon.social",
    "usernames": ["Mastodon"],
    "maxPosts": 100,
    "includeReplies": False,
    "includeReposts": False,
    "localOnly": False,
}

# Run the Actor and wait for it to finish
run = client.actor("bovi/mastodon-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 '{
  "instance": "mastodon.social",
  "usernames": [
    "Mastodon"
  ],
  "maxPosts": 100,
  "includeReplies": false,
  "includeReposts": false,
  "localOnly": false
}' |
apify call bovi/mastodon-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,bovi/mastodon-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/bKxVjmksMq445bGEP/builds/TxxLA3t57grP1TExG/openapi.json
