TikTok's official API is invite-only for most developers, and the application process is selective. Pulse reads TikTok's own public pages from a residential IP — the same numbers a visitor sees — and returns them as clean JSON with one GET request.
curl "https://pulse.walls.sh/metrics?url=https://www.tiktok.com/@khaby.lame/video/6967348974688816390"
{
"platform": "tiktok",
"views": 39600000,
"likes": 5500000,
"comments": 39500,
"shares": 22300,
"publishedAt": "2021-05-28T14:32:30.000Z",
"title": "Boss.. one shot - 3 points",
"author": "@khaby.lame"
}
Those are live numbers — fetched at time of writing. Pulse returns
views, likes, comments, shares,
publishedAt, title, and author for any public
TikTok post.
curl "https://pulse.walls.sh/metrics?url=https://vm.tiktok.com/ZMhQXu7RL/"
vm.tiktok.com short links resolve automatically — paste them
directly without expanding first.
curl "https://pulse.walls.sh/profile?url=https://www.tiktok.com/@charlidamelio"
{
"platform": "tiktok",
"handle": "charlidamelio",
"followers": 158300000,
"posts": 3150
}
Profile URLs return follower count, following count, and total video count for any public TikTok creator.
JavaScript / Node
const videoUrl = "https://www.tiktok.com/@khaby.lame/video/6967348974688816390";
const res = await fetch(
"https://pulse.walls.sh/metrics?url=" + encodeURIComponent(videoUrl)
);
const { views, likes, comments, shares, publishedAt } = await res.json();
console.log({ views, likes, comments, shares, publishedAt });
Python
import requests
video_url = "https://www.tiktok.com/@khaby.lame/video/6967348974688816390"
data = requests.get(
"https://pulse.walls.sh/metrics",
params={"url": video_url}
).json()
print(data["views"], data["likes"], data["comments"])
GET /metrics/batch?url=TIKTOK_URL_A&url=TIKTOK_URL_B&url=TIKTOK_URL_C
Up to 50 TikTok URLs per batch request, order preserved. You can also
mix TikTok with YouTube, X, and Bluesky URLs in the same batch — same endpoint, same
response shape. A private or deleted video comes back as { url, error:
"content_unavailable" } without failing the rest.
curl "https://pulse.walls.sh/metrics/batch?url=TIKTOK_URL_1&url=TIKTOK_URL_2"
# → { "count": 2, "results": [ { "views": …, "likes": … }, { "views": …, "likes": … } ] }
Every /metrics call saves a timestamped snapshot. After the
second fetch, /history returns the full series:
curl "https://pulse.walls.sh/history?url=https://www.tiktok.com/@khaby.lame/video/6967348974688816390"
# → { "points": [ { "t": "…", "views": 39500000, "likes": 5490000 }, … ] }
Add &since=<ISO-timestamp> to get only new points since
your last poll. Pulse stores the time series; you don't need a separate database.
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 · YouTube metrics without an API key.
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