# TikTok Engagement Rate & Audit (`sfoln/tiktok-account-audit`)

Audit any public TikTok account in one row: followers, likes and bio plus average and median views, engagement rate, posting frequency, top videos, hashtags, sounds and best posting hour from its latest videos. $13 per 1,000 accounts; bigger samples $0.007 per extra page.

- Family: Social media data
- Categories: Social media, Lead generation, Automation
- Availability: on request (private on Apify). Email contact@sfoln.com with subject "Access request: TikTok Engagement Rate & Audit (sfoln/tiktok-account-audit)" before calling; calls fail until it is public.
- JSON: https://www.sfoln.com/actors/tiktok-account-audit.json
- MCP: https://mcp.apify.com?tools=sfoln/tiktok-account-audit
- REST (sync): POST https://api.apify.com/v2/actors/sfoln~tiktok-account-audit/run-sync-get-dataset-items
- REST (async): POST https://api.apify.com/v2/actors/sfoln~tiktok-account-audit/runs

TikTok Engagement Rate & Audit gives a one-row audit of any public TikTok account: the profile (followers, following, total likes, videos, bio, link, verification, region) plus analytics computed over its latest videos: average and median views, average likes/comments/shares/saves, engagement rate by followers and by views, views per follower, posting frequency, average length, the three most played videos, top hashtags and sounds, paid-partnership share and the best posting hour (UTC). Built for influencer vetting, creator pricing, competitor benchmarking and agency reporting.

## Price per delivered record

| Event | Price | Per 1,000 | Charged for |
| --- | --- | --- | --- |
| TikTok account audit (`tiktok-account-audit`) | $0.013 | $13 / 1,000 | Charged once per account: profile plus views, engagement rates, posting frequency, top videos, hashtags, sounds and best posting hour over its latest videos (first page of the feed). |
| Extra videos page (`tiktok-audit-extra-page`) | $0.007 | $7 / 1,000 | Charged per additional page of videos read when the first page does not reach sampleSize (page size is set by TikTok). |
| TikTok profile snapshot (`tiktok-account-profile-only`) | $0.0065 | $6.5 / 1,000 | Charged instead of tiktok-account-audit when only the profile could be delivered (private account, no videos, or videos unavailable). |

Pay-per-event, USD, billed by Apify; no platform usage charge. Only records with status `ok` are charged. Cap a run with `maxTotalChargeUsd`. Apify free plan: up to 10 per run.

## Run

```bash
curl -X POST "https://api.apify.com/v2/actors/sfoln~tiktok-account-audit/run-sync-get-dataset-items" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"handles":["nasa"]}'
```

MCP client configuration:

```json
{
  "mcpServers": {
    "apify": {
      "type": "http",
      "url": "https://mcp.apify.com?tools=sfoln/tiktok-account-audit"
    }
  }
}
```

Example prompt: Audit the TikTok accounts @nasa and @natgeo: compare their engagement rate, average views, posting frequency and top videos.

## Input

List TikTok accounts. Each account produces one dataset record with its profile and statistics over its latest videos.

