A FastAPI service for reading public YouTube video metadata, captions, timestamped transcripts, and available transcript languages.
The server is designed for small apps, internal tools, automations, and agents that need a simple HTTP API around YouTube oEmbed and transcript data.
- Video metadata lookup through YouTube oEmbed.
- Caption extraction with language fallback.
- Timestamped transcript generation.
- Transcript language discovery.
- Two endpoint styles: root routes and
/youtube/*namespaced routes. - Optional Webshare proxy support for transcript requests.
- Optional generic HTTP proxy support for metadata requests.
- Optional API key or JWT authentication.
- Docker, pytest, and curl-based endpoint checks.
- Python 3.10+; Python 3.12 is recommended for deploys
pip- Docker, optional
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
cp .env.example .envCheck the active configuration:
python load_env.pyStart the server locally:
python -m app.mainThe default server address is http://localhost:8000.
Start with Docker:
docker-compose up -dHosted Python platforms can use the included Procfile and runtime.txt.
Health and documentation:
GET /GET /healthGET /docsGET /redoc
Video endpoints:
POST /video-dataPOST /video-captionsPOST /video-timestampsPOST /video-transcript-languagesPOST /youtube/video-dataPOST /youtube/video-captionsPOST /youtube/video-timestampsPOST /youtube/video-transcript-languages
Request body:
{
"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"languages": ["en", "es"]
}languages is optional. Transcript requests try the requested languages first, then English if available, then the first available transcript language.
Example responses:
{
"title": "Video Title",
"author_name": "Channel Name",
"author_url": "https://www.youtube.com/@channel",
"type": "video",
"thumbnail_url": "https://i.ytimg.com/vi/example/hqdefault.jpg"
}{
"captions": "Transcript text..."
}{
"timestamps": ["0:00 - Intro", "0:05 - Next line"]
}{
"available_languages": [
{
"language": "English",
"language_code": "en",
"is_generated": false,
"is_translatable": true
}
]
}The /youtube/video-captions, /youtube/video-timestamps, and /youtube/video-transcript-languages routes return the raw captions string, timestamp list, and language list directly.
Server settings:
HOST, default0.0.0.0PORT, default8000RELOAD, defaultfalseLOG_LEVEL, defaultINFOBACKEND_CORS_ORIGINS, comma-separated origins, default*
Generic HTTP proxy for metadata/oEmbed requests:
ENABLE_PROXYPROXY_TYPEPROXY_HOSTPROXY_PORTPROXY_USERNAMEPROXY_PASSWORD
Webshare proxy for transcript requests:
WEBSHARE_PROXY_USERNAMEWEBSHARE_PROXY_PASSWORDWEBSHARE_PROXY_LOCATIONS, comma-separated, defaultde,us
Authentication is disabled by default:
ENABLE_AUTH=falseAUTH_TYPE=api_keyorjwtAPI_KEYJWT_SECRET_KEYJWT_ALGORITHMJWT_ACCESS_TOKEN_EXPIRE_MINUTES
When ENABLE_AUTH=true, video endpoints require either X-API-Key for API key auth or Authorization: Bearer <token> for JWT auth. /, /health, /docs, and /redoc remain public.
Health check:
curl -X GET "http://localhost:8000/health"Get captions:
curl -X POST "http://localhost:8000/video-captions" \
-H "Content-Type: application/json" \
-d '{"url":"https://www.youtube.com/watch?v=dQw4w9WgXcQ","languages":["en"]}'List transcript languages:
curl -X POST "http://localhost:8000/youtube/video-transcript-languages" \
-H "Content-Type: application/json" \
-d '{"url":"https://www.youtube.com/watch?v=dQw4w9WgXcQ"}'Use API key auth:
curl -X POST "http://localhost:8000/video-data" \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{"url":"https://www.youtube.com/watch?v=dQw4w9WgXcQ"}'Run unit and API tests:
python -m pytestRun endpoint checks against a running server:
./test_endpoints.sh http://localhost:8000youtube-api-server/
+-- app/
| +-- core/config.py
| +-- main.py
| +-- middleware/
| +-- models/youtube.py
| +-- routes/youtube.py
| +-- utils/youtube_tools.py
+-- tests/
+-- Dockerfile
+-- docker-compose.yml
+-- load_env.py
+-- requirements.txt
+-- test_endpoints.sh