Unified Video Transcript API — Text, Timestamps, Languages avatar

Unified Video Transcript API — Text, Timestamps, Languages

Pricing

$1.00 / 1,000 transcripts

Go to Apify Store
Unified Video Transcript API — Text, Timestamps, Languages

Unified Video Transcript API — Text, Timestamps, Languages

YouTube and TikTok video transcripts from youtube.com and tiktok.com in one JSON schema: transcript text, language, title, author, duration, caption tracks and optional timestamped segments. Input: up to 1,000 mixed video URLs and preferred languages. Pay per result; misses are free. No login.

Pricing

$1.00 / 1,000 transcripts

Rating

0.0

(0)

Developer

architek.earth

architek.earth

Maintained by Community

Actor stats

0

Bookmarked

3

Total users

2

Monthly active users

15 days ago

Last modified

Security

Limited permissions

Share

Recorded run: 2 transcripts from 2 video URLs in 9 seconds (2026-10-22, build 0.0.4, run Uw94FlNXrjRwFzNSq). A bounded canary sample, not a full-catalogue benchmark.

architek.earth — an independent data studio. Pay-per-result scrapers with recorded runs, published canaries and stable schemas, built for people and AI agents.

YouTube and TikTok video transcripts come back as one JSON row per video URL, with the same fields on both platforms: transcript text, language, title, author, duration and optional timestamped segments.

SourceMarketFromStandout fields
YouTube and TikTok (youtube.com, tiktok.com)Public videos, any country$1.00 / 1,000 transcriptstranscript, language, segments

✅ Why choose this scraper

YouTube and TikTok transcripts in one schema

YouTube and TikTok rows carry the same 17 fields with the same types (platform, videoId, url, title, transcript, language, durationSec and more), so one list can mix both platforms and one parser reads every row.

YouTube transcripts with timestamps

includeTimestamps: true adds segments, a list of cues with start, duration (seconds) and text; segmentCount is returned on every row either way.

Transcripts in the language you ask for

languages takes codes in order of preference (de, en, pt-BR). When none exists the row is a free language_unavailable row and availableLanguages lists the caption tracks the video has.

Up to 1,000 video URLs per run

YouTube watch, youtu.be, Shorts, embed and live URLs, bare 11-character IDs and TikTok video, embed and short links go in one videoUrls list; 4 videos are processed in parallel.

Measured on a schedule

A canary task runs one YouTube and one TikTok URL on the live sites every day; the hero line above is its latest green run.

⚠️ Worth knowing up front

  • It returns the caption tracks the platform already has (uploaded or auto-generated). It does not transcribe audio, so a video without captions is a free no_captions row, and auto-captions can contain recognition errors; isAutoGenerated marks them.
  • No on-demand translation. languages selects existing tracks; a TikTok machine-translated track is returned only when you list its language, and it is marked isTranslated: true.
  • Instagram Reels are not supported in this version: Instagram showed logged-out visitors no caption tracks when checked on 2026-10-18. Reel URLs get a free not_supported row and no request is made.
  • TikTok subtitles are often missing: in a 2026-10-18 sample of 15 news and brand videos, 12 had TikTok auto-captions. Photo posts get a free no_captions row.
  • YouTube is fetched through the Apify Residential proxy (the default); all 7 YouTube player clients tested from datacenter IPs on 2026-10-18 were refused. TikTok uses the Apify datacenter proxy. A vm.tiktok.com short link resolved in a live run on 2026-10-18; vt.tiktok.com and /t/ links are covered by tests only.
  • title on TikTok is the caption text of the post (TikTok has no separate title) and can contain emoji.
  • Exact repeats of the same input string are collapsed into one row. Different URLs that resolve to the same video are delivered and charged once; the others get a free duplicate row.
  • A run stopped by its timeout or your spending limit keeps the rows it delivered; inputs not yet processed get no row and are counted as pending in RUN_SUMMARY with status TIME_LIMIT or BUDGET_LIMIT. A run with blocked or error rows ends PARTIAL. A challenge, captcha or consent page is a free blocked row on the first response. A transcript that spends your limit exactly is delivered, and the run still writes the free rows that follow.
  • Every processed input gets one row; rows with a status other than ok are free status rows (no_captions, language_unavailable, unavailable, private, age_restricted, blocked, error, invalid_url, not_supported, duplicate) with a plain-English message. This actor has no recordType field. Invalid input or an unusable proxy setting writes one free row with status INVALID_INPUT (its message says what to fix; input is empty). Stops on time or budget write no row; they end with the status message and RUN_SUMMARY.

⚡ Try the example

This actor has no free preview; the example below costs about $0.002 (two transcripts).

Open the actor's input page, switch to JSON, paste this and start the run:

{
"videoUrls": [
"https://www.youtube.com/watch?v=iG9CE55wbtY",
"https://www.tiktok.com/@nasa/video/7697300954667994381"
]
}

