How do I track a competitor’s follower growth on Instagram or TikTok?
Read the competitor’s public profile once a day with the Openhandle profile endpoint. Store metrics.followers and capturedAt each time. The growth chart is the difference between rows. The same call works for Instagram and TikTok, with the same response shape.
No API keeps follower history for an account you do not own. Instagram and TikTok publish only the current number. History starts the day you start reading.
Checked September 2026 · request and response run against the API · no affiliate links
curl "https://api.openhandle.dev/v1/tiktok/profiles/@pixel_orchard_tt_test?freshness=live" \
-H "Authorization: Bearer $OPENHANDLE_API_KEY"import { OpenHandle } from '@openhandle/sdk';
const openhandle = new OpenHandle({ apiKey: process.env.OPENHANDLE_API_KEY! });
// Run once a day. Store id, capturedAt, and followers.
const { data, capturedAt } = await openhandle.tiktok.profile('pixel_orchard_tt_test').get({ freshness: 'live' });
await db.insert({ platform: 'tiktok', id: data.id, capturedAt, followers: data.metrics.followers });{
"platform": "tiktok",
"resource": "profile",
"capturedAt": "2026-09-18T06:00:03Z",
"source": "live",
"data": {
"id": "920000000001",
"handle": "pixel_orchard_tt_test",
"displayName": "Pixel Orchard",
"metrics": { "followers": 75120, "following": 411, "posts": 4 }
}
}Trimmed to the fields this question needs. The Instagram profile endpoint returns the same shape with the same metric names. The example is a Test account, so you can run it on a free Test key.
The recipe
- 01Store the ID on the first read. Handles change. IDs do not. Look up by ID after the first call, and a rename never breaks the series.
- 02Read at the same time each day. Use
freshness=liveso every row is a fresh read. A cache hit could repeat yesterday’s number. - 03Keep `capturedAt`, not your cron time. The capture time is when the platform showed the number. That is the timestamp the chart should use.
- 04Store nulls as nulls. If a platform hides the count for a day, the row is
null. Skip it in the chart. Never fill it with the previous value.
What it costs
One profile read per account per day. A live read costs $0.0025. A 24-hour cache hit costs $0.0005, which is fine when several people in your team read the same account on the same day. Ten competitors read daily for a month is 300 live requests.
Beyond the follower count
- —Posting rate. Store
metrics.postsin the same row. The delta is how many posts they published. - —Engagement. Read the profile posts endpoint with
sinceset to your last run to get only new posts and their likes, comments, and views. - —X and Reddit. The same profile endpoint exists for X and Reddit, with
metrics.followersand Reddit karma respectively.
When this does not work
These answers are definitive. Store them as rows, do not retry them.
| Situation | Status | Code |
|---|---|---|
| The account went private | 403 | PROFILE_PRIVATE |
| The account is deleted, banned, or renamed without an ID lookup | 404 | PROFILE_NOT_FOUND |
{
"error": {
"code": "PROFILE_NOT_FOUND",
"message": "This profile was not found.",
"requestId": "req_01j8…",
"retryable": false
}
}A private or not-found day is data. Store the code with the date. A series that goes private and comes back tells you something too.
Read next
More Instagram questions
Send your agent ahead.
Paste the prompt into your agent and it sets everything up. Or come yourself, it takes five minutes.