# Mastodon Profile, Follower & Creator Scraper (`haketa/mastodon-scraper`) Actor

Discover and scrape Mastodon profiles: handle, display name, bio, follower/following/post counts, verified link fields, bot flag and account age. Search by keyword, look up handles, or scrape any account's followers/following. Extracts email, website and socials. For creator discovery and lead gen.

- **URL**: https://apify.com/haketa/mastodon-scraper.md
- **Developed by:** [Haketa](https://apify.com/haketa) (community)
- **Categories:** Social media, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.75 / 1,000 results

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?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Mastodon Scraper — Profiles, Followers, Bios & Creator Contacts

> **The fastest way to scrape Mastodon profiles, followers and creator contacts across the fediverse — no login, no coding.** This **Mastodon scraper** pulls structured accounts from any Mastodon instance: handle, display name, bio, follower / following / post counts, profile link fields, bot flag, account age, and the website, email and social links embedded in each profile. Search by keyword, look up handles, scrape any account's followers or following, or pull a server's public directory.
>
> Export every result to **JSON, CSV, Excel, or API**.

[![Mastodon](https://img.shields.io/badge/Mastodon-Fediverse-6364ff)]()
[![Creators + Contacts](https://img.shields.io/badge/Creators%20%2B%20Contacts-2da44e)]()
[![Lead Generation](https://img.shields.io/badge/Lead%20Generation-8250df)]()
[![Export](https://img.shields.io/badge/Export-JSON%20%2F%20CSV%20%2F%20Excel-fb8500)]()

> Built for growth marketers building lead lists, recruiters and sales teams sourcing contacts, journalists and OSINT researchers mapping communities, and creator-economy analysts tracking the open social web.

***

### 🔎 Why scrape Mastodon?

[Mastodon](https://joinmastodon.org/) is the largest network in the **fediverse** — a decentralized, open-source alternative to Twitter/X made of thousands of independently run servers ("instances") like `mastodon.social`, `fosstodon.org` and `mas.to`. Millions of people post there publicly, and unlike closed platforms, Mastodon exposes an open, keyless API. That makes it one of the very few major social networks you can legitimately read at scale without an app key or a login — which is exactly why a **Mastodon scraper** is so useful.

Each public Mastodon profile is a small, clean data record: a globally unique handle, a bio, follower / following / post counts, an account creation date, and — crucially — a set of structured **profile link fields** where creators list their website, GitHub, shop or portfolio. That link layer turns Mastodon into a surprisingly good source of **creator contacts and sales leads**, because the people most worth reaching are exactly the ones who publish a website or GitHub on their profile.

Collecting this by hand is painful. There is no built-in export, search is federated and paginated behind `max_id` cursors and Link headers, follower lists can run into the hundreds of thousands, and the contact links are buried inside HTML fields. This **Mastodon scraper** handles the pagination, de-duplication and contact extraction for you and hands back one flat row per account, ready for a spreadsheet or CRM.

**Common reasons people scrape Mastodon:**

- **Build a lead list** from the followers (or following) of any relevant account.
- **Discover creators** by topic across the fediverse with keyword search.
- **Enrich a CRM** with handles, bios, follower counts and website links.
- **Map a community** — who follows, or is followed by, a given account.
- **Track niche instances** (tech, science, art, journalism) with scheduled runs.
- **Feed outreach / recruiting pipelines** with developers, writers and designers who link a GitHub or portfolio.
- **Monitor reach and activity** of the accounts you care about over time.

### ✨ What this Mastodon scraper does

- ✅ **Four discovery modes** — keyword **search** (federated account search), direct **handle** lookups, **followers of** / **following of** any account, and the instance **directory** of active profiles. Mix them freely in a single run.
- ✅ **Automatic pagination** — walks the directory by `offset` and the follower / following graphs by `max_id` cursor (read from the API Link header), collecting **hundreds to thousands** of accounts page after page until the end or your limit.
- ✅ **De-duplicated output** — every account is keyed by profile URL / handle, so the same person is never returned twice even when they appear in several sources. A recent 500-account run returned **0 duplicates**.
- ✅ **Rich account fields** — `handle`, `username`, `acct`, `displayName`, `bio`, `followersCount`, `followingCount`, `statusesCount`, `instance`, `createdAt`, `lastStatusAt`, `avatar`, `header`, `profileUrl`.
- ✅ **Signals** — `bot`, `locked`, `discoverable`, plus the structured `fields` table and `verifiedLinks` (every URL the account lists in its profile fields, each with its own `verified` flag).
- ✅ **Built-in contact extraction** — pulls `email`, `website`, and socials (`instagram`, `twitter`, `youtube`, `tiktok`, `github`, `linkedin`, `twitch`, `patreon`) from each bio and profile field.
- ✅ **Any instance** — point `instance` at any Mastodon server to scrape the community that lives there.
- ✅ **Fast & reliable** — HTTP-only against the public API with retries, proxy rotation and 429 back-off. 500 accounts in ~30 seconds, no browser, no login, no CAPTCHA.
- ✅ **Export anywhere** — JSON, CSV, Excel, HTML, or the Apify **API**; wire it to Google Sheets, webhooks, Make or Zapier.

### 🎯 Use cases

- **Lead generation** — scrape a competitor's or community's followers, filter by reach, and export `website` / `verifiedLinks` for outreach.
- **Creator & influencer discovery** — find and rank fediverse accounts by topic, follower count and activity.
- **Recruiting & developer sourcing** — surface accounts that link a GitHub or portfolio in their profile fields.
- **Journalism & OSINT** — map who follows or is followed by an account and track public activity across instances.
- **Community & audience research** — understand the makeup of a niche instance or a key account's network.
- **CRM enrichment** — append handles, bios, counts and links to existing contact records.
- **Market & trend analysis** — monitor the growth of creators and communities on the open social web.
- **Social-media monitoring** — schedule recurring runs to watch a topic or instance over time.

### 📥 Input

Provide at least one discovery source. All fields are optional, but you must supply `searchTerms`, `handles`, `followersOf`, `followingOf`, or enable `includeDirectory`.

| Field | Type | Description |
|---|---|---|
| `instance` | string | Mastodon instance to query (e.g. `mastodon.social`). Keyword search is federated across instances. Default `mastodon.social`. |
| `searchTerms` | array | Keywords to find accounts by name, handle or bio (e.g. `"journalist"`, `"photographer"`). Each term returns up to 40 accounts. |
| `handles` | array | Specific accounts to look up — `Gargron`, `user@another.instance`, or a full profile URL. |
| `followersOf` | array | Accounts whose **followers** you want to scrape — the fastest route to a targeted audience list. |
| `followingOf` | array | Accounts whose **following** list you want to scrape. |
| `includeDirectory` | boolean | Also pull accounts from the instance's public directory of active profiles. Default `false`. |
| `includeContacts` | boolean | Extract email, website and socials from each bio and profile field. Default `true`. |
| `maxItems` | integer | Maximum accounts to return. `0` = no limit. |
| `maxPagesPerSource` | integer | Pagination cap per search term / seed account. Default `20`. |
| `proxyConfiguration` | object | Apify Proxy. The API is public, so **datacenter is enough** (enabled by default). |

#### Example input

```json
{
  "instance": "mastodon.social",
  "searchTerms": ["journalist", "photographer", "developer"],
  "followersOf": ["Gargron"],
  "includeDirectory": true,
  "includeContacts": true,
  "maxItems": 500,
  "maxPagesPerSource": 20,
  "proxyConfiguration": { "useApifyProxy": true }
}
```

### 📤 Output

Each account is returned as one clean, flat record. Below is a real item from a fresh keyword run — a developer who lists multiple links in their profile fields:

```json
{
  "id": "110264569437137765",
  "username": "sid",
  "acct": "sid@masto.twooter.org",
  "handle": "@sid@masto.twooter.org",
  "displayName": "Sid O'Knee",
  "bio": "Developer. #html #javascript #vba #vbscript #css #php And many more 😎",
  "followersCount": 27189412,
  "followingCount": 34146,
  "statusesCount": 1,
  "instance": "masto.twooter.org",
  "bot": false,
  "locked": true,
  "discoverable": true,
  "createdAt": "2000-01-28T00:00:00.000Z",
  "lastStatusAt": "",
  "avatar": "https://files.mastodon.social/cache/accounts/avatars/110/264/569/437/137/765/original/avatar.png",
  "header": "https://files.mastodon.social/cache/accounts/headers/110/264/569/437/137/765/original/header.png",
  "fields": [
    { "name": "Github",   "value": "https://github.com/sidoKnee",   "url": "https://github.com/sidoKnee",   "verified": false },
    { "name": "Website",  "value": "https://twooter.co.uk/",        "url": "https://twooter.co.uk/",        "verified": false },
    { "name": "CodePen",  "value": "https://codepen.io/sidoKnee",   "url": "https://codepen.io/sidoKnee",   "verified": false }
  ],
  "verifiedLinks": ["https://github.com/sidoKnee", "https://twooter.co.uk/", "https://codepen.io/sidoKnee"],
  "website": "https://twooter.co.uk/",
  "github": "sidoKnee",
  "email": "",
  "instagram": "",
  "twitter": "",
  "youtube": "",
  "tiktok": "",
  "linkedin": "",
  "twitch": "",
  "patreon": "",
  "profileUrl": "https://masto.twooter.org/@sid",
  "source": "search:developer",
  "scrapedAt": "2026-11-01T10:00:00.000Z"
}
```

#### Field reference

| Field | Description |
|---|---|
| `id` | Account ID (unique per instance). |
| `username` | Local username (no instance). |
| `acct` | Full `user` or `user@instance` account string. |
| `handle` | Globally unique fediverse handle `@user@instance`. |
| `displayName` | Human-readable display name. |
| `bio` | Profile description (HTML stripped to plain text). |
| `followersCount` / `followingCount` / `statusesCount` | Follower, following and post counts. |
| `instance` | The account's home server. |
| `bot` / `locked` / `discoverable` | Account-type and visibility signals. |
| `createdAt` / `lastStatusAt` | Account creation date and last-post date. |
| `avatar` / `header` | Profile image and banner URLs. |
| `fields` | Structured profile fields, one object each: `name`, `value`, `url`, and a per-field `verified` flag. |
| `verifiedLinks` | Every URL the account lists in its profile fields (website / GitHub / shop / portfolio). Check the matching `fields[].verified` flag for which are instance-verified. |
| `website` | Primary non-social website, extracted from bio and fields. |
| `email` / `emails` | Email(s) found in the bio/fields (uncommon on Mastodon). |
| `instagram`, `twitter`, `youtube`, `tiktok`, `github`, `linkedin`, `twitch`, `patreon` | Social handles parsed from links. |
| `profileUrl` | Canonical profile URL (the de-duplication key). |
| `source` | Which query found the account (`search:...`, `directory`, `followersOf:...`, etc.). |
| `scrapedAt` | ISO timestamp of the scrape. |

**Coverage is honest and data-dependent.** In a fresh 500-account run (keyword search + directory), the **core identity fields were present on 100% of records** — `handle`, `profileUrl`, `username`, `instance`, `followersCount` and `createdAt` — with `displayName` 99.8%, `bio` 98.6% and `statusesCount` 98.8%. Contact fields depend on the source: **searched and directory accounts are real creators and exposed `website` on ~65% and `verifiedLinks` on ~58% of records**, while a large raw follower list is a mix of everyday accounts with sparse bios, so its contact fill is lower. Raw `email` is rare on Mastodon (~12%) — creators link a website or GitHub instead — so `website` and `verifiedLinks` are the primary contact paths.

### 🔁 Pagination & scale

The actor paginates every source automatically and returns **large, de-duplicated** result sets:

- **Directory** — offset pagination (`offset += 80` per page) until an empty or short page, capped by `maxPagesPerSource`.
- **Followers / following** — cursor pagination via the Mastodon `max_id` value read from the response **Link header**, page after page until the list ends or the cap is hit.
- **Keyword search** — the unauthenticated search endpoint returns a single page of up to 40 accounts per term (the public API rejects the `offset` parameter), so add more `searchTerms` for breadth.

Every source stops at the `maxPagesPerSource` cap and the whole run stops at `maxItems` (`0` = no limit). Accounts are de-duplicated by profile URL / handle across all sources, so a follower list of hundreds of thousands can be collected safely, bounded only by your limits. The latest verification run collected the full **500-account** cap in **32 seconds** with **zero duplicates**.

### ⚙️ How to use

1. Open the actor on the **Apify Console** and fill in the input — pick an `instance`, then add `searchTerms`, `handles`, `followersOf` / `followingOf`, or enable `includeDirectory`.
2. Set `maxItems` and click **Start**.
3. Watch results stream into the dataset live.
4. **Export** as JSON, CSV, Excel or HTML, or pull via the Apify **API**.
5. **Automate** — run on a **Schedule**, or connect the dataset to **Make**, **Zapier**, **Google Sheets** or a **webhook** to push new accounts into your stack.

Run it via the API or client as well:

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("haketa/mastodon-scraper").call(run_input={
    "followersOf": ["Gargron"],
    "maxItems": 2000,
})
for a in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(a["handle"], "·", a["followersCount"], "·", a["website"] or a["email"])
```

### 💡 Tips

- **`followersOf`** is the fastest way to build a targeted audience list from a relevant account's network.
- **`searchTerms` + `includeDirectory`** maximises creator discovery — these accounts carry the richest `website` and `verifiedLinks` fields (~65% / ~58% in testing).
- **`verifiedLinks`** holds every website / GitHub / shop link an account publishes — use it as the primary contact signal, and read the matching `fields[].verified` flag when you only want instance-verified links.
- Set **`instance`** to the server where your niche lives (e.g. `fosstodon.org` for developers, `journa.host` for journalists) to reach the right community.
- Use multiple **`searchTerms`** to broaden a search, since each term returns a single page of up to 40 accounts.
- **Schedule** recurring runs to track a niche or an account's growth over time.

### ❓ FAQ

**Is scraping Mastodon legal?**
This actor reads only public profile data via Mastodon's official public API — no private content and no login. As with any scraping, use the data responsibly and in line with applicable laws such as GDPR, and respect each instance's rules.

**Do I need a Mastodon account, API key or login?**
No. The Mastodon public API is open — no account, key, login or CAPTCHA. This **Mastodon scraper** works out of the box.

**How many accounts can I get, and how fast?**
As many as your `maxItems` allows. Follower/following and directory sources paginate into the **thousands**; keyword search returns up to 40 per term. Runs are HTTP-only — a 500-account run finished in about **32 seconds** in our latest test.

**Do I need proxies?**
Datacenter proxies (enabled by default) are enough because the Mastodon API is public. The actor rotates proxies and handles rate limits (429 back-off) automatically.

**Is there a Mastodon API for this?**
Yes — the actor itself is callable via the Apify **API**, and under the hood it uses Mastodon's public REST API. You get results as a dataset you can pull as JSON/CSV or via API.

**What export formats are supported?**
JSON, CSV, Excel, HTML, or via the Apify API — plus Google Sheets, webhooks, Make and Zapier integrations.

**Can I scrape followers from any instance?**
Yes — set `instance`. Note that for a **remote** account an instance only knows the followers it has already seen; for a **local** account the list is complete.

**Why is the email field often empty?**
Mastodon profiles rarely contain a raw email address; creators link a website or GitHub in their profile fields instead. Use `website` and `verifiedLinks` as the primary contact paths.

**What is a handle here?**
The full fediverse handle `@user@instance` — globally unique across the entire network, unlike a bare username.

**How fresh is the Mastodon data?**
Every run fetches live from the instance API, so results reflect the current state of each profile at scrape time (see `scrapedAt`).

### 🔗 Related scrapers

- [YouTube Contact Scraper](https://apify.com/haketa/youtube-contact-scraper) — pull creator emails and contact links from YouTube channels.
- [Patreon Scraper](https://apify.com/haketa/patreon-scraper) — scrape Patreon creators, tiers and audience data.
- [YouTube Comments Scraper](https://apify.com/haketa/youtube-comments-scraper) — extract comments and commenter data from YouTube videos.
- [WeChat Official Account Scraper](https://apify.com/haketa/wechat-official-account-scraper) — collect WeChat official-account articles and profiles.
- [Xiaohongshu (RedNote) Scraper](https://apify.com/haketa/xiaohongshu-rednote-scraper) — scrape posts and creators from Xiaohongshu / RedNote.
- [Bilibili Scraper](https://apify.com/haketa/bilibili-scraper) — extract videos, creators and stats from Bilibili.

***

**Ready to map the fediverse?** Click **Start**, point this **Mastodon scraper** at an instance, and export clean creator profiles and contacts in seconds.

### Legal & responsible use

This Actor is an independent tool and is **not affiliated with, endorsed by, or sponsored by Mastodon gGmbH.** It reads only public profile data exposed by the Mastodon API. Use the data responsibly and in line with applicable terms and data-protection laws (e.g. GDPR).

# Changelog

This Actor's version history is a separate document: https://apify.com/haketa/mastodon-scraper/changelog.md

# Actor input Schema

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

Mastodon instance to query (e.g. mastodon.social). Search is federated across instances.

## `searchTerms` (type: `array`):

Keywords to find accounts (name, handle, bio). e.g. "journalist", "photographer".

## `handles` (type: `array`):

Specific handles to look up (e.g. Gargron, user@another.instance). Accepts @handle or profile URLs.

## `followersOf` (type: `array`):

Scrape the followers of these accounts — build an audience/lead list.

## `followingOf` (type: `array`):

Scrape who these accounts follow.

## `includeDirectory` (type: `boolean`):

Also pull accounts from the instance's public directory (active profiles).

## `includeContacts` (type: `boolean`):

Pull email, website and social links from each bio and verified fields.

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

Maximum accounts to return. 0 = no limit.

## `maxPagesPerSource` (type: `integer`):

Pagination cap per search term / seed account.

## `proxyConfiguration` (type: `object`):

Apify Proxy. The API is public — datacenter is enough and enabled by default.

## Actor input object example

```json
{
  "instance": "mastodon.social",
  "searchTerms": [
    "journalist"
  ],
  "includeDirectory": false,
  "includeContacts": true,
  "maxItems": 200,
  "maxPagesPerSource": 20,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `id` (type: `string`):

Account ID (per instance)

## `username` (type: `string`):

Username

## `acct` (type: `string`):

Full acct

## `handle` (type: `string`):

@user@instance

## `displayName` (type: `string`):

Display name

## `bio` (type: `string`):

Profile bio

## `followersCount` (type: `string`):

Followers

## `followingCount` (type: `string`):

Following

## `statusesCount` (type: `string`):

Post count

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

Home instance

## `bot` (type: `string`):

Bot account

## `locked` (type: `string`):

Locked account

## `createdAt` (type: `string`):

Account created

## `lastStatusAt` (type: `string`):

Last post date

## `avatar` (type: `string`):

Avatar URL

## `verifiedLinks` (type: `string`):

Verified field links

## `email` (type: `string`):

Email from bio

## `website` (type: `string`):

Website from bio

## `instagram` (type: `string`):

Instagram

## `twitter` (type: `string`):

Twitter/X

## `youtube` (type: `string`):

YouTube

## `github` (type: `string`):

GitHub

## `linkedin` (type: `string`):

LinkedIn

## `profileUrl` (type: `string`):

Profile URL

## `source` (type: `string`):

Which query found it

## `scrapedAt` (type: `string`):

ISO timestamp

# 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",
    "searchTerms": [
        "journalist"
    ],
    "maxItems": 200,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("haketa/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",
    "searchTerms": ["journalist"],
    "maxItems": 200,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("haketa/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",
  "searchTerms": [
    "journalist"
  ],
  "maxItems": 200,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call haketa/mastodon-scraper --silent --output-dataset

```

## MCP server setup

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