Mastodon Scraper · Posts, Accounts, Hashtags & Instances avatar

Mastodon Scraper · Posts, Accounts, Hashtags & Instances

Pricing

from $0.70 / 1,000 post returneds

Go to Apify Store
Mastodon Scraper · Posts, Accounts, Hashtags & Instances

Mastodon Scraper · Posts, Accounts, Hashtags & Instances

Mastodon scraper for fediverse posts, profiles, hashtags, and instance timelines. Extract public Mastodon statuses, user accounts, engagement metrics, media, and outbound links with no login required.

Pricing

from $0.70 / 1,000 post returneds

Rating

0.0

(0)

Developer

Tarek Etman

Tarek Etman

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

1

Monthly active users

9 hours ago

Last modified

Share

reapX — public sources in, addressable records out

Mastodon Scraper · Posts, Accounts, Hashtags & Instances

Mastodon scraper to scrape public posts, profiles, hashtags, and account feeds from any Mastodon fediverse instance (such as mastodon.social). Returns clean structured data per post: author details, follower counts, post text, engagement metrics, media, and outbound links.

Maintained by reapX. Every row cites the Apify run that produced it — nothing is inferred, modelled or filled in, and a field absent from the source is absent from the row. The extracted archive for this source is browsable at reapx.dev/data/mastodon-scraper/ and mirrored as an open dataset on Hugging Face and Kaggle. Questions: reapxdev@proton.me

No API key, token, app registration, or login required. This Mastodon scraper reads Mastodon's public REST API across any instance.

What you get per post

Field
handlethe author as instance/username - unique across the whole fediverse
accountAcctthe same author in Mastodon's native user@instance form
accountDisplayName · accountFollowers · accountStatusCount · accountIsBotwho posted it
content · spoilerText · language · visibility · isSensitivethe post
favouritesCount · reblogsCount · repliesCountengagement as the reading instance sees it
hashtags · mentionCount · mediaCount · mediaTypeswhat is in it
linkUrl · linkTitlewhere 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.

Input configuration

Every field is optional. The prefilled values below are what runs if you press Start without changing anything.

Where to read

An instance's hashtag timeline is federated, so one instance sees posts from across the fediverse.

FieldTypeAcceptsWhat it does
instanceslistone value per lineMastodon 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. Prefilled with ["mastodon.social"].

What to read

Give hashtags, accounts, the instance timeline, trending - or any combination.

FieldTypeAcceptsWhat it does
hashtagslistone value per lineHashtags to read, one per line, with or without the #. Each is fetched as its own timeline. Prefilled with ["photography"].
accountslistone value per lineAccounts whose public posts to read, one per line, as user@instance or a bare username for a local account.
includePublicTimelinetrue/falsecheckboxRead 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.
includeTrendingtrue/falsecheckboxRead what each instance is currently amplifying through its trends endpoint.

Filters

All optional.

FieldTypeAcceptsWhat it does
localOnlytrue/falsecheckboxRestrict hashtag and public timelines to posts written on the instance itself, excluding federated posts from elsewhere.
onlyWithMediatrue/falsecheckboxKeep only posts carrying at least one image, video or audio attachment.
excludeRepliestrue/falsecheckboxDrop posts that reply to another post.
excludeReblogstrue/falsecheckboxDrop boosts (reblogs) and keep only original posts.
languagestringfree textKeep only posts the author tagged with this two-letter language code.
minFavouritesinteger0 to 1000000Keep only posts with at least this many favourites - the simplest way to skim the top of a busy hashtag.

Output

How many rows you get and how politely they are fetched.

FieldTypeAcceptsWhat it does
maxPostsinteger1 to 5000Hard ceiling on the rows this run produces, and therefore on what it costs. You are charged per post returned. Prefilled with 100.
requestsPerSecondinteger1 to 5Politeness against each instance. Mastodon instances are volunteer-run; keep this low. Prefilled with 2.

Pricing

Pay per event. The primary event is Post returned (post-returned), charged at $0.001 per event on the free plan, falling to $0.0005 on the highest tier.

One public Mastodon post delivered as a complete row, including its author, engagement counts, hashtags and media. Blocked instances and empty result sets are never charged.

Other charged events: apify-actor-start (Actor Start).

Minimum charge cap per run: $0.05.

Tiered discounts apply automatically on every paid Apify plan. Platform usage is absorbed by the Actor, so the per-event price is the whole price.

Usage examples

The prefilled run, which is what Start does with nothing changed

