- HTML 63.1%
- JavaScript 35.9%
- Dockerfile 1%
- Extract ytdlp.js with sanitizeUrl, isPlaylistUrl, parseYtDlpJson, and scheduled auto-update (every 24h, first check after 5m) - Fix YouTube n-challenge: add --js-runtimes node and --ignore-config to all yt-dlp invocations; yt-dlp[default] bundles EJS scripts - Fix format selection: detect preset selector strings vs numeric IDs to avoid double-wrapping format args - Guard cookies.txt: only pass --cookies if file is non-empty - Add playlist URL rejection in /api/info - Unify UI: login.html now shares the same design system as index.html (fonts, CSS variables, card style, background grid) - Add sign-out confirmation modal with CSRF-POST flow - Overhaul README: add cookies, reverse proxy, and auto-update docs - Tighten .gitignore and .dockerignore Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|---|---|---|
| .github/workflows | ||
| public | ||
| tests | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| auth.js | ||
| docker-compose-build.yml | ||
| docker-compose.yml | ||
| Dockerfile | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| server.js | ||
| vitest.config.js | ||
| ytdlp.js | ||
FETCH — yt-dlp Web UI
A self-hosted video downloader with a clean web UI, powered by yt-dlp. Runs as a Docker container with OAuth authentication.
Supports YouTube, Vimeo, TikTok, Twitter/X, and 1000+ other sites.
Warning
This repo has been heavily generated with Claude.
Requirements
- Docker + Docker Compose
- At least one OAuth provider configured (GitHub, Google, or Authentik)
Everything else (Node.js, yt-dlp, ffmpeg, Python) is inside the image.
Quick start
cp .env.example .env
# Edit .env — add AUTH_SECRET and at least one OAuth provider
docker compose up -d
# App is at http://localhost:4242
Authentication
All routes require login. AUTH_SECRET is always required.
# Generate AUTH_SECRET
openssl rand -base64 32
| Provider | Required env vars | Register at |
|---|---|---|
| GitHub | GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET |
github.com/settings/developers |
GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET |
console.cloud.google.com/apis/credentials | |
| Authentik | AUTHENTIK_CLIENT_ID, AUTHENTIK_CLIENT_SECRET, AUTHENTIK_ISSUER |
Your Authentik instance |
Set the OAuth callback URL to: https://your-domain/auth/callback/<provider>
YouTube cookies
YouTube requires authentication cookies to serve video formats (bot detection).
- Install the "Get cookies.txt LOCALLY" browser extension
- Go to youtube.com while logged in, export cookies in Netscape format
- Save the file as
cookies.txtnext todocker-compose.yml
The file is mounted at /app/cookies.txt — yt-dlp picks it up automatically. Without it, YouTube downloads will fail. Cookies expire periodically and will need re-exporting.
Reverse proxy
When running behind a reverse proxy (Traefik, nginx, etc.), set in .env:
AUTH_URL=https://your-domain
AUTH_TRUST_HOST=true
docker-compose-build.yml includes pre-configured Traefik labels as a reference.
Commands
docker compose up -d # Start
docker compose down # Stop
docker compose logs -f # Follow logs
docker compose up --build -d # Rebuild after code changes
yt-dlp auto-updates inside the container every 24 hours (first check 5 minutes after startup).
Development
npm install
npm start # Runs on http://localhost:4242
npm test # Run tests once
npm run test:watch
Note: local dev won't have yt-dlp or ffmpeg unless installed on the host. Docker is the recommended way to run this.
Notes
- Downloaded files land in
./downloadson the host (mounted into the container) - Files expire and are cleaned up 10 minutes after download
- To change the port, edit
"4242:4242"indocker-compose.yml