Skip to main content

Turn YouTube playlists into Notion databases, Obsidian notes, or Anki decks.

Project description

playlistpipe

Turn a YouTube playlist into a Notion database, Obsidian vault, or Anki deck.

plp "https://youtube.com/playlist?list=..." --to notion-api
plp "https://youtube.com/playlist?list=..." --to obsidian --vault ~/vault
plp "https://youtube.com/playlist?list=..." --to anki

Why this exists

I was working through a 40-video React course on YouTube and wanted a checklist I could tick off, with notes per video, that synced between my laptop and phone. The obvious home for that is Notion, except adding 40 videos to a Notion database by hand is tedious and you give up after video eight.

Every tool I tried either dumped a text file I still had to reformat, or demanded a Google API key for a 30-minute setup, or was a browser extension that broke the next time YouTube shipped a frontend change. So I wrote this.

It does one thing: take a playlist URL, pull out titles and durations and channels, and hand them to wherever you actually keep your learning stuff.

What you can send a playlist to

Target What you get Use it for
notion-api A real Notion database with typed columns Course progress tracking
notion-md Markdown checklist (optionally copied to clipboard) Pasting into any Notion page
obsidian One note per video with YAML frontmatter + index Research, long-term reference
anki A .apkg file with two cards per video Spaced review of what you watched

Re-running on the same playlist updates in place. It won't clobber notes you've added, and it won't duplicate Anki cards. That part matters more than you'd think.

Install

pip install playlistpipe

Or with pipx if you want it isolated:

pipx install playlistpipe

You'll also want pyperclip if you plan to use --copy:

pip install "playlistpipe[clipboard]"

Getting started with each target

Notion (API, the real version)

One-time setup:

  1. Go to https://www.notion.so/my-integrations, click New integration, name it something like "playlistpipe". Copy the Internal Integration Token — starts with secret_.
  2. In Notion, open the page where you want the database to live. Click the ... menu in the top right, then Connections, and add your new integration.
  3. Copy the page's ID. It's the 32-character chunk at the end of the URL — https://notion.so/My-Page-abc123...def789 → the abc123...def789 bit.
export NOTION_TOKEN=secret_...
plp "https://youtube.com/playlist?list=..." \
    --to notion-api --notion-parent YOUR_PAGE_ID

The output tells you the new database's URL. On subsequent runs, pass --notion-db DATABASE_ID to append to the same database instead of making a new one. Or put both in ~/.config/playlistpipe/config.toml and forget about them:

[notion]
token = "secret_..."
default_parent_page_id = "abc123..."

Notion (copy-paste, no setup)

For one-off use or if you don't want to mess with API tokens:

plp "https://youtube.com/playlist?list=..." --to notion-md --copy

The markdown ends up on your clipboard. Paste it into any Notion page and it becomes a real checklist. Without --copy, you get a .md file in the output directory.

Obsidian

plp "https://youtube.com/playlist?list=..." --to obsidian --vault ~/MyVault

This creates MyVault/YouTube/Playlist Name/ with one markdown file per video plus an _index.md that uses Dataview to show progress. The frontmatter looks like:

---
title: "Intro to Hooks"
url: "https://youtu.be/..."
channel: "Dev Ed"
duration: 745
position: 3
playlist: "React Full Course"
watched: false
tags: [youtube]
---

The watched: false field is the key bit — flip it to true as you go and Dataview will show you your progress in the index note. If you edit the video notes (adding your own notes, changing tags), re-running the tool preserves those edits. The index gets regenerated every time.

Anki

plp "https://youtube.com/playlist?list=..." --to anki

Outputs a .apkg file you can drag into Anki. Each video becomes one note with two cards: a recall card (channel + duration → title) and a review card (title + link → "do you remember what this covers?"). Useful for study-heavy playlists — lectures, conference talks, language videos.

Add --thumbnails if you want the video thumbnails embedded. They're downloaded from YouTube's CDN with a size cap, so large playlists don't blow up.

Re-running updates existing cards in place, so editing a playlist on YouTube and re-exporting won't duplicate your deck.

Compared to alternatives

Being honest because I'd want someone to be honest with me:

yt-dlp --flat-playlist --print "%(title)s" — the serious answer for anyone who just wants a list of titles. If you're technical and that's all you need, use it. This tool uses yt-dlp under the hood for scraping and then focuses entirely on the export side, which yt-dlp doesn't do.