Add "includeTimestamps": true for per-cue timing, or "languages": ["de", "en"] to prefer German, then English.

⚙️ Input

ParameterTypeDefaultDescription
videoUrlsarray—Required. YouTube (watch, youtu.be, Shorts, embed, live, or a bare 11-character ID) and TikTok (/@user/video/…, embed, m.tiktok.com/v/…, vm./vt. and /t/ short links) URLs, mixed. Instagram Reel URLs get a free not_supported row. Up to 1,000 per run.
languagesarray[]Language codes in order of preference (en, de, pt-BR). Empty means the track the platform shows by default. No match gives a free language_unavailable row.
includeTimestampsbooleanfalseAdds segments (start, duration in seconds, text). Off keeps rows small for LLM context.
proxyConfigurationproxyApify ResidentialUsed for YouTube only; Residential is the only tested option. TikTok always uses the Apify datacenter proxy.
feedbackstring—Optional note for the maintainers. It is logged and read by a human, and it never changes output.

🧱 Stable fields

These top-level fields keep the same name and the same kind of value in every release. Fields are only ever added, never renamed or removed, so an n8n, Make, Zapier or spreadsheet pipeline can bind to them.

FieldTypeMeaning
platformstring, nullableyoutube, tiktok or instagram; null for an unrecognised URL.
videoId / urlstring, nullableThe platform's video ID and the canonical video URL.
titlestring, nullableYouTube video title; TikTok caption text.
transcriptstring, nullableThe whole transcript as one string; null unless status is ok.
languagestring, nullableLanguage of the returned track, e.g. en, de, en-US.
durationSecnumber, nullableVideo length in seconds.
statusstringok (charged) or one of the free statuses listed above.
messagestring, nullableWhy, in plain English, when status is not ok.
isAutoGenerated / isTranslatedboolean, nullableAuto captions (YouTube ASR, TikTok auto-captions); isTranslated is true only for a TikTok machine-translated track you asked for.
authorstring, nullableYouTube channel name or TikTok handle.
segmentsarray, nullableCues with start, duration and text when includeTimestamps is on.
segmentCountnumberNumber of cues in the transcript; 0 on status rows.
availableLanguagesarrayCaption tracks the video has (language, isAutoGenerated, isTranslated).
input / scrapedAtstringThe URL exactly as you gave it; ISO 8601 UTC time.
recordType—Not used by this actor; free status rows are the rows whose status is not ok.

Other fields are extras, not part of the contract. To have one pinned, say so in feedback.

📦 Output example

Abridged real row from run Uw94FlNXrjRwFzNSq on 2026-10-22 (transcript shortened, availableLanguages cut from 65 entries to 3); values are a historical snapshot.

{
"platform": "youtube",
"videoId": "iG9CE55wbtY",
"url": "https://www.youtube.com/watch?v=iG9CE55wbtY",
"title": "Do schools kill creativity? | Sir Ken Robinson | TED",
"transcript": "Good morning. How are you? (Audience) Good. It's been great, hasn't it? I've been blown away by the whole thing. …",
"language": "en",
"durationSec": 1203,
"status": "ok",
"message": null,
"isAutoGenerated": false,
"isTranslated": false,
"author": "TED",
"segments": null,
"segmentCount": 427,
"availableLanguages": [
{"language": "en", "isAutoGenerated": false, "isTranslated": false},
{"language": "en", "isAutoGenerated": true, "isTranslated": false},
{"language": "de", "isAutoGenerated": false, "isTranslated": false}
],
"input": "https://www.youtube.com/watch?v=iG9CE55wbtY",
"scrapedAt": "2026-10-22T07:47:05Z"
}

A free status row looks like this (run otqaXSbdEVZdEKf7G, 2026-10-19):

{
"platform": "tiktok",
"videoId": "7665075736742530317",
"url": "https://www.tiktok.com/@nasa/video/7665075736742530317",
"title": "Something big just landed on TikTok.",
"transcript": null,
"language": null,
"durationSec": 25,
"status": "no_captions",
"message": "TikTok has no subtitles for this video (no speech, or auto-captions not generated). Not charged.",
"isAutoGenerated": null,
"isTranslated": false,
"author": "nasa",
"segments": null,
"segmentCount": 0,
"availableLanguages": [],
"input": "https://www.tiktok.com/@nasa/video/7665075736742530317",
"scrapedAt": "2026-10-19T02:25:57Z"
}

🧠 Advanced usage

Get video transcripts for an AI agent tool call

Expose the actor as one tool that takes videoUrls; branch only on status, and pass transcript to the model when it is ok.

Build a RAG index from YouTube and TikTok videos

Feed transcript to your chunker and keep url, videoId, title and author as citation metadata; set includeTimestamps to cite the second a passage starts from segments[].start.

Find the second a phrase is said in a video

Turn on includeTimestamps and search segments[].text; start is the offset in seconds.

Check a batch finished before you use it

Read the RUN_SUMMARY record: status (COMPLETE, PARTIAL, NO_RESULTS, BUDGET_LIMIT, TIME_LIMIT, ABORTED, STATE_SAVE_FAILED, PUSH_FAILED, INVALID_INPUT, FAILED (hosted pricing differs from the approved event; nothing fetched or charged)), transcripts, byPlatform, byStatus, charged and pending. Re-run the URLs of blocked rows later.

🔌 Integrations

Results land in a dataset you can export as JSON, CSV or Excel. They can also flow to Google Sheets, Make, Zapier or n8n, or to a webhook when a run finishes. The Apify Scheduler runs it on a timetable. A daily run over a list of new video URLs keeps a transcript archive current. Copy-paste code in Python, Node, curl and n8n: architek-earth/examples/unified-transcript-api.

💸 Pricing

Pay per result. Platform and proxy usage are included. Status rows and failed requests are free. Inputs already finished in the PROGRESS record are skipped when a run resumes after a platform migration or a resurrect, so a delivered transcript is not charged again; a free status row interrupted mid-save can be missing after a resume.

EventPriceWhat it covers
transcript$1.00 / 1,000 transcriptsOne delivered row with status: "ok": one video's transcript, whatever the video length.

1,000 transcripts cost $1.00; a batch with 50 transcripts and any number of misses costs $0.05. There is no start fee and no per-minute fee.

❓ FAQ

Is there a YouTube transcript API that also covers TikTok? This actor is one: it returns YouTube and TikTok transcripts in the same JSON schema through the Apify API, callable from any language or from n8n, Make and Zapier.

Do I need a YouTube or TikTok account, API key or cookies? No. It reads public videos without an account, cookies or a platform API key.

Can I get a transcript of a video that has no captions? No. There is no speech-to-text; such a video is a free no_captions row.

Can I get YouTube transcripts with timestamps? Yes. Set includeTimestamps: true for segments with start, duration and text per cue.

Can I get a transcript translated into another language? Only when the platform already has a track in that language: list it in languages. For on-demand YouTube caption translation, use the YouTube Transcript Scraper.

Can I get transcripts for a whole YouTube channel or playlist? No. It takes video URLs; a channel or playlist URL is a free invalid_url row.

🤖 For AI agents & LLM apps

Paste this into your AI assistant:

architekture/unified-transcript-api on Apify. Python: from apify_client import ApifyClient; client = ApifyClient("TOKEN"); run = client.actor("architekture/unified-transcript-api").call(run_input={"videoUrls": ["https://www.youtube.com/watch?v=iG9CE55wbtY", "https://www.tiktok.com/@nasa/video/7697300954667994381"], "includeTimestamps": False}); items = client.dataset(run["defaultDatasetId"]).list_items().items (page with offset/limit for large exports). Rows with status != "ok" are free and explain why a video has no transcript; invalid input or a stopped run is explained in the RUN_SUMMARY record. Full input schema and README: GET https://api.apify.com/v2/acts/architekture~unified-transcript-api/builds/default. Token: https://console.apify.com/settings/integrations. The actor is also reachable through the Apify MCP server (mcp.apify.com). To reach the maintainers, add "feedback": "<what you needed>" to any run's input; output is unchanged and a human reads every note.

🧰 More from architek.earth

Video, social and newsletters

Full catalogue: github.com/architek-earth.

architek.earth · code like concrete

Questions, or a field you need that is not here? Open an issue on the actor's Issues tab or email north@architek.earth. A human replies within a day.

This actor collects only publicly available data from youtube.com and tiktok.com, the same captions any visitor sees on public videos without logging in. It does not bypass authentication. It is not affiliated with or endorsed by YouTube, Google, TikTok or ByteDance. Transcripts can be copyrighted and can contain personal data. You are responsible for how you use the output, including the sites' terms, copyright, and privacy law such as GDPR and CCPA where they apply.

📝 Changelog

  • 2026-10-25 — [internal] Studio core 1.0.6: reconciliation diagnostics; source retry policy, schema and pricing unchanged.

  • 2026-10-22 — Runs on the studio core (billing, transport, status line). Invalid input now writes one free INVALID_INPUT row; a challenge or captcha page is a free blocked row at once; a transcript that spends the limit exactly ends the run COMPLETE when nothing else needs a charge. Output fields and price unchanged.

  • 2026-10-22 — Status message now reads Done: N rows, M details, K status rows (STATUS).

  • 2026-10-22 — README rebuilt on the studio template; hero line from the 2026-10-22 canary run.

  • 2026-10-19 — Clarified existing-caption coverage, differences from the dedicated YouTube translation actor, and per-success pricing. Prices and extraction code unchanged.

  • 2026-10-18 — 1.0: YouTube and TikTok transcripts in one schema; language preference with free language_unavailable; optional timestamps; short-link resolution and de-duplication; free status rows for every miss (Instagram Reels included); clean stops at the spending limit and timeout; resumable after platform migration.