YouTube Transcript Scraper: Channel, Playlist & Keyword Search avatar

YouTube Transcript Scraper: Channel, Playlist & Keyword Search

Pricing

from $1.00 / 1,000 transcript hours

Go to Apify Store
YouTube Transcript Scraper: Channel, Playlist & Keyword Search

YouTube Transcript Scraper: Channel, Playlist & Keyword Search

YouTube transcript scraper: search a channel's transcripts, get timestamped quotes with links. Watch channels for new uploads with Slack alerts. RAG chunks, SRT, VTT. Videos, Shorts, playlists. From $1 per 1,000 transcript hours (a video under an hour counts once); failed videos free. No login.

Pricing

from $1.00 / 1,000 transcript hours

Rating

0.0

(0)

Developer

Fulox

Fulox

Maintained by Community

Actor stats

1

Bookmarked

1

Total users

1

Monthly active users

10 days ago

Last modified

Share

Get the transcript of any YouTube video, Short, channel or playlist as clean text, timed segments, SRT, VTT, Markdown or RAG chunks. Then search every transcript for your keywords and get each hit as a quote with a link that opens the video at that second. Schedule it and only new uploads are delivered, with a digest in Slack.

From $1.00 per 1,000 transcript hours (a video under an hour counts once). Videos without captions, listings and keyword matches are free. No login, no API key. Built for RAG and AI-agent pipelines, content and SEO teams, brand and PR monitoring, and research.

Search a whole YouTube channel for your keywords and get timestamped quotes, new-upload alerts and RAG-ready chunks

▶️ Watch the demo: paste a channel, search its transcripts, open each quote at the second it was said, then get only new uploads.

⚡ Try it in 30 seconds

Click Start with the default input. It reads two public videos (a 15-minute talk and a 19-second clip) and returns two transcripts for $0.003 on the Free or Starter plan. Then paste your own links: videos, Shorts, @channel names or playlists.

