A production-ready REST API for video downloads and metadata extraction using yt-dlp. Supports YouTube with cookie authentication, async job processing, and Prometheus metrics.
- Video Operations: Metadata extraction, format listing, video/audio download
- Async Downloads: Job queue with priority, progress tracking, retry logic
- Authentication: API key authentication with multi-key support
- Rate Limiting: Token bucket rate limiter (100 rpm metadata, 10 rpm downloads)
- Cookie Management: Hot-reload, validation, 7-day expiry warnings
- Monitoring: Prometheus metrics, structured JSON logging, health checks
- Security: Non-root container, input validation, path traversal prevention
- Docker Ready: Multi-stage build, docker-compose, resource limits
- Clone and configure:
git clone https://github.com/fvadicamo/yt-dlp-api.git
cd yt-dlp-api
# Create required directories
mkdir -p downloads cookies logs
# Create .env file with your API key
echo 'API_KEY=["your-secure-api-key"]' > .env
echo 'ALLOW_DEGRADED_START=true' >> .env # Optional: start without cookies- Start the service:
docker compose up -d- Verify it's running:
curl http://localhost:8000/health# Create virtual environment
python3 -m venv venv
source venv/bin/activate
# Install dependencies
pip install -r requirements-dev.txt
# Run the application
uvicorn app.main:app --reloadAll API endpoints (except health checks) require an API key:
curl -H "X-API-Key: your-api-key" http://localhost:8000/api/v1/info?url=...curl -H "X-API-Key: your-api-key" \
"http://localhost:8000/api/v1/info?url=https://www.youtube.com/watch?v=dQw4w9WgXcQ"curl -H "X-API-Key: your-api-key" \
"http://localhost:8000/api/v1/formats?url=https://www.youtube.com/watch?v=dQw4w9WgXcQ"# Start download job
curl -X POST -H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ", "format_id": "best"}' \
http://localhost:8000/api/v1/download
# Response: {"job_id": "abc123", "status": "pending", ...}
# Check job status
curl -H "X-API-Key: your-api-key" \
http://localhost:8000/api/v1/jobs/abc123curl -X POST -H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ", "extract_audio": true, "audio_format": "mp3"}' \
http://localhost:8000/api/v1/download# Full health check (returns 503 if unhealthy)
curl http://localhost:8000/health
# Liveness probe (always 200 if app is running)
curl http://localhost:8000/liveness
# Readiness probe (200 if ready to accept traffic)
curl http://localhost:8000/readinesscurl http://localhost:8000/metricsYouTube requires authentication cookies for most downloads. Export cookies from your browser:
- Install Get cookies.txt LOCALLY extension
- Go to youtube.com and log in
- Click the extension icon → Export → Save as
cookies/youtube.txt
- Install cookies.txt extension
- Go to youtube.com and log in
- Click the extension icon → Export → Save as
cookies/youtube.txt
curl -X POST -H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{"provider": "youtube"}' \
http://localhost:8000/api/v1/admin/validate-cookiecurl -X POST -H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{"provider": "youtube"}' \
http://localhost:8000/api/v1/admin/reload-cookie| Variable | Default | Description |
|---|---|---|
API_KEY |
(required) | JSON array of API keys, e.g. ["key1", "key2"] |
ALLOW_DEGRADED_START |
false |
Start without valid cookies |
LOG_LEVEL |
INFO |
Logging level (DEBUG, INFO, WARNING, ERROR) |
METRICS_ENABLED |
true |
Enable Prometheus metrics |
See DEPLOYMENT.md for the complete list of 30+ configuration options.
server:
host: "0.0.0.0"
port: 8000
storage:
output_dir: "/app/downloads"
cleanup_age: 24 # hours
max_file_size: 524288000 # 500MB
downloads:
max_concurrent: 5
queue_size: 100
rate_limiting:
metadata_rpm: 100
download_rpm: 10
burst_capacity: 20
logging:
level: "INFO"
format: "json"
providers:
youtube:
enabled: true
cookie_path: "/app/cookies/youtube.txt"
retry_attempts: 3| Endpoint | Method | Description |
|---|---|---|
/health |
GET | Health check with component status |
/liveness |
GET | Kubernetes liveness probe |
/readiness |
GET | Kubernetes readiness probe |
/metrics |
GET | Prometheus metrics |
/api/v1/info |
GET | Get video metadata |
/api/v1/formats |
GET | List available formats |
/api/v1/download |
POST | Start download job |
/api/v1/jobs/{id} |
GET | Get job status |
/api/v1/admin/validate-cookie |
POST | Validate provider cookies |
/api/v1/admin/reload-cookie |
POST | Hot-reload cookies |
Full API documentation available at /docs (Swagger UI) or /redoc.
| Code | HTTP Status | Description |
|---|---|---|
INVALID_URL |
400 | URL malformed or unsupported |
INVALID_FORMAT |
400 | Format ID invalid |
AUTH_FAILED |
401 | API key missing or invalid |
VIDEO_UNAVAILABLE |
404 | Video private/deleted/geo-blocked |
JOB_NOT_FOUND |
404 | Job ID not found or expired |
RATE_LIMIT_EXCEEDED |
429 | Rate limit hit, check Retry-After |
DOWNLOAD_FAILED |
500 | Download operation failed |
QUEUE_FULL |
503 | Download queue at capacity |
- YouTube provider may be disabled (missing/invalid cookies)
- Check
/healthendpoint for component status - Ensure cookies are exported correctly
- Try
ALLOW_DEGRADED_START=truefor testing without cookies
- Cookies may be expired (YouTube cookies last ~1 year)
- Re-export cookies from browser
- Check cookie file format (Netscape format required)
- Verify cookie file permissions
- Wait for Retry-After seconds indicated in response
- Metadata: 100 requests/minute
- Downloads: 10 requests/minute
- Ensure
API_KEYenvironment variable is set - Check logs:
docker compose logs -f - Verify config.yaml is mounted correctly
| Document | Description |
|---|---|
| DEPLOYMENT.md | Docker and Kubernetes deployment guide |
| CONFIGURATION.md | Complete configuration reference (30+ options) |
| CHANGELOG.md | Version history and release notes |
| CONTRIBUTING.md | Development setup and contribution guidelines |
| RELEASING.md | Release process for maintainers |
| SECURITY.md | Security policy and vulnerability reporting |
# Run tests
make test
# Run all checks (format, lint, type, security, test)
make check
# Format code
make format- Python 3.11+
- ffmpeg (for audio extraction)
- Node.js 20+ (for yt-dlp JavaScript challenges)
- Docker (recommended for deployment)
MIT