InsightSocial API
Recipes

Creator engagement scoring

Compare one creator's engagement on TikTok, Instagram and YouTube in a single ranked table, calculated with one formula from each platform's recent posts. 60 to 190 credits per creator.

You will build a vetting table for influencer marketing: a single row per platform for one creator across TikTok, Instagram and YouTube, sorted by an engagement rate you compute the same way on each network.

Cost per run

60 to 190 credits per creator: three profile calls at 10 credits each, plus one page of recent posts per platform (TikTok 10, Instagram 10–130, YouTube 10–20). Vetting a shortlist of 100 creators costs at least 6,000 credits. Checking the same creator again is charged again, so keep the scores you calculated.

How do you compare engagement rates across platforms?

Fetch each platform's profile for the follower count, and one page of the creator's recent posts for the likes and comments. Then apply one formula everywhere: for each post, (likes + comments) / followers, and take the median over the page. The median keeps one viral post from carrying the whole score.

Raw numbers do not compare on their own. A TikTok like is not an Instagram like, follower counts inflate differently, and every analytics tool defines "engagement rate" its own way. A formula you own, applied to the same fields on every platform, is what makes the ranking fair. Recent posts also avoid a trap in lifetime totals: a TikTok profile's like count is every heart the account ever received, which says little about how its videos do now.

What you need

EndpointReturnsCredits
GET /v1/tiktok/profiledata.author.followers10
GET /v1/tiktok/profile/videosRecent videos, post.engagement10
GET /v1/instagram/profiledata.author.followers10
GET /v1/instagram/profile/postsRecent posts, post.engagement10–130
GET /v1/youtube/channeldata.author.followers (rounded above 1,000)10
GET /v1/youtube/channel/videosRecent videos; includeExtras=true fills likes and comments10–20

The code

Python
# creator_scoring.py
# Run with: INSIGHTSOCIAL_API_KEY=isk_live_... python creator_scoring.py
import os
from concurrent.futures import ThreadPoolExecutor
from statistics import median

import requests

KEY = os.environ["INSIGHTSOCIAL_API_KEY"]
BASE = "https://api.insightsocial.app/v1"

# Real creators rarely share one handle, so map them per platform.
CREATOR = {"tiktok": "mrbeast", "instagram": "mrbeast", "youtube": "MrBeast"}
PATHS = {
    "tiktok":    ("tiktok/profile",    "tiktok/profile/videos",   {}),
    "instagram": ("instagram/profile", "instagram/profile/posts", {}),
    "youtube":   ("youtube/channel",   "youtube/channel/videos",  {"includeExtras": "true"}),
}

def get(path, **params):
    res = requests.get(f"{BASE}/{path}", params=params,
                       headers={"x-api-key": KEY}, timeout=120)
    return res.json()

def score(platform):
    profile_path, posts_path, extra = PATHS[platform]
    handle = CREATOR[platform]
    profile = get(profile_path, handle=handle)
    posts = get(posts_path, handle=handle, **extra)
    row = {"platform": platform, "followers": None, "engagement_rate": None, "posts_scored": 0,
           "credits": profile.get("credits_used", 0) + posts.get("credits_used", 0), "why": None}
    if not profile["success"] or not posts["success"]:
        row["why"] = (profile.get("error") or posts.get("error"))["type"]
        return row
    followers = profile["data"]["author"]["followers"]
    row["followers"] = followers
    if not followers:
        row["why"] = "no follower count"
        return row
    rates = []
    for item in posts["data"]["items"]:
        post = item["post"]
        likes, comments = post["engagement"]["likes"], post["engagement"]["comments"]
        # Skip pinned posts (old, out of order) and posts with a hidden count.
        if post["flags"]["pinned"] or likes is None or comments is None:
            continue
        rates.append((likes + comments) / followers)
    row["posts_scored"] = len(rates)
    if rates:
        row["engagement_rate"] = round(median(rates), 4)
    else:
        row["why"] = "no post with both counts"
    return row

with ThreadPoolExecutor(max_workers=3) as pool:
    rows = list(pool.map(score, CREATOR))

# Rank the comparable rows; keep the others visible but unranked.
ranked = sorted((r for r in rows if r["engagement_rate"] is not None),
                key=lambda r: r["engagement_rate"], reverse=True)
for r in ranked:
    print(f'{r["platform"]:<10} {r["followers"]:>12,}  {r["engagement_rate"]:.4f}  ({r["posts_scored"]} posts)')
for r in rows:
    if r["engagement_rate"] is None:
        print(f'{r["platform"]:<10} cannot compare: {r["why"]}')
print("credits used:", sum(r["credits"] for r in rows))

What you get back

Example output
youtube      298,000,000  0.0071  (30 posts)
tiktok       112,000,000  0.0109  (9 posts)
instagram     71,500,000  0.0052  (11 posts)
credits used: 60

The figures are illustrative. A None rate is a signal, not a low score: the profile had no follower count, or no post on the page showed both likes and comments. Treat such rows as "cannot compare", never as "best" or "worst". YouTube subscriber counts are rounded above 1,000 (followers_approximate: true on the profile), which is close enough for a ranking but not for a precise rate.

What to change

  • The formula. Add shares and saves where a platform shows them, or divide by views for a reach-based rate. A count the platform never shows is null on every row, and a count hidden on one post is null on that post only, so filter on None exactly as the code does.
  • A bigger sample. Send pagination.next_cursor back as cursor with the same handle to read older posts, at the page price each. See Pagination.
  • Score a shortlist. Loop over a list of creator maps and sort the flattened rows. Budget at least 60 credits per creator.
  • Weight the rank. Engagement rate alone favours small accounts. Blend it with followers for the trade-off your team actually makes.

On this page