One endpoint. Give it a public post URL, get normalized engagement metrics as JSON. No signup, no API key.
Pulse is free right now — /metrics needs no payment, no key, no account. (Pulse also speaks x402, so an agent can pay per call in USDC if billing is ever enabled — but it's off.)
curl "https://pulse.walls.sh/metrics?url=https://www.youtube.com/watch?v=xWnqY2Mav4s"
{ "url": "https://www.youtube.com/watch?v=xWnqY2Mav4s", "platform": "youtube", "contentId": "xWnqY2Mav4s", "postType": "youtube", "views": 35707, "likes": 1072, "comments": null, "shares": null, "quotes": null, "bookmarks": null, "viewsEstimated": false, "publishedAt": "2026-06-07T17:00:38.000Z", "title": "I Built Two Apps That Make $120K/Month", "author": "Starter Story", "thumbnail": "https://i.ytimg.com/vi_webp/xWnqY2Mav4s/maxresdefault.webp", "fetchedAt": "2026-06-10T13:00:43.347Z", "history_url": "https://pulse.walls.sh/history?url=https%3A%2F%2Fwww.youtube.com%2F..." }
| Name | Required | Description |
|---|---|---|
| url | yes | A public post URL on a supported platform — or a profile URL, which auto-routes to /profile and returns follower counts (so you can hand /metrics any URL). Share-style short links (vm.tiktok.com/…, tiktok.com/t/…, t.co/…) are resolved automatically; the response's url is the canonical post URL they pointed at. |
| Field | Type | Notes |
|---|---|---|
| platform | string | youtube · x · tiktok · bluesky · mastodon · instagram · threads · linkedin |
| views | number | null | Real where the platform exposes it; otherwise estimated (see viewsEstimated) or null. |
| likes | number | null | Null when the platform hides it. |
| comments | number | null | Null when the platform hides it. For YouTube this is an abbreviated count (see commentsEstimated). |
| shares | number | null | Reshares — X retweets, TikTok shares, Bluesky reposts. Null where the platform doesn't expose it. |
| quotes | number | null | Quote posts — X quote tweets, Bluesky quotes. Null where the concept doesn't exist. |
| bookmarks | number | null | Saves — X bookmarks. No other platform exposes saves publicly. |
| viewsEstimated | boolean | True when views was estimated from likes rather than read directly. |
| commentsEstimated | boolean | True when comments is an abbreviated/approximate count — YouTube only publishes "2.4M", never the exact integer. False (exact) everywhere else. |
| publishedAt | string | null | ISO-8601 publish date. |
| title | string | null | Post title / caption (truncated). |
| author | string | null | Channel / handle (e.g. @nasa). |
| thumbnail | string | null | A representative image URL for the post. |
| history_url | string | Direct link to /history for this URL — every call records a snapshot, so this link immediately shows the growth curve after a second fetch. |
| HTTP | error | Meaning |
|---|---|---|
| 400 | url_required / bad_url / unsupported_url | Missing, malformed, or unrecognized URL. |
| 402 | — | Payment required (x402), only if billing is on. Pay and retry; clients do this automatically. |
| 404 | content_unavailable | The post is deleted, private, or region-locked — not a server error. |
| 422 | login_required | Platform returns a login wall on our residential reader — Instagram & Threads post metrics, LinkedIn profiles (always), and Instagram/Threads profile metrics when even the logged-out public page is gated. The account exists; reading it just needs a session we don't have (≠ 404, which means deleted/private). |
| 429 | rate_limited | Over 120 lookups/min (free tier). Respect Retry-After and retry. Every response carries RateLimit-Limit / -Remaining / -Reset so you can self-throttle. Pro ($19/mo) raises this to 1,200/min and includes commercial-use terms. |
| 502 | fetch_failed | Upstream platform fetch failed; safe to retry. |
Account-level metrics from a profile URL — followers, following, post count, verified, avatar.
Live for YouTube (subscribers come abbreviated, e.g. "29.8M" → parsed), TikTok
(exact counts + total hearts), Instagram (exact counts), X (followers,
following, post count), Bluesky (exact counts), and Threads (followers,
following, verified — via the public Barcelona API, no auth). LinkedIn profiles are login-walled
→ login_required.
Up to 50 profile URLs in one request — mixed platforms welcome. Same URL conventions as
/metrics/batch. Order preserved; each item is a profile object or
{ url, error }. Add &format=csv for a spreadsheet of follower
counts (url,platform,handle,name,followers,following,posts,verified,error) — capture
many accounts straight into Sheets.
{ "count": 2, "results": [ { "platform": "youtube", "handle": "@mkbhd", "followers": 21000000 … }, { "platform": "instagram", "handle": "nasa", "followers": 104395242 … } ] }
The growth curve of a post or a profile. Every fresh /metrics fetch records a
{ t, views, likes, comments } snapshot, and every fresh /profile fetch records
{ t, followers, posts } — so repeat lookups build a series over time. Returns
{ url, platform, kind, count, points }. An empty series just means the URL hasn't been fetched yet.
Polling? Add since=<ISO-8601 or unix ms> to get only the points after that moment —
the delta, not the whole series. Add format=csv for a chart-ready spreadsheet
(t,views,likes,comments,shares,followers, one row per snapshot) — drop it into Sheets and plot.
Need a whole set at once? Pass repeated url params (or a comma-separated
urls= list, max 50) and get them all in one request. Mixed batches welcome —
post URLs return post metrics, profile URLs return profile metrics. Order is preserved; each
item is either a metrics object or { url, error } — one bad URL never fails the batch.
{ "count": 2, "results": [ { "platform": "youtube", "views": 25275, … }, { "url": "…", "error": "content_unavailable" } ] }
Add &format=csv for a spreadsheet instead of JSON — one row per URL
(url,platform,views,likes,comments,shares,followers,publishedAt,error), posts and
profiles in the same table. Drop it straight into Excel or Google Sheets.
curl "https://pulse.walls.sh/metrics/batch?format=csv&url=<a>&url=<b>"
Returns a live SVG badge you can embed in GitHub READMEs, documentation, or any page that renders images, in shields.io flat style. Give it a profile URL for a follower badge ("platform followers: count"), or a post URL for a metric badge ("platform views: count" — falls back to likes, then comments, for posts that don't expose views). Cache-Control is 1 hour so GitHub's CDN refreshes without hammering Pulse.
  
Optional params: metric (post URLs only — views, likes, or
comments; defaults to whichever the platform exposes) · label (text on the
left side) · color (right side fill; one of blue, green,
gray, red, purple, or hex).
See the badge guide for copy-paste Markdown.
Every response carries three headers so you can self-throttle before hitting a 429:
RateLimit-Limit: 120 # calls/min for your tier RateLimit-Remaining: 87 # calls left in the current window RateLimit-Reset: 34 # seconds until the window resets
Free tier: 120 calls/min. Pro ($19/mo) raises this to 1,200 calls/min (10×) and adds a commercial-use license. Get a key and upgrade at /account.
Pulse is built to be found and used by agents: