LinkedIn's official Marketing API requires OAuth 2.0, page admin access, and partner approval — you can only fetch analytics for posts you own or manage. Pulse reads LinkedIn's own public pages from a residential IP and returns engagement data as clean JSON with one GET request. Any public post URL works. No API key, no OAuth flow, no partner application.
curl "https://pulse.walls.sh/metrics?url=https://www.linkedin.com/posts/williamhgates_celebrating-50-years-of-microsoft-bill-activity-7313324476165681154-1SNT"
{
"platform": "linkedin",
"views": 1238474,
"likes": 7598,
"comments": 665,
"shares": null,
"viewsEstimated": true,
"publishedAt": null,
"title": "Celebrating 50 years of Microsoft",
"thumbnail": "https://media.licdn.com/…"
}
Those are real numbers from Bill Gates' Microsoft 50th anniversary post.
likes = total reactions (LinkedIn groups all reaction types).
comments = comment count.
views is estimated from reactions using LinkedIn's typical engagement ratio
(viewsEstimated: true) — LinkedIn does not expose impression counts on public
post pages; that metric is owner-only. shares and publishedAt
are also not available on the logged-out post page and return null honestly.
LinkedIn post URLs follow this format:
https://www.linkedin.com/posts/<handle>_<slug>-activity-<id>-<suffix>
Copy the URL directly from the post's "Copy link" option on LinkedIn — paste it into Pulse as-is. The activity ID in the URL is what uniquely identifies the post.
JavaScript / Node
const postUrl = "https://www.linkedin.com/posts/williamhgates_celebrating-50-years-of-microsoft-bill-activity-7313324476165681154-1SNT";
const res = await fetch(
"https://pulse.walls.sh/metrics?url=" + encodeURIComponent(postUrl)
);
const { likes, comments, views, viewsEstimated, title } = await res.json();
console.log({ likes, comments, views, viewsEstimated, title });
Python
import requests
post_url = "https://www.linkedin.com/posts/williamhgates_celebrating-50-years-of-microsoft-bill-activity-7313324476165681154-1SNT"
data = requests.get(
"https://pulse.walls.sh/metrics",
params={"url": post_url}
).json()
print(data["likes"], data["comments"], data["views"])
GET /metrics/batch?url=LINKEDIN_URL_A&url=LINKEDIN_URL_B&url=LINKEDIN_URL_C
Up to 50 LinkedIn post URLs per batch request, order preserved. You can mix
LinkedIn with YouTube, TikTok, X, Bluesky, Mastodon, and Instagram URLs in the same batch —
same endpoint, same response shape. A deleted or private post returns
{ url, error: "content_unavailable" } without failing the rest.
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=LINKEDIN_POST_URL"
# → {
# "points": [ { "t": "…", "likes": 7400, … }, … ],
# "latest": { "likes": 7598, "comments": 665 },
# "delta": { "hours_elapsed": 24.0, "likes": 198, "comments": 12 },
# "velocity": { "likes_per_hour": 8.25, "comments_per_hour": 0.5 }
# }
The velocity field tells you whether a post is still picking up
traction — useful for tracking viral content or monitoring campaign performance over time.
LinkedIn public posts are fully visible to any browser visitor without an account — the engagement counts are right there in the page. Pulse fetches each post from a residential IP using a headless browser, waits for the page to render, and extracts the reaction and comment counts from the rendered DOM. The residential IP matters: LinkedIn returns its full SPA to residential addresses but blocks datacenter IPs at the network layer, which is why cloud-based approaches fail.
A few things LinkedIn doesn't expose on public post pages:
viewsEstimated: true).null.null./in/username) are
behind a login wall. The /profile endpoint returns login_required
for LinkedIn profile URLs.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 · how I built Pulse · Bluesky metrics.
Need more than 60 calls/day?
Pulse Pro — 10,000 calls/month for $19/mo. No OAuth, no webhooks, just curl. Cancel any time.
Get a free API key →Free tier: 60 calls/day · Pro: 10k/month · takes 30 seconds