Mastodon's API is public and per-instance — but there's no unified endpoint, every instance has a different base URL, and the federation means a post on one server is boosted by users across dozens of others. Pulse wraps the per-instance public REST API into one call: give it a Mastodon post URL, get back normalized engagement data as JSON. No auth, no instance registration, no signup.
curl "https://pulse.walls.sh/metrics?url=https://mastodon.social/@Mastodon/116697945683857980"
{
"platform": "mastodon",
"views": null,
"likes": 652,
"comments": 10,
"shares": 436,
"publishedAt": "2026-06-05T14:22:17.000Z",
"title": "Following the @EUCommission Tech Sovereignty and Open Source Strategy…",
"author": "@Mastodon"
}
Those are live numbers. Pulse returns likes (favourites),
comments (replies), shares (boosts), publishedAt,
title, and author for any public Mastodon post on any instance.
Mastodon doesn't have view counts at the protocol level — null is accurate.
# mastodon.social curl "https://pulse.walls.sh/metrics?url=https://mastodon.social/@Mastodon/116697945683857980" # fosstodon.org curl "https://pulse.walls.sh/metrics?url=https://fosstodon.org/@kev/12345678" # hachyderm.io curl "https://pulse.walls.sh/metrics?url=https://hachyderm.io/@user/12345678"
Pulse detects the instance from the URL and calls that instance's public REST API — no hardcoded list of servers, no registration required. Posts on any public Mastodon instance work.
curl "https://pulse.walls.sh/profile?url=https://mastodon.social/@Mastodon"
{
"platform": "mastodon",
"handle": "Mastodon",
"name": "Mastodon",
"followers": 872954,
"following": 47,
"posts": 516
}
Profile URLs return follower count, following count, and post count for any
public Mastodon account on any instance. Remote profiles in
@[email protected] form also work.
JavaScript / Node
const postUrl = "https://mastodon.social/@Mastodon/116697945683857980";
const res = await fetch(
"https://pulse.walls.sh/metrics?url=" + encodeURIComponent(postUrl)
);
const { likes, comments, shares, publishedAt } = await res.json();
console.log({ likes, comments, shares, publishedAt });
Python
import requests
post_url = "https://mastodon.social/@Mastodon/116697945683857980"
data = requests.get(
"https://pulse.walls.sh/metrics",
params={"url": post_url}
).json()
print(data["likes"], data["shares"], data["comments"])
GET /metrics/batch?url=MASTODON_URL_A&url=MASTODON_URL_B&url=MASTODON_URL_C
Up to 50 URLs per batch request, order preserved. Mix Mastodon posts with
posts from other platforms — YouTube, X, TikTok, Bluesky, Instagram — in the same batch.
A deleted or private post returns { url, error: "content_unavailable" }
without failing the rest.
curl "https://pulse.walls.sh/metrics/batch?url=MASTODON_URL_1&url=BLUESKY_URL"
# → { "count": 2, "results": [ { "likes": …, "shares": … }, { "likes": …, "shares": … } ] }
Every /metrics call saves a timestamped snapshot. After the
second fetch, /history returns the full series plus computed growth stats:
curl "https://pulse.walls.sh/history?url=https://mastodon.social/@Mastodon/116697945683857980"
# → {
# "points": [ { "t": "…", "likes": 640, "shares": 420 }, … ],
# "latest": { "likes": 652, "shares": 436 },
# "delta": { "hours_elapsed": 24.0, "likes": 12, "shares": 16 },
# "velocity": { "likes_per_hour": 0.5, "shares_per_hour": 0.67 }
# }
Add &since=<ISO-timestamp> to poll only new snapshots.
The velocity field gives you engagement rate per hour without computing it yourself.
Free: 120 calls/minute, no account or signup needed. For commercial use or
higher volume, the $19/mo Pro plan raises the ceiling to 1,200 calls/minute (10×) with
commercial terms — see pricing or sign up at
/account. All endpoints set RateLimit-*
response headers so your code can self-throttle before hitting a 429.
More: full API docs · OpenAPI spec · all supported platforms · Bluesky metrics · X/Twitter metrics without the API.