TikTok Transcript Scraper — TikTok Subtitles to Text, No Login
Pricing
from $1.00 / 1,000 videos
TikTok Transcript Scraper — TikTok Subtitles to Text, No Login
TikTok subtitles and transcripts for a creator's videos: type a handle and get every video as a row — views, likes, comments, shares, saves, caption, hashtags, duration and a playable MP4 link — with an opt-in transcript from TikTok's own captions or speech-to-text. No login.
Pricing
from $1.00 / 1,000 videos
Rating
0.0
(0)
Developer
Steadyfetch Team
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
Type a TikTok handle and get that creator's videos as rows: the caption, hashtags, when it was posted, how long it runs, plays, likes, comments, shares and saves, the sound it uses, the cover image and a playable MP4 link — and, on request, the spoken words of every video as a timestamped transcript. No login, no cookies, no proxy to configure. Your result limit is exact — set 30 and you get 30, and a video we could not deliver is never charged. A transcript is charged only when it was actually produced. From $1.00 per 1,000 videos on the cheapest paid tier, $3.00 per 1,000 on the Apify free plan, platform usage included, nothing charged for starting a run. Press Start with nothing set and the run returns three built-in sample rows so you can see the exact output shape first — nothing is read from TikTok and there is no result fee.
Using an AI agent? Pin this actor in Apify's MCP server with one link: https://mcp.apify.com?tools=steadyfetch/tiktok-profile-transcripts
- Actor id:
steadyfetch/tiktok-profile-transcripts - Input:
{ "profiles": ["natgeo"], "includeTranscripts": true, "resultsLimit": 30 }—"profiles"is the one field you have to set;"includeTranscripts"adds the spoken words. - Cap the bill: set
maxTotalChargeUsdon the run (a run option, not Actor input), e.g.0.50— the run stops when it reaches it, and the last row says what it did not deliver.
Unofficial. Not affiliated with, endorsed by, or sponsored by TikTok or ByteDance Ltd.
What one row looks like
A real delivered row, built by this actor's own parser from a harvested profile feed:
{"videoId": "7683891628230315295","url": "https://www.tiktok.com/@natgeo/video/7683891628230315295","authorHandle": "natgeo","authorName": "National Geographic","authorId": "6780344874811442181","caption": "Presented by @ROLEX. Welcome to Africa 🌍 Africa Earth's Wild Home takes you deep into the heart of our wildest continent…","hashtags": ["rolex", "perpetualplanet"],"createdAt": "2026-09-10T13:04:07.000Z","durationSeconds": 72.619,"playCount": 74592,"likeCount": 10803,"commentCount": 193,"shareCount": 291,"saveCount": 576,"isPinned": true,"mediaType": "video","musicTitle": "original sound - natgeo","originalSound": true,"hasCaptions": true,"captionLanguage": "en"}
The caption is trimmed for this page; a real row carries it in full. coverUrl and videoUrl ride the same row — they are signed links that stop working after a few days, so they are not reprinted here. With Include transcripts on, the row also carries transcript, transcriptSource, transcriptLanguage and timestamped transcriptSegments. Every column is listed in the table below.
What you get
One row per video, with everything the video exposes at one price — there is no second charge for "details".
| Column | What it holds |
|---|---|
videoId · url | the video's own id and its permalink |
caption · hashtags | the description, and the tags pulled out of it |
createdAt | when it was posted, ISO-8601 UTC |
durationSeconds · mediaType · isPinned | how long it runs, whether it is a video or a photo post, and whether the creator pinned it |
playCount · likeCount · commentCount · shareCount · saveCount | engagement |
authorHandle · authorName · authorId | who posted it |
musicTitle · originalSound | the sound, and whether it is the creator's own |
coverUrl · videoUrl | the cover image and the playable MP4 link |
transcript · transcriptSource · transcriptLanguage · transcriptSegments | the spoken words, where they came from, the language, and the timestamped segments |
transcriptStatus · transcriptReason · transcriptCharged | whether a transcript was produced, why not when it was not, and whether it billed |
source · charged · chargedEvents · status · statusReason | whether this row was billed and for which events, so your invoice reconciles from the dataset itself |
Media links are signed and time-limited by TikTok, so download what you need in the same session.
What to set
Two fields say what to collect, and either one works on its own:
profiles— TikTok handles, one per line.natgeo,@natgeo,https://www.tiktok.com/@natgeoandtiktok.com/@natgeo/all mean the same creator.startUrls— the same creators in the store's own field name, as plain strings or as{ "url": "https://www.tiktok.com/@natgeo" }objects. A creator sent through both fields is collected once and charged once.
The rest only shape a run that already has a creator:
includeTranscripts(defaultfalse) — adds the spoken words to every delivered video.sortBy(default"latest") —"latest"walks the creator's grid newest first;"popular"walks TikTok's own most-played ordering for that creator, which is a different set of videos. An order this actor does not recognise is refused on an uncharged row naming the two that work — never quietly swapped for one of them.resultsLimit(default30) — videos per creator.maxItems(default1000) — videos for the whole run.maxRunSeconds(default1800) — the run stops cleanly before this and reports what is left. Up to 2,000 videos per creator, 20,000 in a run, and a clock between 30 and 3,600 seconds — ask outside any of those and the run still starts, continues at the nearest end of the range, and one uncharged row names what you asked for and what bound it.includeSeen(defaultfalse) andresumeFromDatasetId— the repeat memory described below.
Every optional field accepts null, which means "use the default", so the all-fields-null shape that templates and agent frameworks send runs exactly as a bare call does. A field name this actor does not have, or a creator list left empty, comes back as one uncharged row naming the field you meant — never as sample rows pretending the typo worked.
Price
Three charged events, and each lands only on work that was actually delivered.
video — one per delivered video row, tiered by your Apify plan:
| Apify plan | Per video | Per 1,000 videos |
|---|---|---|
| Free plan | $0.003 | $3.00 |
| Bronze | $0.002 | $2.00 |
| Silver | $0.0015 | $1.50 |
| Gold and above | $0.001 | $1.00 per 1,000 videos |
transcript — one per video whose spoken words were actually produced: $0.015 on the Free plan, $0.010 Bronze, $0.0075 Silver and Gold. It is off by default; switch on Include transcripts to get it.
long-video-surcharge — $0.005 per started minute beyond the first three minutes of a transcribed video, on every plan. Three minutes of speech are included in the transcript price, so most TikToks never touch it: a 45-second video is one transcript and nothing else, and a 5-minute video is one transcript plus two surcharge minutes.
The arithmetic on a typical job: 30 videos with transcripts on, all of them under three minutes, on Gold = 30 × $0.001 + 30 × $0.0075 = $0.255. The same job on the Free plan = $0.54. Platform usage is included in all three prices — there is no separate compute bill on top, and no start fee. Set maxTotalChargeUsd on the run and it is a hard ceiling: a video and its transcript are reserved together, so the run stops cleanly under your maximum rather than half-billing a unit.
TikTok publishes its own captions for most videos, and those cost no speech-to-text at all — the words are taken straight from the caption track, and transcriptSource on the row says captions when that is where they came from and speech when the audio had to be transcribed. You pay the same either way. A video that cannot be transcribed at all — no speech in it, no audio track, an expired media link, or a photo post, which carries no video — is still delivered as a normal row with an explicit null transcript and a reason, and the transcript event is not charged for it.
Honest rows: what "not charged" actually means
Every run closes its own books. A creator that returned less than it was asked for leaves an uncharged row saying which thing happened, and none of them is billed:
profile_not_found— TikTok says the account does not exist or has been deactivated.profile_private— the account is private, so its videos are not public data.no_videos— the feed had no more videos to list for that account (from any region this actor can read), or the run stopped at this actor's own per-creator page limit. The row says which of the two it was: a limit of ours is named as ours and never dressed up as a verdict about the account, and where the limit went unfilled because the videos were ones you already have, the row names the switch that would have filled it (a token that cannot open key-value stores cannot see what you already have — the run says so and collects as usual).vendor_unavailable— the read did not go through. Temporary, says nothing about the creator, and a re-run is the fix.vendor_budget·vendor_out_of_credit— this actor reached its own monthly collection allowance, or the data feed behind it is out of allowance for now, and it stopped rather than collecting more. That is our ceiling, never yours, and nothing was charged for it.stopped_at_limit— one of your own limits, your maximum total charge, or the run clock stopped it first. The row names which.user_input— a value that is not a creator: a link to a single video, a share link, another site's address, or an order this actor does not recognise. The row names the mistake and, where another actor of ours takes that value, names that actor too.
On a delivered video, transcriptStatus carries the same honesty for the transcript leg: no_video, no_speech, no_audio_stream, expired, transcript_too_long, failed_download, asr_failed, asr_unavailable. Each is an explicit null transcript with a reason on the row, and none of them is charged.
The last row of every run is a receipt: delivered, asked for, transcripts produced, how many came from TikTok's own captions, what was skipped, what stopped the run, and the charged-event totals for all three events.
How often the data changes
An active creator posts daily to weekly, and a video's play, like and comment counts keep moving for roughly 72 hours after it goes up. The MP4 and caption links are signed and expire within days. Re-run for fresh counts and fresh links.
Re-running the same creators does not re-buy what you already have. Every run remembers the videos it delivered to your account, in a key-value store in your own Apify account, and a later run skips them: not delivered again, not charged, never re-transcribed, and the slot goes to the next new video instead, so you still get the number you asked for. That makes a daily or weekly schedule on the same creators cost only what is new. The memory is a key-value store in your own Apify account, so a run started with a scoped API token in restricted-access mode needs key-value store Read, Write and Create permission, or Actor runs set to Full access (Write is what lets the run remember what it delivered; without it every run pays again); without it the run says so on its status line and on an uncharged row of its own, and cannot skip what you already have. Switch Include videos you already have on to get them back anyway, marked repeat: true and still uncharged, and use Skip videos in this dataset to carry the same memory across accounts.
Reliability
The videos come from a licensed data feed rather than from scraping TikTok's own web pages, which is why there is nothing to log into and nothing to configure. When that feed cannot answer, the run says so on an uncharged row and finishes successfully — a failed read is never billed and never dressed up as an empty profile. Transcripts come from TikTok's own caption track where the video has one, and from a speech-recognition service over the video's audio where it does not; when neither can answer, the video is still delivered and only the transcript is left null.
If this actor is not the door you want
A link to a single TikTok video is refused here with an uncharged row, because this listing is the profile door: it takes a creator and returns that creator's videos. Paste single video links into our media transcriber instead — it takes a video link or a direct media file from any host and returns the transcript.
Limits and good manners
Only public accounts are returned; a private account comes back as an uncharged row saying so. Transcripts are capped at 30 minutes of speech per video, and a longer video is delivered with its transcript left null and a reason. Photo posts are delivered as rows like any other post, with no transcript and no transcript charge. This actor may stop working if TikTok changes how the data is served; if it does, failed items are never charged.
If it earned its keep, a rating helps other buyers find it, and saving the actor keeps it one click away.