✨ Key features

  • 🔎 Search a whole channel like Ctrl+F. Put words in searchTerms and every hit comes back as a quote with the second it was said, a clickable youtu.be/<id>?t=<seconds> link and the chapter. A phrase that spans two caption lines still matches. Matches are free.

    Keyword quotes from a channel's transcripts, each with the second it was said and a link that opens the video there

  • 🔔 Watch mode. Turn on watch and schedule the Actor. Each run delivers only the uploads it has not delivered before, plus a free digest row and an optional Slack or webhook message with the new videos and the top quotes.

  • 🧠 AI-ready output. RAG chunks with a stable id (<videoId>#3), start and end seconds, a token estimate, the chapter and a deep link. Or one markdown document with YAML front matter and a [m:ss](link) anchor per paragraph. Clean text without [Music] and >>.

  • 📑 Chapters. Read from the timestamps in the video description, and attached to every chunk and match.

  • 🅰️ Quality grade. A to D from the caption kind (written by a person or auto-generated), how much of the video the captions cover, words per minute and the share of music cues, so you can filter weak transcripts before you embed them.

  • 🔍 YouTube searches as input. Give searchQueries (what you would type into YouTube) and every query becomes a source: its first results are fetched like a channel's uploads. Listing is free.

  • 📅 Publish date for every video (publishedAt, YYYY-MM-DD), also for links you paste directly.

  • 📺 Videos, Shorts, live recordings, channels and playlists in one list, mixed. channelContent picks videos, Shorts or live streams of a channel. publishedAfter keeps recent ones.

  • 🌍 Languages in order of preference, with a fallback to the best available track (the row says if your language was missing). Each row lists the languages the video has (availableLanguages).

  • 👀 Free preview. listOnly returns one free row per video with its length, its caption languages and what it would cost, without downloading any transcript.

  • 💶 Fair pricing. One result per started hour of video: a 10-minute video and a 59-minute one cost the same, a 3-hour podcast costs three. Failures, listings, matches, digests and alerts are free.

  • 🔑 No login, no API key, no personal data beyond the public channel name.

👥 Who it is for

  • 🤖 AI and RAG builders. Use case: load 300 videos of a conference channel into a vector store. Set formats: ["chunks"]; each chunk has a stable id, a token estimate and a deep link, so an answer can cite the exact second. Filter on quality.grade before embedding.
  • ✍️ Content repurposing. Use case: turn a podcast back catalogue into articles and show notes. Set formats: ["markdown"] for a document with front matter, chapter headings and timestamp links per paragraph.
  • 📈 SEO and competitor research. Use case: find every video where a competitor's channel mentions "pricing" or your product name. Set searchTerms and formats: [] and read the quotes and links.
  • 📣 Brand and PR monitoring. Use case: "tell me every time one of these 20 channels says our name". watch plus searchTerms on a daily Schedule, with the top quotes sent to Slack.
  • 🔬 Researchers and journalists. Use case: export a playlist of hearings or lectures as text and find who said what, with a link to the moment.
  • 🧩 AI agents and MCP. Use case: an agent answers "what did this channel say about X" with one call and cites matches[].url. See the agent notes below.

🚀 How to use it

  1. Paste YouTube links into Videos, channels or playlists: https://www.youtube.com/watch?v=..., https://youtu.be/..., a Shorts link, @mkbhd, a channel link or a playlist link. Or type a search into YouTube searches.
  2. Choose the output formats and, if you want quotes, add search terms.
  3. Click Start. Download the dataset as JSON, CSV or Excel, or send it to Google Sheets, Make, Zapier, n8n or Clay.
  4. For a recurring feed, turn on Watch mode, open Schedules and run the Actor daily or weekly with the same input. Each run delivers only new uploads.

Not sure what a channel will cost? Turn on listOnly first: it lists up to 200 videos with their lengths and caption languages, free.

📥 Input

Input form with video, channel and playlist links, search terms, output formats and watch mode

Example input:

{
"videoUrls": ["@mkbhd", "https://www.youtube.com/watch?v=UF8uR6Z6KLc"],
"searchQueries": ["steve jobs stanford commencement"],
"searchTerms": ["battery life", "connecting the dots"],
"languages": ["en"],
"formats": ["text", "chunks"],
"maxVideosPerSource": 20,
"publishedAfter": "30 days"
}
FieldWhat it doesDefault
videoUrlsVideos, Shorts, /live/ links, channels (@handle, /channel/UC..., /c/name, /user/name) and playlists (list=PL...). Up to 500 entries, 5,000 videos per run (300 on the Apify free plan). Duplicates and invalid entries are reported in free rows. Can be empty when you use searchQueries.two public videos
searchQueriesTexts to search on YouTube (videos only, in YouTube's relevance order). Each query gives up to maxVideosPerSource videos (about 600 at most). Up to 20 queries of 200 characters. Listing is free.none
searchTermsWords or phrases to find in every transcript, ignoring case. Each hit becomes a quote with a timestamp link. Up to 50.none
matchRowsBesides the video row, add one free match row per keyword hit (term, second, link, quote, chapter), up to 50 per video.off
languagesCaption languages in order of preference (en, de, pt-BR). en also matches en-US and en-GB.["en"]
preferAutoGeneratedRead the auto-generated track before the one written by a person.off
fallbackToAnyLanguageIf none of your languages exists, deliver the best available track (requestedLanguageFound: false). Off: a free language_not_found row that lists what exists.on
formatstext, segments, srt, vtt, markdown, chunks. Empty gives metadata, chapters, quality and matches only, at the same price.["text", "segments"]
chunkTokensTarget chunk size, 100 to 2000 tokens. Chunks end at a sentence end or a pause of 2 seconds or more.400
channelContentFor channels: videos, shorts, live.["videos"]
maxVideosPerSourceNewest first, per playlist and per selected channel tab.100
publishedAfterA date (2026-09-01) or an age (7 days, 3 weeks, 2 months) for channels and playlists. Uses the listing's relative date ("3 days ago"). Shorts list no date, so their exact date is checked when they are fetched: an older Short comes back as a free too_old row. A video whose date cannot be found at all is kept.none
includeDescriptionAdds the video description (up to 5,000 characters).off
listOnlyFree preview: one preview row per video with hasCaptions, languages, length and estimatedResults, no transcript, never charged. Checks at most 200 videos per run; watch mode is ignored.off
watchDeliver only videos not delivered by an earlier run with the same watchlistName.off
watchlistNameSeparate memory per name (letters, digits, -, _).default
slackWebhookUrl / webhookUrlA hooks.slack.com URL, or an https URL, that receives the digest when at least one transcript was delivered. Stored as secrets, never logged.none
resetStateForget what watch mode delivered for the sources in this run.off

📤 Output

AI-ready output: RAG chunks with stable ids, token estimates, deep links and a quality grade

One dataset with five kinds of rows. Filter the type column: video, match, input, digest, run (and preview with listOnly). Fields a format did not ask for are null.

A delivered video (type: "video", status: "ok"), shortened:

{
"type": "video", "status": "ok",
"videoId": "UF8uR6Z6KLc", "url": "https://www.youtube.com/watch?v=UF8uR6Z6KLc",
"title": "Steve Jobs' 2005 Stanford Commencement Address", "channel": "Stanford", "lengthSeconds": 904, "durationText": "15:04",
"viewCount": 49252055, "publishedAt": "2008-03-07", "language": "en", "languageName": "English", "captionKind": "manual", "requestedLanguageFound": true,
"text": "This program is brought to you by Stanford University. Please visit us at stanford.edu\n\nThank You. I am honored to be with you today...",
"segments": [{ "start": 7.47, "dur": 2.899, "text": "This program is brought to you by Stanford University." }],
"chunks": [{ "id": "UF8uR6Z6KLc#1", "start": 7.47, "end": 118.469, "text": "This program is brought to you by...", "tokensApprox": 326, "chapter": null, "url": "https://youtu.be/UF8uR6Z6KLc?t=7" }],
"chapters": [], "words": 2298, "tokensApprox": 3039,
"quality": { "grade": "A", "captionKind": "manual", "coverage": 0.82, "wordsPerMinute": 185, "musicShare": 0, "reasons": ["manual captions", "speech covers 82% of the video"] },
"matches": [{ "term": "connecting the dots", "start": 55.85, "timestamp": "0:55", "url": "https://youtu.be/UF8uR6Z6KLc?t=55", "quote": "...The first story is about connecting the dots. I dropped out of Reed College...", "chapter": null }],
"matchCount": 1, "resultsCharged": 1
}

Other fields: channelId, channelUrl, tags, thumbnailUrl, availableLanguages, translationLanguages (information only: the languages YouTube lists as translatable; this Actor does not translate), srt, vtt, markdown, description (when asked), source (the channel or playlist the video came from) and publishedText (the listing's "3 days ago", for videos that came from a channel, playlist or search). publishedAt is the exact date for every delivered video; it comes from a second, tiny request, and is null if YouTube does not answer it.

  • A video that failed has status no_captions, language_not_found, unavailable, age_restricted, live_in_progress, blocked, pot_required, fetch_failed or too_large, a reason, and resultsCharged: 0. Never charged.
  • match rows (free, only with matchRows): one per keyword hit, right after the video row.
  • preview rows (free, only with listOnly): status: "preview", hasCaptions, availableLanguages, lengthSeconds, estimatedResults.
  • input rows (free): invalid or duplicate entries, and for each channel or playlist a source_resolved row (listed, afterFilters, alreadySeen), or source_not_found, source_empty, source_truncated.
  • digest row (free, last): the sources with counts, videosDelivered, hoursOfVideo, resultsCharged, matchesTotal, the 10 topMatches, up to 20 newVideos and the alert status.
  • run row (free): says why nothing was delivered or why the run stopped early.

A run summary (OUTPUT) lists the counts and, for your own checks, the proxy bytes per video.

💸 Pricing

Pay per result, cheaper on higher Apify plans. A result is one transcript of up to 60 minutes of video (the Store calls it a "transcript hour"); a longer video counts one result per started hour (a 25-minute video is 1, a 2.5-hour podcast is 3).

Your Apify planPer 1,000 resultsPer result
Free and Starter$1.50$0.0015
Scale$1.25$0.00125
Business$1.00$0.0010
Enterprise$1.00$0.0010

Apify's standard Store tiers apply: Free and Starter are the Free and Bronze tiers, Scale is Silver, Business is Gold, Enterprise is Platinum and Diamond.

Free: videos without captions, unavailable, age-restricted, live or refused videos, channel, playlist and search listings, listOnly previews, keyword matches and match rows, digests, alerts, and input and run rows.

ResultsFree / StarterScaleBusiness
🆕 The default input (2 short videos)2$0.003$0.0025$0.002
📅 100 ten-minute videos100$0.15$0.125$0.10
🎙️ One 3-hour podcast3$0.0045$0.00375$0.003
📚 A 1,000-video channel, 10% without captionsabout 900$1.35$1.125$0.90
🔔 Weekly watch of 20 channels, 60 new uploads60$0.09$0.075$0.06

Set a maximum cost per run to stay in control. A run on the Apify free plan processes up to 300 videos; paid plans up to 5,000.

🔌 Alerts and integrations

Watch mode digest in Slack: new uploads from the watched channels and the top quotes

  • 💬 Schedule plus Slack: watch: true, a slackWebhookUrl, and a daily Schedule. Slack gets one message per run with the new videos and the top quotes, and nothing when there is nothing new. Free.
  • 🔗 Webhook: webhookUrl receives the same digest as JSON, no polling.
  • 📑 Google Sheets: Integrations > Google Sheets appends the dataset after every run. Filter the type column to video.
  • 🔁 Make, n8n, Zapier: run the Actor, then send video rows to your tool.
  • 📓 NotebookLM, Claude Projects, Cursor: set formats: ["markdown"] and upload the markdown field of each row as a document.
  • 🧱 Clay: an HTTP API column that calls this Actor's run-sync-get-dataset-items endpoint with your Apify token and the body {"videoUrls":["{{url}}"],"formats":["text"]}.
  • 🛠️ API: call it from any language and read the dataset.

🤖 For AI agents

Call with {"videoUrls": ["https://www.youtube.com/watch?v=<id>"], "formats": ["text"]} and read the dataset. Row type is video (status: "ok" has the transcript, any other status is a free failure with a reason), match, preview, input, digest or run. To work from a topic instead of links, pass "searchQueries": ["your topic"]. To check what exists before paying, add "listOnly": true; the estimatedResults of each preview row is what a real run would charge for it. Add "matchRows": true to get one flat row per quote. To find what someone said, add "searchTerms": ["phrase"] and "formats": [], then read matches[].quote and matches[].url (the link opens the video at that second). quality.grade A to D says how far to trust the text.

🆚 How it compares (October 2026)

Facts from each Actor's Apify Store page and README, read on 2026-10-14. Prices per 1,000 results are not like-for-like, and competitors may change.

This Actorstarvibe/youtube-video-transcriptjohnvc/YoutubeTranscriptspintostudio/youtube-transcript-scraper
Inputvideos, Shorts, channels, playlists, searches, mixed, up to 500 entriesone video or one channel (max 200) per runup to 100 URLs, channels (max 1,000)one video
Playlistsyesnot documentednot documentedno
Keyword search with timestamp linksyesnonono
New-uploads-only mode, digest, Slackyesnonono
RAG chunks, Markdown, chapters, quality gradeyesnonono
SRT / VTT / text / segmentsyessegments, textyessegments
Translationnonoyesno
Failed videosfreecharged as itemsfreecharged
Price per 1,000$1.50 Free/Starter, $1.25 Scale, $1.00 Business, per transcript hour$5$2.75 down to $2.00 (+$3 for extended metadata)$10

Where others do better: johnvc offers translation, a cache of popular videos and extended metadata. starvibe returns richer video metadata such as likes, and has more ratings. This Actor has no translation, no audio transcription and a shorter track record.

⚠️ Limitations

  • Captions only. It reads the captions YouTube already has (written by the creator, or auto-generated). It does not transcribe audio, so a video without captions is a free no_captions row. Captions that hold only music or sound cues are treated the same way.
  • No translation. You get the transcript in a language the video already has. availableLanguages shows which. translationLanguages only lists what YouTube says it could translate to; this Actor does not request translations.
  • YouTube can change. Caption availability and the way YouTube serves it change from time to time. If YouTube refuses 8 requests in a row the run stops, writes a free run row, and charges nothing for the refused videos. Try again in a few minutes.
  • Dates: publishedAt is the exact date of every delivered video (one small extra request). Videos from a channel, playlist or search also carry the listing's relative date in publishedText ("3 days ago"), and publishedAfter uses that one, rounded in your favour.
  • YouTube search returns what YouTube returns: relevance order, at most about 600 results per query, and results can differ between runs and regions. Watch mode on a query delivers videos it has not delivered before, but a new video that ranks low may not be listed.
  • Live streams are delivered after the stream has ended. A stream in progress is a free live_in_progress row.
  • Watch mode remembers up to 5,000 video IDs per source. A video that failed for a temporary reason (blocked, pot_required, fetch_failed, live_in_progress, or a very fresh upload without captions yet) is tried again next run. The memory is saved with the run's progress (every 25 videos and whenever Apify moves or stops the run), so a hard kill delivers again at most the videos since the last save, up to about 25 plus the one in flight. A run that Apify restarts continues with the video list it saved at the start and never charges a video twice.
  • Very long captions: captions over 2 MB are a free too_large row. A row over 8 MB drops segments, vtt, srt and chunks (in that order) and lists them in truncated, at the same price.
  • Search is a case-insensitive text match, not meaning-based. Hyphens, spaces and punctuation between words count as the same, so "product-market fit" also finds "product market fit". At most 50 matches are listed per video; matchCount is the full count.
  • Slack and webhook URLs must be https with a public host (Slack only hooks.slack.com). The host is also resolved, and an address that is private, loopback, link-local, shared (CGNAT) or reserved is refused before anything is sent.
  • listOnly checks at most 200 videos per run.

❓ FAQ

Is this legal? The Actor reads captions of public videos, the same text YouTube shows to anyone who turns subtitles on. It collects no comments and no personal data beyond the public channel name. You are responsible for how you use the text and for the laws that apply to you, including YouTube's terms and the creators' rights. It does not download any video or audio.

What if YouTube changes something? Caption delivery on YouTube changes from time to time, and scrapers break when it does. If that happens, the run stops early, charges nothing for refused videos and says so in a free run row. Report it on the Issues tab and I fix it; I reply within 12 hours.

What does "failed videos are free" cover? Everything that is not a delivered transcript: no captions, wrong language (with fallback off), private, deleted, age-restricted, live, refused by YouTube, a network failure, captions that are too large.

How does watch mode work? At the end of each run the Actor saves the IDs it handled, per channel or playlist, in a key-value store named youtube-transcript-scraper-state in your account. The next run lists the source again and fetches only new IDs. A different watchlistName has its own memory. resetState clears it.

Why is a video I pasted charged more than one result? It is longer than an hour. Each started hour is one result: 1:00:01 is two.

How much will it cost me? $1.50 per 1,000 results (transcript hours) on Free and Starter, $1.25 on Scale, $1.00 on Business and Enterprise (see Pricing for worked examples). Use listOnly to see estimatedResults before a big run, and set a maximum cost per run.

Can I get the transcript in another language than the video has? No, translation is not offered. See availableLanguages on each row for the languages the video has, and put your preferred ones in languages.

How fast is it? About 6 videos are fetched in parallel. A hundred videos take a minute or two. A run can hold up to 5,000 videos.

Something is wrong or missing. Who do I ask? Open an issue on the Actor's Issues tab. I reply within 12 hours.

🛠️ Need a custom feature?

A different output, a corpus file for a whole channel, a signal you need? Open an issue on the Actor page and describe it.

Changelog

  • 1.1.1 (2026-10-21): publishedAfter now also filters Shorts (older ones are a free too_old row, never charged); publishedText is kept on every listed video.
  • 1.1 (2026-10-14): searchQueries (YouTube search as input), publishedAt for every video, listOnly free preview, matchRows, other YouTube clients tried before pot_required, a restarted run keeps its saved video list and never charges twice, watch memory saved with every progress save, alert hosts resolved and private addresses refused.
  • 1.0 (2026-10-14): first version. Videos, Shorts, channels and playlists; text, segments, SRT, VTT, Markdown and RAG chunks; chapters; quality grade; keyword search with timestamp links; watch mode with digest, Slack and webhook; one result per started hour, failures free.