| Field | Type | Default | Meaning |
| --- | --- | --- | --- |
| `handles` (required) | array | — | Accounts: TikTok handles (with or without @) or profile URLs (https://www.tiktok.com/@nasa), one per line. Duplicates are removed. Accounts on the Apify free plan can process up to 10 accounts per run. |
| `sampleSize` | integer | `30` | Videos to analyze: Latest videos sampled per account (5–100). The first page of the feed is included in the audit price; each further page is charged as tiktok-audit-extra-page. |
| `includeVideos` | boolean | `false` | Include sampled videos: Add the sampled videos (id, url, description, plays, likes, comments, shares, date, hashtags, sound) to each record. |
| `maxItems` | integer | `500` | Max accounts: Safety cap on how many accounts are processed in this run. |
| `concurrency` | integer | `3` | Concurrency: Accounts processed in parallel (1–5). |
| `itemTimeoutSecs` | integer | `300` | Per-account timeout (seconds): Time limit per account; video paging stops early when it is near. |
| `includeRaw` | boolean | `false` | Include raw upstream response: Attach the unmodified profile and video payloads under `raw` (larger output). |

Example input:

```json
{
  "handles": [
    "nasa"
  ]
}
```

## Output

One record per input item with `status` (`ok` is charged; `not_found`, `error`, `skipped_*` are free) and `charged`. The run stores an `OUTPUT` summary record.

| Field | Type | Meaning |
| --- | --- | --- |
| `input` | string | object | Input: The input item this record corresponds to. |
| `status` | string | Status: ok (auditType full or profile-only, charged) \| not_found (unknown account, not charged) \| error \| skipped_invalid \| skipped_budget \| skipped_free_plan |
| `charged` | boolean | Charged: Whether this record incurred a pay-per-event charge. |
| `chargedEvent` | string | Charged event: Pay-per-event event charged for this record. |
| `source` | string | Source: Upstream data source (scrapecreators = ScrapeCreators, public TikTok data). |
| `fetchedAt` | string | Fetched at: ISO timestamp. |
| `error` | object | Error: code / message when status is not ok (or a partial failure). |
| `warnings` | array | Warnings: Non-fatal notes (partial data, stopped early, free-plan caps). |
| `found` | boolean | null | Found: Account exists. |
| `auditType` | string | null | Audit type: full (profile + video stats) or profile-only (private / no videos / videos unavailable). |
| `handle` | string | null | Handle: TikTok username. |
| `userId` | string | null | User id: Numeric TikTok id. |
| `secUid` | string | null | secUid: TikTok secure user id. |
| `profileUrl` | string | null | Profile URL: https://www.tiktok.com/@<handle>. |
| `nickname` | string | null | Nickname: Display name. |
| `bio` | string | null | Bio: Profile bio. |
| `bioLink` | string | null | Bio link: Link in bio. |
| `followers` | integer | null | Followers: Follower count. |
| `following` | integer | null | Following: Accounts followed. |
| `likes` | integer | null | Total likes: Lifetime likes received. |
| `videoCount` | integer | null | Videos: Total videos. |
| `friendCount` | integer | null | Friends: Mutual follows. |
| `isVerified` | boolean | null | Verified: Verified badge. |
| `isPrivate` | boolean | null | Private: Private account. |
| `isOrganization` | boolean | null | Organization: Organization account. |
| `isCommerceUser` | boolean | null | Commerce: Commerce / seller account. |
| `avatarUrl` | string | null | Avatar: Avatar image URL. |
| `region` | string | null | Region: Account region. |
| `language` | string | null | Language: Account language. |
| `createdAt` | string | null | Created: Account creation date (ISO), when reported. |
| `sampleSizeRequested` | integer | null | Sample size requested: sampleSize input. |
| `videosAnalyzed` | integer | null | Videos analyzed: Latest videos in the sample (pinned excluded). |
| `pinnedExcluded` | integer | null | Pinned excluded: Pinned videos left out of the stats. |
| `avgViews` | integer | null | Avg views: Mean plays per sampled video. |
| `medianViews` | number | null | Median views: Median plays per sampled video. |
| `avgLikes` | number | null | Avg likes: Mean likes per sampled video. |
| `avgComments` | number | null | Avg comments: Mean comments per sampled video. |
| `avgShares` | number | null | Avg shares: Mean shares per sampled video. |
| `avgSaves` | number | null | Avg saves: Mean saves (collects) per sampled video. |
| `engagementRatePct` | number | null | Engagement rate %: (avgLikes + avgComments + avgShares) ÷ followers × 100. |
| `engagementRateByViewsPct` | number | null | Engagement / views %: Σ(likes + comments + shares) ÷ Σ plays × 100. |
| `viewsPerFollowerPct` | number | null | Views / follower %: avgViews ÷ followers × 100. |
| `postingFrequencyPerWeek` | number | null | Posts per week: Sampled videos ÷ weeks from the oldest sampled video to fetch time. |
| `sampleWindowDays` | number | null | Sample window (days): Days from the oldest sampled video to fetch time. |
| `avgDurationSecs` | integer | null | Avg duration (s): Mean video length. |
| `topVideos` | array | Top videos: Up to 3 most played sampled videos { videoId, url, description, views, likes, createdAt }. |
| `topHashtags` | array | Top hashtags: Up to 10 { tag, count }: sampled videos using the hashtag. |
| `topSounds` | array | Top sounds: Up to 5 { sound, count } ('title — author'). |
| `paidPartnershipSharePct` | number | null | Paid partnership %: Share of sampled videos flagged as paid partnership (when reported). |
| `postingHoursUtc` | array | Posting hours (UTC): { hourUtc, posts, avgEngagement } for each hour with posts. |
| `bestPostingHourUtc` | integer | null | Best hour (UTC): Hour with the highest mean likes + comments + shares (hours with ≥ 2 videos preferred). |
| `mostActivePostingHourUtc` | integer | null | Most active hour (UTC): Hour with the most sampled videos. |
| `newestVideoAt` | string | null | Newest video: ISO. |
| `oldestVideoAt` | string | null | Oldest sampled video: ISO. |
| `pagesFetched` | integer | null | Pages fetched: Video feed pages fetched. |
| `extraPagesCharged` | integer | null | Extra pages charged: Pages charged as tiktok-audit-extra-page. |
| `sampleStopReason` | string | null | Sample stop reason: limit \| end \| budget \| deadline \| aborted \| empty_pages \| max_pages \| error. |
| `videos` | array | Sampled videos: Only with includeVideos: normalized videos (plays, likes, comments, shares, saves, hashtags, sound…). |

Example record:

```json
{
  "input": "nasa",
  "found": true,
  "auditType": "full",
  "handle": "nasa",
  "userId": "6750",
  "profileUrl": "https://www.tiktok.com/@nasa",
  "nickname": "NASA",
  "bio": "Exploring the universe",
  "followers": 2300000,
  "following": 5,
  "likes": 41000000,
  "videoCount": 640,
  "isVerified": true,
  "isPrivate": false,
  "region": "US",
  "sampleSizeRequested": 30,
  "videosAnalyzed": 30,
  "pinnedExcluded": 0,
  "avgViews": 182000,
  "medianViews": 96000,
  "avgLikes": 14100.5,
  "avgComments": 210.3,
  "avgShares": 380.1,
  "avgSaves": 920.4,
  "engagementRatePct": 0.639,
  "engagementRateByViewsPct": 7.95,
  "viewsPerFollowerPct": 7.91,
  "postingFrequencyPerWeek": 3.5,
  "sampleWindowDays": 60,
  "avgDurationSecs": 41,
  "topVideos": [
    {
      "videoId": "74…",
      "url": "https://www.tiktok.com/@nasa/video/74…",
      "description": "Artemis II rollout…",
      "views": 1900000,
      "likes": 160000,
      "createdAt": "2026-09-30T16:00:00.000Z"
    }
  ],
  "topHashtags": [
    {
      "tag": "space",
      "count": 18
    },
    {
      "tag": "nasa",
      "count": 15
    }
  ],
  "topSounds": [
    {
      "sound": "original sound — nasa",
      "count": 22
    }
  ],
  "paidPartnershipSharePct": 0,
  "postingHoursUtc": [
    {
      "hourUtc": 16,
      "posts": 9,
      "avgEngagement": 21000
    }
  ],
  "bestPostingHourUtc": 16,
  "mostActivePostingHourUtc": 16,
  "newestVideoAt": "2026-10-13T16:00:00.000Z",
  "oldestVideoAt": "2026-08-15T18:00:00.000Z",
  "pagesFetched": 1,
  "extraPagesCharged": 0,
  "sampleStopReason": "limit",
  "status": "ok",
  "charged": true,
  "chargedEvent": "tiktok-account-audit",
  "source": "scrapecreators",
  "fetchedAt": "2026-10-14T10:00:00.000Z"
}
```

## Related

- [Instagram Engagement Rate & Audit](https://www.sfoln.com/actors/instagram-account-audit.md) (`sfoln/instagram-account-audit`)
- [YouTube Channel Analytics & Audit](https://www.sfoln.com/actors/youtube-channel-audit.md) (`sfoln/youtube-channel-audit`)
- [Twitter (X) Account Audit – Engagement](https://www.sfoln.com/actors/x-account-overview.md) (`sfoln/x-account-overview`)
- [TikTok User Videos Scraper](https://www.sfoln.com/actors/tiktok-user-videos.md) (`sfoln/tiktok-user-videos`)

Publisher: SFOLN LLC, contact@sfoln.com. Catalogue: https://www.sfoln.com/catalog.json. Agent guide: https://www.sfoln.com/agents.md.