{
"instances": [
"mastodon.social"
],
"hashtags": [
"photography"
],
"maxPosts": 100,
"requestsPerSecond": 2
}

Filter by instances

{
"instances": [
"mastodon.social",
"fosstodon.org"
],
"hashtags": [
"photography"
],
"maxPosts": 100,
"requestsPerSecond": 2
}

Filter by hashtags

{
"instances": [
"mastodon.social"
],
"hashtags": [
"opensource",
"rustlang"
],
"maxPosts": 100,
"requestsPerSecond": 2
}

Filter by accounts

{
"instances": [
"mastodon.social"
],
"hashtags": [
"photography"
],
"maxPosts": 100,
"requestsPerSecond": 2,
"accounts": [
"Gargron@mastodon.social",
"torproject@mastodon.social"
]
}

Filter by include the instance's public timeline

{
"instances": [
"mastodon.social"
],
"hashtags": [
"photography"
],
"maxPosts": 100,
"requestsPerSecond": 2,
"includePublicTimeline": true
}

Output example

One row, exactly as the actor wrote it to the dataset:

{
"handle": "mastodon.social/QasimRashid",
"accountAcct": "QasimRashid@mastodon.social",
"accountDisplayName": "Qasim Rashid, Esq.",
"accountUrl": "https://mastodon.social/@QasimRashid",
"accountFollowers": 92218,
"accountFollowing": 106,
"accountStatusCount": 4537,
"accountIsBot": false,
"accountCreatedAt": "2022-10-30T00:00:00.000Z",
"instanceDomain": "mastodon.social",
"sourceInstance": "fosstodon.org",
"statusId": "117029450607940916",
"statusUrl": "https://mastodon.social/@QasimRashid/117029450548542124",
"content": "Hey so the Trump regime unilaterally forced Haitian Americans into undocumented status, and is now using that undocumented status as an excuse to force them to wear ankle monitors. A reminder that the \"just follow the...",
"spoilerText": null,
"createdAt": "2026-08-03T03:28:20.000Z",
"editedAt": null,
"language": "en"
}

That row carries 32 fields in total; 18 are shown.

Fields on every row

FieldTypeWhat it is
handlestringThe author's globally unique handle as instance/username. Unique across the whole fediverse, where a bare username is not, and stable across runs.
accountAcctstringThe author in Mastodon's native user@instance form.
accountDisplayNamestringThe name the author shows on their profile.
accountUrlstringThe author's public profile page.
accountFollowersintegerHow many accounts follow the author, as their home instance reports it.
accountFollowingintegerHow many accounts the author follows.
accountStatusCountintegerHow many posts the author has published in total.
accountIsBottrue/falseTrue when the account declares itself automated.
accountCreatedAtstringWhen the author's account was created.
instanceDomainstringThe instance the author's account lives on.
sourceInstancestringThe instance this run read the post through. Differs from the author's instance whenever a post arrived by federation.
statusIdstringThe post's id on the instance it was read from.
statusUrlstringThe post's canonical public address on its author's instance.
contentstringThe post body reduced from HTML to readable text.
spoilerTextstringThe content warning the author put in front of the post, if any.
createdAtstringWhen the post was published, in UTC.
editedAtstringWhen the post was last edited, if it was.
languagestringThe two-letter language code the author tagged the post with.
visibilitystringHow widely the author published the post.
isSensitivetrue/falseTrue when the author flagged the post or its media as sensitive.
isReplytrue/falseTrue when the post replies to another post.
isReblogtrue/falseTrue when the post is a boost of someone else's post rather than original.
repliesCountintegerReplies the post has received, as the reading instance sees them.
reblogsCountintegerBoosts the post has received, as the reading instance sees them.
favouritesCountintegerFavourites the post has received, as the reading instance sees them.
hashtagslistEvery hashtag the post carries.
mentionCountintegerHow many accounts the post mentions.
mediaCountintegerHow many images, videos or audio files the post carries.
mediaTypeslistThe distinct kinds of media attached to the post.
linkUrlstringThe URL of the link preview card the post generated, if it linked out.
linkTitlestringThe title of the link preview card.
retrievedAtstringWhen this row was read, in UTC.

3 named dataset views ship with it: Posts, Accounts, Engagement. They drive the Output tab in Console and the Output block on the Actor's .md page.

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.

The full published archive

Each archive page carries Dataset JSON-LD, a canonical URL and the identifiers used, so an agent can resolve an entity without running anything. Nothing on those pages is estimated or modelled.

🧪 Example input

A real, runnable configuration — this is an actual input this Actor has run with.

