Tape is a Chrome extension for the Mac that downloads any video you can watch online, from any page on any website, in the quality you choose and with subtitles. It finds the videos a page is playing, names each file after the heading above it, and keeps downloading in the background after Chrome is closed. The name comes from taping a show to watch later.
Keeping a copy of a video you can watch in Chrome usually takes a different workaround for each site:
- YouTube has no button that saves a file you keep. Premium downloads only play inside YouTube.
- Most other sites stream video in small pieces, so there's no file to right-click and save.
- yt-dlp, the open-source engine that reads well over a thousand sites, runs in the terminal, and each site needs its own options for quality, subtitles and login.
- Files that do get saved have names like
master.mp4or the site's name, so a folder of downloads is hard to use. - Subtitles arrive as a separate file that QuickTime ignores, or with a language code in the name that some players skip.
- Downloading a long playlist in one burst gets slowed down or blocked by YouTube.
Anyone who wants to keep a copy of a video they can watch online, from any page on any website. I built it for my own use on my Mac.
- Finds the videos on any page while it plays, and the toolbar icon shows how many. The list is ready when you open it: one row per video, named after the heading above it, with each quality's size and your default quality preselected.
- Downloads YouTube videos, playlists and whole channels from a button under the player, a button on thumbnails, the right-click menu or a keyboard shortcut.
- Offers presets such as 1080p MP4, 4K for QuickTime, Podcast MP3 and subtitles only, and shows each quality's size before you download, so you can see what 4K costs next to 1080p.
- Saves subtitles three ways: an
.srtfile named exactly like the video, a plain-text transcript, and a track inside the video that QuickTime plays. - Uses your login on a site only after you turn it on for that site, for videos you can only watch signed in.
- Remembers the folder you pick for each site, so the next video from that site goes to the same place.
- Keeps downloading with Chrome closed and picks up again after a restart. A side panel shows the queue with pause, resume, retry and Show in Finder.
- Watches the channels and playlists you choose and downloads new uploads on a schedule.
- Also cuts clips, removes sponsor segments with SponsorBlock, keeps or splits chapters, records live streams from the start, and skips videos you've already downloaded.
An extension alone can't do the work well. YouTube serves anything above 360p as separate video and audio that ffmpeg has to merge, merging inside the browser is slow and limited to 2 GB files, and Chrome stops idle extension code, which would cut off long downloads. So the extension is only the interface, and a Python service on the Mac runs yt-dlp and ffmpeg. It starts at login, keeps going with Chrome closed, and updates yt-dlp daily, which matters because YouTube changes often. The cost is that Tape only works on macOS and the helper is installed from the terminal.
The Chrome Web Store rejects extensions that download from YouTube. Tape is built for personal use and loaded through Chrome's developer mode. The cost is no one-click install and no automatic updates for the extension.
The first version looked for videos only when you clicked the icon. In testing it was slow and listed one video 23 times. It now works the way Video DownloadHelper does: it notes the video streams a page loads as you browse, folds a stream's quality copies into one row, and counts the videos on the toolbar icon. The cost is permission to read every site. What it finds stays in Chrome's session storage and is cleared when the page changes, and page addresses only go to the helper on the Mac.
A stream's own name is usually index or master. Tape names each video after the heading above it, then the player's own title, then the page title. Several videos from one page go into a folder named after the page, numbered in page order. Names can be edited before downloading. A name that's already taken gets " (2)" when the download is created, so a retried download keeps writing to its own file.
QuickTime only shows subtitles stored inside the video file, and many other players only pick up a separate subtitle file whose name matches the video exactly. Tape saves both, plus a plain-text transcript for reading and searching. The cost is three files per video, and each one can be switched off.
Some videos can only be watched signed in. Tape copies Chrome's cookies for a site only after you turn on "Use my login" for that site, and turning it off deletes the copy. YouTube login is off by default, because yt-dlp's developers warn that heavy use can get an account flagged.
YouTube slows down or blocks clients that download a playlist in one burst. Videos from one playlist download one at a time, with a random 5 to 15 second pause between them, and videos downloaded before are skipped. Each download uses eight connections, because YouTube throttles single connections unevenly. Videos from other web pages skip the pause. The cost is that a large channel takes longer.
A program that downloads whatever it's asked to is a target for malicious web pages. The helper only listens on 127.0.0.1 and needs a pairing token on every request. It rejects requests that come from web pages, checks the Host header to block DNS rebinding, sends no CORS headers, and refuses addresses on your own network when a page supplies them. Cookies and login headers never go into the download history.
I used each version on the sites I actually download from and turned what broke into the next round of work. Most fixes came with automated tests so the problem can't quietly come back.
| Round | What I saw | Cause | What changed |
|---|---|---|---|
| 1 | A 27-video playlist downloaded slowly | My connection did 14 MB/s, but YouTube sent some videos at under 0.2 MB/s, with stalls | Eight connections per download, stalled connections dropped after 10 seconds instead of 20, and one automatic retry on temporary errors |
| 2 | On a page with one video, Tape listed 23, and "Reading videos" never finished | Lookups shared one copy of my login cookies, so all but the first failed. Without them Tape couldn't tell a stream's quality copies apart, so each became a row. Nothing started until I clicked | Detection rebuilt to run while the page plays, with quality copies folded into one row, sizes shown, my default quality preselected, and slow lookups dropped after 10 seconds |
| 3 | A video that played fine in Chrome stuck on "Reading video info" | My network gave the Mac an IPv6 address that didn't carry traffic. Chrome quietly fell back to IPv4, but yt-dlp kept waiting | The helper uses IPv4 whenever it works and checks again every 5 minutes |
| 4 | A video saved under the website's name | The page had no heading above the player, so the name fell back to the page title | The player's own title now comes before the page title |
| 5 | Subtitles next to a video didn't show up in my player | yt-dlp adds a language code (Video.eng.srt), and the player only reads a file named exactly like the video |
One language is saved as Video.srt. Several languages keep their codes |
| 6 | On another site, Tape found nothing | Its player loads streams by script from addresses with no .m3u8 ending. The first check ran before I'd turned on my login and never ran again |
Pages on sites yt-dlp supports are checked as they load, failed videos are retried when login is turned on, and the row says which switch to turn on |
| 7 | A video landed at the top of my download folder instead of the subfolder I'd just made for it | There was one download folder for everything | A "Save to" folder in the popup, remembered for each site. Downloads already queued keep their folder |
The requirements became automated tests, in three layers:
- 106 unit and API tests for the helper. They cover how options turn into yt-dlp settings, file naming, the queue, subtitles and transcripts, page detection, and the local service's security checks.
- An offline end-to-end test that loads the built extension in Chromium with its own helper and a local test page, then makes 17 checks, from the toolbar count to the files on disk.
- Real downloads from YouTube. One test drives the popup, the YouTube menu and the side panel. A smoke test downloads a video with subtitles and a 1080p clip, then inspects the files with ffprobe (20 checks).
They cover these requirements:
- Videos are found before Tape is opened. The toolbar shows the right count while the page loads, and the list appears in under 2 seconds.
- One row per video. An HLS stream and its quality copies show as one row, with a size for each quality.
- Names come from the page. Files are named after the heading above each video and numbered in page order.
- Subtitles arrive in all three forms: an
.srtand a.txtnamed like the video, and a subtitle track inside the file. - The quality you pick is the quality you get. Picking 180p produces a 180p file.
- Files go where you said, including a folder picked for the site, and nothing is left in the temp folder.
- The local service refuses requests without the token, from web pages, or with an unexpected Host header.
- Mac only, and the helper is installed from the terminal.
- It's loaded as an unpacked extension, because the Chrome Web Store doesn't accept YouTube downloaders.
- Video protected with DRM, such as purchased movies and most streaming services, can't be downloaded.
- A player that hasn't started loading its video shows up once you press play.
- When a site changes, downloads from it can break until yt-dlp catches up. The helper updates yt-dlp daily.
- Heavy use can trigger YouTube's "Sign in to confirm you're not a bot" check.
Only download what you have the right to keep.
- Downloads that finish on their own: retries with backoff, waiting out network drops, keeping the Mac awake, and a disk-space check before big jobs.
- More sites: spotting streams by their content type instead of their address, getting past Cloudflare checks, and per-site rules for names and ad players.
- Every video linked from a page in one go.
- Trimming a video before downloading it.
- Transcribing videos that have no subtitles, on the Mac, plus summaries, chapters and translated subtitles, on the Mac or with Claude.
- A library that searches everything saved, including what was said, with a player that remembers where you stopped.
I defined the problem and the requirements, chose between the options at each decision point, tested every version on the sites I download from, and decided what to fix next. The code was written with Claude Code, an AI coding assistant, working from those requirements and my test feedback. I use it for my own downloads, and it has saved 222 videos so far: 131 from YouTube and 91 from other websites.
You need a Mac, Homebrew and Chrome.
-
Download this repository (Code > Download ZIP, then unzip it) or clone it.
-
Install the helper. It installs ffmpeg, Deno and uv through Homebrew if they're missing, starts the background service and prints a pairing token.
./scripts/install.sh
-
Build the extension. This needs pnpm.
cd extension pnpm install pnpm build -
Open
chrome://extensions, turn on Developer mode (top right), click Load unpacked and chooseextension/.output/chrome-mv3. -
Click the Tape icon in the toolbar and paste the pairing token. To print it again, run
~/.local/bin/ytdl-helper --print-token.
Then:
- On any site, start playing a video. The toolbar icon shows how many videos Tape found. Click it for the list.
- On YouTube, click Download file under the player and pick a preset, or open the popup to see every quality with its size.
- Thumbnails on YouTube get a download button on hover. Shift-click it to choose options.
- Right-click a YouTube link or page and choose Download with Tape. Alt+Shift+D downloads the current video with your default preset, and Alt+Shift+Y opens the popup.
- The list icon in the popup opens the side panel with the queue.
- On a channel or playlist, choose Download new uploads automatically and the helper checks for new videos on a schedule.
Files go to ~/Movies/YouTube until you choose another folder in Settings or under Save to in the popup.
- How it works: the two parts, privacy and security, troubleshooting, and how to run the tests.
- Built on yt-dlp and ffmpeg.
- The screenshots show a made-up demo site and Big Buck Bunny (© Blender Foundation, CC BY 3.0).
pnpm screenshotsmakes them. - License: MIT.


