From youtube-transcriber
Transcribe YouTube videos and playlists by extracting auto-generated captions directly from the browser — no API key, no external service, completely free. Trigger on: "transcribe this video", "transcribe this playlist", "get the transcript", "extract captions", "what does this video say", "תמלל את הסרטון", "תמלל פלייליסט", or any request involving extracting text/captions/subtitles from a YouTube video or playlist URL. Also trigger when the user pastes a YouTube URL and asks about its content.
npx claudepluginhub msapps-mobile/claude-plugins --plugin youtube-transcriberThis skill uses the workspace's default tool permissions.
Extract transcripts from YouTube videos and playlists using browser-based caption extraction.
Guides Next.js Cache Components and Partial Prerendering (PPR) with cacheComponents enabled. Implements 'use cache', cacheLife(), cacheTag(), revalidateTag(), static/dynamic optimization, and cache debugging.
Migrates code, prompts, and API calls from Claude Sonnet 4.0/4.5 or Opus 4.1 to Opus 4.5, updating model strings on Anthropic, AWS, GCP, Azure platforms.
Automates semantic versioning and release workflow for Claude Code plugins: bumps versions in package.json, marketplace.json, plugin.json; verifies builds; creates git tags, GitHub releases, changelogs.
Extract transcripts from YouTube videos and playlists using browser-based caption extraction. Works with any video that has auto-generated or manual captions — no API key required.
Environment note: This skill works in both Claude Code and Cowork. It requires the Claude in Chrome extension in both environments. The Chrome MCP tools (
navigate,javascript_tool,get_page_text, etc.) work identically in both.
This skill requires Claude in Chrome (browser automation). If the Chrome MCP tools
(navigate, javascript_tool, get_page_text, etc.) are not available, inform the user:
navigate to: https://www.youtube.com/watch?v={VIDEO_ID}
Wait for the page to load. If given a short URL (youtu.be/ID) or a URL with extra params, extract the video ID and use the canonical format above.
Use javascript_tool to click "...more" on the description:
const expandBtn = document.querySelector('#description-inline-expander #expand')
|| document.querySelector('tp-yt-paper-button#expand');
if (expandBtn) expandBtn.click();
Wait 1-2 seconds for the description to expand.
Use javascript_tool to find and click the "Show transcript" button:
const buttons = document.querySelectorAll('button.yt-spec-button-shape-next');
let clicked = false;
buttons.forEach(b => {
if (b.innerText.includes('Show transcript') || b.innerText.includes('הצגת תמליל') || b.innerText.includes('להצגת התמליל')) {
b.click();
clicked = true;
}
});
clicked ? 'Transcript panel opened' : 'Show transcript button not found';
Wait 2 seconds for the transcript panel to load.
If the transcript button is not found, the video may not have captions. Inform the user.
YouTube lazy-loads transcript segments. Scroll the engagement panel to trigger loading:
(() => {
const panel = document.querySelector(
'ytd-engagement-panel-section-list-renderer[visibility="ENGAGEMENT_PANEL_VISIBILITY_EXPANDED"]'
);
if (!panel) return 'No transcript panel found';
const scroller = panel.querySelector('#content');
if (!scroller) return 'No scrollable content found';
// Scroll to bottom to trigger lazy-load
scroller.scrollTop = scroller.scrollHeight;
return 'Scrolled transcript panel';
})();
Important: Run this scroll snippet 2-3 times with a short pause between each call to ensure all segments load. For long videos (10+ minutes), scroll more aggressively.
Use javascript_tool to extract text from the engagement panel and parse it:
(() => {
const panel = document.querySelector(
'ytd-engagement-panel-section-list-renderer[visibility="ENGAGEMENT_PANEL_VISIBILITY_EXPANDED"]'
);
if (!panel) return 'ERROR: No transcript panel found';
const raw = panel.innerText;
const lines = raw.split('\n').map(l => l.trim()).filter(l => l.length > 0);
const timestampRe = /^(\d{1,2}:)?\d{1,2}:\d{2}$/;
const hebrewTimeWords = /שני|דקו|שעה/;
const result = [];
for (let i = 0; i < lines.length; i++) {
if (timestampRe.test(lines[i])) {
const ts = lines[i];
let text = '';
if (i + 1 < lines.length && !timestampRe.test(lines[i + 1])) {
if (hebrewTimeWords.test(lines[i + 1])) {
if (i + 2 < lines.length && !timestampRe.test(lines[i + 2])) {
text = lines[i + 2];
i += 2;
} else {
i += 1;
continue;
}
} else {
text = lines[i + 1];
i += 1;
}
}
if (text) result.push(ts + ' ' + text);
}
}
return result.length > 0
? result.join('\n')
: 'ERROR: Could not parse transcript lines. Raw line count: ' + lines.length;
})();
Use javascript_tool:
document.querySelector('yt-formatted-string.ytd-watch-metadata')?.innerText || document.title;
Combine the video title, URL, and transcript into a clean document:
# {Video Title}
Video: https://www.youtube.com/watch?v={VIDEO_ID}
{timestamp} {text}
{timestamp} {text}
...
Save to the outputs folder as a .txt file.
When the user provides a playlist URL:
Navigate to the playlist URL, then use javascript_tool:
(() => {
const links = document.querySelectorAll('a#video-title');
const videos = [];
const seen = new Set();
links.forEach(a => {
const href = a.href;
const match = href.match(/[?&]v=([a-zA-Z0-9_-]{11})/);
if (match && !seen.has(match[1])) {
seen.add(match[1]);
videos.push({ id: match[1], title: a.innerText.trim() });
}
});
return JSON.stringify(videos);
})();
If the playlist has many videos, scroll down first to load them all:
for (let i = 0; i < 10; i++) {
window.scrollBy(0, 2000);
await new Promise(r => setTimeout(r, 500));
}
Loop through each video ID and follow Steps 1-7 from Single Video Transcription. Store each transcript in a separate variable/file, then compile at the end.
Important: Between videos, navigate directly to the next URL — do not rely on the playlist's auto-play.
Create a compiled file with all transcripts separated by headers:
============================================================
Video 1: {Title}
URL: https://www.youtube.com/watch?v={ID}
============================================================
{transcript}
============================================================
Video 2: {Title}
...
Save to outputs as {playlist-name}-transcripts.txt.
| Problem | Solution |
|---|---|
| "Show transcript" button not found | The video may not have captions. Try checking if captions exist via the CC button in the player controls. |
| Transcript panel loads but is empty | Scroll the panel more aggressively (increase scroll iterations to 20+). |
| Hebrew/Arabic time descriptions mixed in | The extraction script filters these out using the hebrewTimeWords regex. If new patterns appear, add them. |
| Wrong language detected by YouTube | YouTube sometimes misdetects the language for songs. Note this in the output but still extract whatever text is available. |
| Very short video (<30 seconds) | May not have auto-generated captions. Inform the user and offer to describe the video content instead. |
navigate tool not available | This skill requires Claude in Chrome. Suggest installing the Chrome extension. |