From a TikTok Handle to a Full Dataset in One Script
Turn a TikTok username into a structured CSV of profile and post engagement with one Monid script over the Apify tiktok-profile-scraper.

Copy this line to your agent to turn a TikTok handle into a clean CSV of profile and post engagement.
set up https://monid.ai/SKILL.md and use apify/apidojo/tiktok-profile-scraper to turn a TikTok handle into a profile and posts dataset
A single username is enough to build a real dataset: point one endpoint at a handle, get back the profile plus recent posts with views, likes, comments, and shares, then flatten the fields you care about into CSV. This is the whole cookbook, one handle at a time, using Monid as the interface and Apify as the source. No per-post pagination, no browser automation, no vendor signup.
Monid is a pay-per-call data-API marketplace: one interface and one wallet to discover and run hundreds of external data endpoints without a separate account for each provider. You inspect a schema for free, then pay only for the run. Here is the script that takes you from @handle to profiles.csv.
TL;DR
- One endpoint,
apify/apidojo/tiktok-profile-scraper, returns a profile object (bio, followers, verification) plus a list of posts with engagement counts, hashtags, and media URLs. - Inspect the schema for free, run one handle with a small
maxItems, then loop a handful of handles. jqflattens the nested JSON into flat rows; a two-line append turns each run into CSV.- Cost is billed per result, so a test of a few handles at ten posts each lands in the single-digit-cents range. See monid.ai/tools for live pricing.
- TikHub is an alternate TikTok source if you want a second opinion on the same handle.
Set up Monid once
For agents
Grab an API key at app.monid.ai, then paste this to your agent and hand it the key:
set up https://monid.ai/SKILL.md
It learns the whole discover, inspect, run workflow itself. More details in the agent quickstart.
For humans
npm install -g @monid-ai/cli
monid keys add --label main --key <your-api-key>
More details in the CLI quickstart.
Step 1: inspect the endpoint (free)
Before spending anything, read the schema. Inspect shows the accepted input fields and the price per result, and it costs nothing.
monid inspect -p apify -e /apidojo/tiktok-profile-scraper
You will see that the input body accepts usernames (an array of handles) or startUrls, plus maxItems, and optional since and until date bounds. The output carries a profile block (bio, follower count, verification flag) and a posts array where each entry has views, likes, comments, shares, a hashtag list, and media URLs. That output shape is what the rest of the script depends on, so it is worth reading once. The full endpoint reference lives on the Apify tiktok-profile-scraper page.
Step 2: run one handle with a small limit
Start with a single handle and a tiny maxItems so the first run is cheap and fast. The -i flag takes the JSON body, and -w waits inline so the result comes straight back.
monid run -p apify -e /apidojo/tiktok-profile-scraper \
-i '{"usernames":["nasa"],"maxItems":10}' \
-w -o nasa.json
If a run takes long enough to go async, you get a run ID instead. Poll and save it with:
monid runs get -r <RunID> -o nasa.json
Now nasa.json holds the profile and the ten most recent posts. Keep maxItems small while you shape the pipeline. You can raise it later once the CSV columns are exactly what you want.

Step 3: read the fields that matter with jq
The raw JSON is nested. Pull the profile fields first so you know they are landing:
jq '{handle: .username, followers: .followerCount, verified: .verified, bio: .bio}' nasa.json
Then flatten each post into a flat record, one row per video:
jq '.posts[] | {
handle: input_filename,
views: .playCount,
likes: .diggCount,
comments: .commentCount,
shares: .shareCount,
hashtags: (.hashtags | join("|"))
}' nasa.json
Field names follow the schema you saw in Step 1, so if Apify labels a count differently, the inspect output is your source of truth. Confirm the keys there rather than guessing.
Step 4: loop a handful of handles
One handle proves the shape. A short list gives you a comparable dataset. Keep the list small and the limit low while testing.
for h in nasa duolingo gordonramsayofficial; do
monid run -p apify -e /apidojo/tiktok-profile-scraper \
-i "{\"usernames\":[\"$h\"],\"maxItems\":10}" \
-w -o "raw_$h.json"
done
Each handle writes its own raw_<handle>.json. Running them separately keeps failures isolated: if one handle is private or misspelled, the others still land clean. You could also pass all three inside a single usernames array in one call, but per-handle files make the CSV step simpler to reason about.
Step 5: write it all to CSV
Emit a header once, then append a flattened row for every post across every file.
echo "handle,views,likes,comments,shares,hashtags" > profiles.csv
for f in raw_*.json; do
handle=$(jq -r '.username' "$f")
jq -r --arg h "$handle" '.posts[] |
[$h, .playCount, .diggCount, .commentCount, .shareCount,
(.hashtags | join("|"))] | @csv' "$f" >> profiles.csv
done
@csv handles quoting and escaping, so commas inside hashtags or captions will not break your columns. Open profiles.csv in any spreadsheet and you have a per-post engagement table keyed by handle, ready to sort by views or pivot on hashtag.
Cost tally
Everything up to the run was free: discover and inspect cost nothing, so you can read the schema and shape the jq calls without touching your wallet. The runs in this walkthrough are billed per result, meaning a handful of handles at ten posts each is a single-digit-cents job. Scaling maxItems up or adding more handles scales the cost linearly with results returned, so a broader pull of thousands of posts still stays in the low single-digit-dollars range. Check current per-result pricing on monid.ai/tools before you widen the net.
FAQ
Can I get more than the recent posts for a handle?
Raise maxItems in the input body, and use the since and until date fields to bound the window. Start small to confirm your columns, then widen once the CSV looks right.
What if a handle is private or does not exist? That single run returns an empty or error result while the rest of your loop keeps going, which is exactly why Step 4 writes one file per handle instead of batching them.
How much does a test run cost?
Inspect is free, and runs are billed per result, so a few handles at a small maxItems costs cents. Live per-result pricing is on monid.ai/tools.
Is there another source for the same data? Yes. TikHub exposes TikTok profile and post endpoints through the same Monid interface, so you can run the same handle against a second provider and compare the fields without a new signup.