{
"instances": [
"chaos.social"
],
"includePublicTimeline": true,
"localOnly": true,
"maxPosts": 500,
"requestsPerSecond": 2
}

📄 Sample output

One real row from a real run of this Actor, unedited.

{
"handle": "chaos.social/weizenspreu",
"accountAcct": "weizenspreu@chaos.social",
"accountDisplayName": "Kenny",
"accountUrl": "https://chaos.social/@weizenspreu",
"accountFollowers": 408,
"accountFollowing": 232,
"accountStatusCount": 926,
"accountIsBot": false,
"accountCreatedAt": "2025-10-13T00:00:00.000Z",
"instanceDomain": "chaos.social",
"sourceInstance": "chaos.social",
"statusId": "117031265960004228",
"statusUrl": "https://chaos.social/@weizenspreu/117031265960004228",
"content": "✅ Studienarbeit eingereicht",
"spoilerText": null,
"createdAt": "2026-08-03T11:10:01.001Z",
"editedAt": null,
"language": "de",
"visibility": "public",
"isSensitive": false,
"isReply": false,
"isReblog": false,
"repliesCount": 0,
"reblogsCount": 0,
"favouritesCount": 0,
"hashtags": [],
"mentionCount": 0,
"mediaCount": 0,
"mediaTypes": [],
"linkUrl": null,
"linkTitle": null,
"retrievedAt": "2026-08-03T11:11:02Z"
}

How it works

  1. You set the filters below, or none at all - every field is optional.
  2. The Actor calls the public mastodon.social API directly over HTTP. There is no key to obtain, no login and no headless browser, so a run is fast and cannot break on a UI change.
  3. It pages through the results until your maximum is reached or the source runs out of matches.
  4. Every row is pushed to the dataset as it is built - never buffered to the end. A run that hits its time limit still returns everything it collected.
  5. You are charged post-returned at $0.001 per row, and nothing for Apify platform usage. The maximum-results field is therefore your cost cap, and Apify Store discounts apply on top.

💬 Your feedback

Found a bug, or need a field this does not return yet? Open an issue on the Actor's Issues tab, or write to reapxdev@proton.me. Bugs get fixed and reasonable field requests get added.

⚠️ Run outcomes and error handling

This Actor reports what happened in the run's status message, and it always keeps whatever it collected. These are the outcomes you can get and what each one means.

OutcomeWhat it means
SuccessRows were returned and you were charged post-returned at $0.001 per row.
No matchesThe source returned nothing for your filters. Nothing is charged. Widen the date window or drop a filter.
Partial - source refusedThe source rate-limited or refused some requests. The affected items are skipped and named in the log, and everything already collected is still pushed. A block never discards a run's work.
Private or login-walledThe requested item is not publicly readable. It is skipped and named; the rest of the run continues.

What is guaranteed either way

  • Every row is pushed as it is built, not buffered to the end of the run. Anything that buffers output loses everything to a timeout, a block or a migration; this does not.
  • A field absent from the source is absent from the row. Nothing is inferred, modelled or filled in to make a row look complete.

🧭 Ready-made configurations

These are saved, published configurations of this exact Actor. Open one and run it as it is, or copy its input as a starting point - each link is a live page with the full input and its output schema.

ConfigurationInput
#photography Posts on Mastodoninstances: mastodon.social; hashtags: photography; maxPosts: 500
#opensource Posts on Mastodoninstances: mastodon.social; hashtags: opensource; maxPosts: 500
#linux Posts on Mastodoninstances: mastodon.social; hashtags: linux; maxPosts: 500
#rustlang Posts on Mastodoninstances: mastodon.social; hashtags: rustlang; maxPosts: 500
#python Posts on Mastodoninstances: mastodon.social; hashtags: python; maxPosts: 500
#javascript Posts on Mastodoninstances: mastodon.social; hashtags: javascript; maxPosts: 500
#golang Posts on Mastodoninstances: mastodon.social; hashtags: golang; maxPosts: 500
#webdev Posts on Mastodoninstances: mastodon.social; hashtags: webdev; maxPosts: 500
#devops Posts on Mastodoninstances: mastodon.social; hashtags: devops; maxPosts: 500
#infosec Posts on Mastodoninstances: mastodon.social; hashtags: infosec; maxPosts: 500
#privacy Posts on Mastodon-
#selfhosted Posts on Mastodon-
#fediverse Posts on Mastodon-
#ai Posts on Mastodon-

There are 49 of these in total, all listed on the Actor's Examples tab.