# Mastodon Scraper · Posts, Accounts & Instances (`reapx/mastodon-scraper`) Actor

Mastodon and ActivityPub scraper for fediverse posts, profiles, hashtags, and instance timelines. Extract public statuses, accounts, engagement metrics, media, and links. No login required. Scrape toots across the open social network.

- **URL**: https://apify.com/reapx/mastodon-scraper.md
- **Developed by:** [Tarek Etman](https://apify.com/reapx) (community)
- **Categories:** Social media, News, Automation
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.00 / 1,000 post returneds

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/platform/actors/running/actors-in-store#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, Accounts, Hashtags & Instances

**Mastodon scraper** that reads public posts from any instance — by hashtag, by the
instance's own timeline, by what it is trending, or by account — and returns one structured
row per post: the author and their follower counts, the post text, engagement counts,
hashtags, media and any outbound link.

No token, no app registration, no login. It reads Mastodon's own public REST API. Run it
with nothing set and it reads `#photography` on `mastodon.social`.

### What you get per post

| Field | |
|---|---|
| `handle` | the author as `instance/username` — unique across the whole fediverse |
| `accountAcct` | the same author in Mastodon's native `user@instance` form |
| `accountDisplayName` · `accountFollowers` · `accountStatusCount` · `accountIsBot` | who posted it |
| `content` · `spoilerText` · `language` · `visibility` · `isSensitive` | the post |
| `favouritesCount` · `reblogsCount` · `repliesCount` | engagement as the reading instance sees it |
| `hashtags` · `mentionCount` · `mediaCount` · `mediaTypes` | what is in it |
| `linkUrl` · `linkTitle` | where it points |
| `instanceDomain` · `sourceInstance` · `statusUrl` · `createdAt` · `retrievedAt` | |

### A hashtag timeline is federated

Reading `#rustlang` on one instance returns posts from across the fediverse, not only from
that instance — a hashtag timeline is the cheapest wide view Mastodon offers. Set **Only
posts from this instance** if you want the narrow one instead.

### Track a hashtag over time

Put your hashtags in, set **Maximum posts** high, and schedule the run. Every row carries
`statusUrl` and `createdAt`, so consecutive runs append cleanly and `handle` groups the
whole set by author.

### Watch an instance's own community

Turn on **Include the instance's public timeline** with **Only posts from this instance**
and point it at `fosstodon.org`, `hachyderm.io` or any instance you care about. Note that
some instances — `mastodon.social` among them — require a logged-in user for their public
timeline; those are skipped with a note in the run status rather than failing the run, and
their hashtag and trending timelines still work.

### Follow specific accounts

Put `user@instance` addresses in **Accounts**. Each is resolved on the instance you are
reading from and its public posts returned, with replies and boosts filtered out if you
want only original material.

### Pricing

Pay per event: **$0.001 per post returned**, with tiered discounts down to $0.0005. A
refused instance or an empty result set is never charged, and the run's maximum cost caps
how many posts it will fetch. Apify platform usage is absorbed, not billed to you
separately.

### FAQ

**Does it need a Mastodon account or an access token?** No. Every endpoint it uses is
public and unauthenticated.

**Does it read private or followers-only posts?** No. Only what the instance serves
publicly; `visibility` on every row says which it was.

**Why does `sourceInstance` differ from `instanceDomain`?** Because the post arrived by
federation: `instanceDomain` is where the author lives, `sourceInstance` is where this run
read it.

**Are engagement counts exact?** They are what the reading instance knows. Mastodon is
federated, so a post's favourite count can differ slightly between instances. Reading the
author's own instance gives the authoritative figure.

**What is the stable identifier?** `handle`. Instance and username together address one
account across the whole network, and it is the right key to join runs together over time.

***

Unofficial - not affiliated with Mastodon gGmbH or any instance operator. Collects public
data only. reapx. Contact reapxdev@proton.me.

# Actor input Schema

## `instances` (type: `array`):

Mastodon instance domains to read, one per line — mastodon.social, fosstodon.org, hachyderm.io, mstdn.social. Every source below is read on each instance and the results merged.

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

Hashtags to read, one per line, with or without the #. Each is fetched as its own timeline.

## `accounts` (type: `array`):

Accounts whose public posts to read, one per line, as user@instance or a bare username for a local account.

## `includePublicTimeline` (type: `boolean`):

Read each instance's public timeline. Some instances, mastodon.social among them, require a logged-in user for this and are skipped with a note rather than failing the run.

## `includeTrending` (type: `boolean`):

Read what each instance is currently amplifying through its trends endpoint.

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

Restrict hashtag and public timelines to posts written on the instance itself, excluding federated posts from elsewhere.

## `onlyWithMedia` (type: `boolean`):

Keep only posts carrying at least one image, video or audio attachment.

## `excludeReplies` (type: `boolean`):

Drop posts that reply to another post.

## `excludeReblogs` (type: `boolean`):

Drop boosts (reblogs) and keep only original posts.

## `language` (type: `string`):

Keep only posts the author tagged with this two-letter language code.

## `minFavourites` (type: `integer`):

Keep only posts with at least this many favourites — the simplest way to skim the top of a busy hashtag.

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

Hard ceiling on the rows this run produces, and therefore on what it costs. You are charged per post returned.

## `requestsPerSecond` (type: `integer`):

Politeness against each instance. Mastodon instances are volunteer-run; keep this low.

## Actor input object example

```json
{
  "instances": [
    "mastodon.social",
    "fosstodon.org"
  ],
  "hashtags": [
    "opensource",
    "rustlang"
  ],
  "accounts": [
    "Gargron@mastodon.social",
    "torproject@mastodon.social"
  ],
  "includePublicTimeline": true,
  "includeTrending": true,
  "localOnly": true,
  "onlyWithMedia": true,
  "excludeReplies": true,
  "excludeReblogs": true,
  "language": "en",
  "minFavourites": 5,
  "maxPosts": 500,
  "requestsPerSecond": 2
}
```

# Actor output Schema

## `items` (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 = {
    "instances": [
        "mastodon.social"
    ],
    "hashtags": [
        "photography"
    ],
    "maxPosts": 100,
    "requestsPerSecond": 2
};

// Run the Actor and wait for it to finish
const run = await client.actor("reapx/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 = {
    "instances": ["mastodon.social"],
    "hashtags": ["photography"],
    "maxPosts": 100,
    "requestsPerSecond": 2,
}

# Run the Actor and wait for it to finish
run = client.actor("reapx/mastodon-scraper").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 '{
  "instances": [
    "mastodon.social"
  ],
  "hashtags": [
    "photography"
  ],
  "maxPosts": 100,
  "requestsPerSecond": 2
}' |
apify call reapx/mastodon-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

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