Minimalist, modern and responsive YouTube downloader: get your video as MP4 (360p/480p/720p/1080p) or your audio as MP3, plus a short direct link to the file stored on the server.
Note
YPi is built for a clean, frictionless experience: paste a link, pick a format, get a direct link. Files are stored locally and expire automatically after 3 minutes — plenty of time to download while keeping the server tidy.
YPi is a YouTube downloader web app with a TypeScript backend that combines several download engines:
- MP4 video (360p, 480p, 720p & 1080p) — engines run in parallel and the first one to deliver the exact quality wins (it never silently downgrades).
- MP3 audio (96, 128, 256 & 320 kbps) — also raced in parallel; the fastest response wins.
- Video details (title, channel and thumbnail) — fetched from YouTube's public API.
- Real download progress — the UI shows the actual percentage of the download as it happens.
- Bilingual UI — switch between Spanish and English at any time (ES/EN toggle in the header, remembered on your next visit).
When you request a download, the server downloads the file buffer, saves it locally and generates a short link (/d/AbC123xY) that automatically detects the current domain, so it always works. The interface shows the real download percentage in real time.
| Requirement | Description |
|---|---|
| Node.js v20+ | To run the server |
| Bun 1.x | To install dependencies and run the scripts |
🍃 Linux / macOS / Windows
git clone https://github.com/nauut2/ypi.gitcd ypibun installbun run devThe app will be available at
http://localhost:3000(respecting thePORTvariable if set).
🍀 Production
bun installbun run buildbun start🦎 No environment variables or API keys needed.
- Paste the YouTube link (video, Short or
youtu.be). - Choose Video · MP4 (360p/480p/720p/1080p) or Audio · MP3 (96/128/256/320 kbps).
- Hit Download and follow the real progress until you get your direct link.
| Endpoint | Method | Description |
|---|---|---|
/api/video |
POST |
{ "url": "…", "quality": 360 | 480 | 720 | 1080, "lang": "es" | "en" } → MP4 video (SSE progress) |
/api/audio |
POST |
{ "url": "…", "quality": 128, "lang": "es" | "en" } → MP3 audio (96/128/256/320) |
/d/:id.mp4 · /d/:id.mp3 |
GET |
Direct download of the stored file (with extension) |
/health |
GET |
Service status |
Example:
curl -X POST http://localhost:3000/api/audio \
-H "Content-Type: application/json" \
-d '{"url":"https://www.youtube.com/watch?v=dQw4w9WgXcQ","quality":128,"lang":"en"}'{
"ok": true,
"data": {
"id": "8dj9vC8r",
"downloadUrl": "http://localhost:3000/d/8dj9vC8r.mp3",
"filename": "Rick Astley - Never Gonna Give You Up.mp3",
"size": 472670,
"calidad": "128 kbps",
"expiraEn": 180
}
}ypi/
├── public/ # Frontend (HTML · CSS · JS)
│ ├── index.html
│ ├── styles.css
│ └── app.js
├── src/ # TypeScript backend
│ ├── index.ts # Express server + API routes + short links + SSE progress
│ ├── utils.ts # Utilities (videoId, MP4 resolution, timeouts)
│ ├── storage.ts # Local storage, short IDs, 3-minute expiry
│ └── services/ # Download engines (video & audio)
├── downloads/ # Downloaded files (self-cleaning)
├── package.json
└── tsconfig.json🍀 Want to contribute? Pull requests and issues are welcome.
This project is not affiliated with YouTube or Google. It is an independent tool for personal and educational use. Respect copyright and YouTube's terms of service when downloading content.