TubeBuddy / VidIQ / YouTube browser extensions — more features, but closed-source, ad-supported, and they don't integrate with Notion or Obsidian. If you want an analytics tool, they're better. If you want to turn a playlist into a study system, they're not the right shape.

Notion Web Clipper — works one video at a time. That's the problem this tool solves.

Configuration

All settings live in ~/.config/playlistpipe/config.toml (or $XDG_CONFIG_HOME/playlistpipe/config.toml if you set that). Full example:

[notion]
token = "secret_..."
default_parent_page_id = "abc123..."
# default_database_id = "xyz789..."    # if you always append to the same DB

[obsidian]
vault_path = "~/MyVault"

[defaults]
output_dir = "~/playlistpipe-out"

Environment variables override the config file:

  • NOTION_TOKEN or PLAYLISTPIPE_NOTION_TOKEN
  • PLAYLISTPIPE_OBSIDIAN_VAULT
  • PLAYLISTPIPE_OUTPUT_DIR

Tokens on the command line are deliberately not supported — they end up in your shell history, and that's a bad default.

What it won't do

  • Download videos. Use yt-dlp for that. This is metadata only.
  • Extract transcripts. youtube-transcript-api does that well.
  • Summarize with AI. Out of scope. Pipe the output to your tool of choice.
  • Scrape private playlists. We don't ask for your YouTube login. If a playlist is public or unlisted, it works; if it's private, it doesn't.
  • Work on channel pages. Playlists only. A channel's "uploads" is a playlist — use that URL instead of the channel URL.

Development

git clone https://github.com/srimur/playlistpipe
cd playlistpipe
pip install -e ".[dev]"
pytest

The test suite is strict on purpose — security-relevant behavior (URL validation, HTML escaping in Anki cards, path traversal checks) has regression tests you shouldn't remove without replacing.

Architecture:

src/playlistpipe/
├── cli.py                   # argparse, dispatch to exporters
├── config.py                # XDG config, env precedence
├── logging_setup.py         # token redaction filter
├── core/
│   ├── models.py            # Video, Playlist, Exporter protocol
│   ├── scraper.py           # yt-dlp wrapper, returns Playlist
│   └── utils.py             # url parsing, path safety, http session
└── exporters/
    ├── notion_api.py
    ├── notion_markdown.py
    ├── obsidian.py
    └── anki.py

Adding a new exporter is three things: a class implementing the Exporter protocol, a config dataclass, and wiring in cli.py. See existing exporters for the pattern.

Security notes

  • Notion tokens are read from env or config only, never from argv; they're redacted from all log output via a logging.Filter.
  • Every user-sourced string that becomes an Anki card field is passed through html.escape(quote=True). Anki's renderer is a WebEngine that executes JS, so this matters.
  • Thumbnail downloads are restricted to YouTube's CDN hosts, capped at 2 MiB, and have explicit timeouts. No arbitrary HTTP fetches.
  • Output paths are validated with Path.is_relative_to() against the configured output directory. No traversal via --deck-name "../../".

If you find something I missed, open an issue or email me directly.

License

MIT.

Credits

  • yt-dlp does the actual scraping.
  • genanki builds the Anki packages.
  • Notion's API is documented well enough that the exporter was an evening's work. That's rare, and appreciated.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

playlistpipe-0.1.0.tar.gz (31.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

playlistpipe-0.1.0-py3-none-any.whl (34.0 kB view details)

Uploaded Python 3

File details

Details for the file playlistpipe-0.1.0.tar.gz.

File metadata

  • Download URL: playlistpipe-0.1.0.tar.gz
  • Upload date:
  • Size: 31.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for playlistpipe-0.1.0.tar.gz
Algorithm Hash digest
SHA256 1301b4401a684dfd1037d8cc6ed0d7b4c1d18c6c6d7e0a1105a879b95d432c25
MD5 810a905d7ecc1be487430cdccc2dd56b
BLAKE2b-256 a3b1cbc3f9909943b418243355502c153901c814d58458fa6a1d935dec73c418

See more details on using hashes here.

File details

Details for the file playlistpipe-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: playlistpipe-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 34.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for playlistpipe-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4eadd4868e9c27398e7aa8d515d7d7bd38aba86fb7b37a7094ecbc0ebac164b3
MD5 81a853a4fb3976c82e327c523b720581
BLAKE2b-256 1fd8a336af4c62b0a098598c4a446e04d42251bf54aa10dd8e0f7966a9c51cdd

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page