Influencer marketing budgets keep growing, but the metric most deals are still signed on - follower count - has never been easier to inflate or less predictive of results. On TikTok the disconnect is structural: the For You Page decides delivery, not the follower graph, so a 40k-follower creator can reliably outperform a 900k-follower one. If you vet creators with public data, you need a number that captures how an audience actually behaves, not how large it looks. This guide builds that number: a 0-100 engagement score computed from three measurable pillars - content engagement, audience quality, and reach efficiency.
Everything below is procedural PHP with cURL against three of the TikLiveAPI user endpoints: /userinfo-by-username/ for the profile baseline, /user-posts/ for per-video engagement counters, and /user-followers/ for audience sampling. Field names match the live response shapes exactly, so the snippets run as soon as you swap in your API key.
Three failure modes make the headline number useless on its own. First, followers can be bought, and purchased accounts never convert. Second, even honestly earned audiences decay: a creator who blew up in 2023 carries hundreds of thousands of "zombie" followers who have not opened the app in a year. Third, and most TikTok-specific, follower count is not the delivery denominator. The algorithm shows videos to whoever it predicts will watch them, which means a creator's real reach lives in play_count on recent videos, not in the follower total on the profile.
A vetting score that survives contact with reality therefore has to answer three separate questions: do the people who see this creator's content react to it, are the followers real humans with active accounts, and does the algorithm still deliver this creator's videos beyond their existing audience?
Content engagement measures reactions per delivered view across the last 30 videos. We deliberately divide by views, not followers - the full reasoning, plus six alternative formulas and when to use each, is in our guide to TikTok engagement rate math.
Audience quality samples up to 200 followers and scores each one against simple humanity heuristics: has the account ever posted, did the owner write a bio, does anyone follow them back, and does the follow pattern look organic.
Reach efficiency compares average views per video against the follower base. A ratio near or above 1.0 means the algorithm grants the creator reach beyond their list; a ratio under 0.1 means content is only trickling out to a fraction of an audience that mostly is not watching.
All requests share one helper. It authenticates with the X-Api-Key header, enforces a timeout, checks the HTTP status, and backs off and retries when it hits a 429 - standard plans allow 200 requests per minute, and a vetting batch over a long creator list will brush against that ceiling.
function tla_get($path, $params) {
$url = "https://api.tikliveapi.com" . $path
. "?" . http_build_query($params);
for ($attempt = 1; $attempt <= 3; $attempt++) {
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 20,
CURLOPT_HTTPHEADER => array(
'X-Api-Key: YOUR_API_KEY'
),
));
$body = curl_exec($curl);
$code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
if ($code === 429) { // rate limited: back off, retry
sleep($attempt * 2);
continue;
}
if ($code !== 200 || $body === false) {
return null; // log it, skip this creator
}
$data = json_decode($body, true);
return is_array($data) ? $data : null;
}
return null;
}
$profile = tla_get("/userinfo-by-username/", array(
"username" => "tiktok"
));
$userid = $profile["user"]["id"];
$verified = $profile["user"]["verified"];
$followers = $profile["stats"]["followerCount"];
$hearts = $profile["stats"]["heartCount"];
$videoCount = $profile["stats"]["videoCount"];
Two things matter here. The numeric user.id is the key every follow-up call requires. And stats.heartCount divided by stats.videoCount gives a quick lifetime likes-per-video figure - useful as a sanity check against the recent-window numbers computed next, because a large gap between the two usually means the account's best era is behind it.
/user-posts/ returns up to 35 videos per request inside a videos[] array, alongside cursor and hasMore for pagination. Each video carries snake_case counters: play_count, digg_count (likes), comment_count, share_count, and collect_count (saves). We include collects in the numerator because saves signal revisit intent, which is exactly what a brand buying a product placement wants.
$posts = array();
$cursor = 0;
while (count($posts) < 30) {
$page = tla_get("/user-posts/", array(
"userid" => $userid,
"count" => 30,
"cursor" => $cursor,
));
if ($page === null || empty($page["videos"])) {
break;
}
$posts = array_merge($posts, $page["videos"]);
if (empty($page["hasMore"])) {
break;
}
$cursor = $page["cursor"];
}
$posts = array_slice($posts, 0, 30);
$plays = 0;
$engagements = 0;
foreach ($posts as $v) {
$plays += $v["play_count"];
$engagements += $v["digg_count"] + $v["comment_count"]
+ $v["share_count"] + $v["collect_count"];
}
$er = $plays > 0 ? $engagements / $plays : 0;
$reach = ($followers > 0 && count($posts) > 0)
? ($plays / count($posts)) / $followers : 0;
Summing numerator and denominator across the window before dividing - rather than averaging per-post rates - keeps one viral or one suppressed video from distorting the result. Healthy accounts land roughly between 5% and 9% views-based engagement; treat anything under 3% as a flag, and anything over 15% on a large account as worth a manual look for engagement-pod behavior.
/user-followers/ returns up to 200 follower objects per call, each with enough public metadata to run humanity heuristics: aweme_count (videos posted), signature (bio), follower_count, and following_count. Pagination uses a time value returned by the previous page rather than a cursor.
$sample = array();
$time = 0;
while (count($sample) < 200) {
$page = tla_get("/user-followers/", array(
"userid" => $userid,
"count" => 200,
"time" => $time,
));
if ($page === null || empty($page["followers"])) {
break;
}
$sample = array_merge($sample, $page["followers"]);
if (empty($page["hasMore"])) {
break;
}
$time = $page["time"];
}
$real = 0;
foreach ($sample as $f) {
$signals = 0;
if ($f["aweme_count"] > 0) $signals++;
if ($f["signature"] !== "") $signals++;
if ($f["follower_count"] >= 5) $signals++;
if ($f["following_count"] < 2000) $signals++;
if ($signals >= 2) {
$real++;
}
}
$audience = count($sample) > 0 ? $real / count($sample) : 0;
Requiring two of four signals is deliberately forgiving: plenty of genuine lurkers never post or write a bio. Bot farms, by contrast, tend to fail three or four heuristics at once - zero posts, empty bio, near-zero followers, and thousands of accounts followed. If the sampled ratio falls below 0.5, escalate to the deeper checks described in our guide to detecting fake TikTok followers programmatically before signing anything.
Normalize each pillar to a 0-1 range, then weight them. The weights below favor content engagement, because it is the hardest signal to fake at scale and the closest proxy for campaign performance:
$erNorm = min($er / 0.08, 1.0); // 8% ER caps the pillar
$reachNorm = min($reach / 1.0, 1.0); // views/follower ratio
$score = (int) round(100 * (
0.45 * $erNorm
+ 0.35 * $audience
+ 0.20 * $reachNorm
));
echo $profile["user"]["uniqueId"] . " scores " . $score . "/100\n";
The caps matter. Without them, a single 10M-view outlier or a freak 25% engagement video would let one pillar swallow the score. Capping engagement at 8% and reach at 1.0 means a creator earns full marks for being excellent, not for being briefly viral.
Two caveats. Niches differ - comedy runs structurally higher engagement than B2B finance content, so compare scores within a vertical, not across verticals. And the score is a snapshot: a creator who landed a hit yesterday will read hot for a week. Rerun the calculation the day before any contract is signed.
One full vetting pass costs three requests - profile, one posts page, one followers page - and 1 credit equals 1 request. At the standard 200 requests per minute, a sequential screening run covers roughly 60 creators per minute, so a 1,000-creator longlist scores in under 20 minutes for 3,000 credits. Cache results for 24 hours keyed by userid; engagement data does not move fast enough to justify re-pulling inside a day, and the cache keeps shortlist re-sorting free.
You can inspect live payloads for all three endpoints in the playground before writing a line of code, and the pricing page has the credit packages - no subscription required. Decide with data, not with the size of the number under the profile photo.
Ready to put what you read into code? Try our endpoints live or grab the full reference.