Skip to main content

Download Twitch VOD metadata, video and chat

Project description

twitch-vod-lib

Python License: MIT Tests Code style: ruff Type checked: mypy PRs Welcome

A clean Python library for downloading Twitch VOD metadata, video files, and chat logs.

Features

  • Fetch VOD metadata via Twitch Helix API
  • Download video via yt-dlp (supports quality selection, cookies for sub-only VODs)
  • Download full chat replay via Twitch GQL with pagination, deduplication and caching
  • Structured logging (stdlib or structlog)
  • Retry logic with exponential back-off on transient errors
  • File-based caching — re-running skips already completed work
  • Config from environment variables, dict, or YAML (bring your own loader)

Requirements

Installation

Poetry (recommended)

git clone https://github.com/sontiago/twitch-vod-lib.git
cd twitch-vod-lib
poetry install                   # installs main deps
poetry install --with dev        # installs dev deps (pytest, ruff, mypy)

Copy the env file and fill in your credentials:

cp .env.example .env
# edit .env — set TWITCH_CLIENT_ID and TWITCH_CLIENT_SECRET

Run the library:

poetry run python your_script.py

pip (alternative)

pip install -e ".[dev]"

Quick start

from twitch_vod import TwitchVodClient, TwitchConfig

# Reads TWITCH_CLIENT_ID and TWITCH_CLIENT_SECRET from environment
with TwitchVodClient() as client:
    vod = client.get_latest_vod("xqcow")
    print(f"VOD: {vod.title}  ({vod.duration / 3600:.1f}h)")

    video_path = client.download_video(vod.id, quality="720p")
    messages   = client.download_chat(vod.id, vod_duration=vod.duration)

    print(f"Downloaded {len(messages)} chat messages → {video_path}")

Or use the one-shot helper:

vod, video_path, messages = client.fetch_all("xqcow", quality="480p")

Environment variables

Copy .env.example to .env and fill in your values (use python-dotenv or export manually):

Variable Required Default Description
TWITCH_CLIENT_ID Twitch app client ID
TWITCH_CLIENT_SECRET Twitch app client secret
TWITCH_USER_ACCESS_TOKEN "" User token for sub-only VODs
TWITCH_COOKIES_FILE None Path to Netscape cookies file
TWITCH_DOWNLOAD_QUALITY best best, 1080p60, 1080p, 720p60, 720p, 480p, worst
TWITCH_OUTPUT_DIR output/raw Directory for video and chat files
TWITCH_API_TIMEOUT 30 HTTP timeout in seconds
TWITCH_API_RETRIES 3 Number of retry attempts
TWITCH_CHAT_MAX_PAGES 10000 Hard cap on GQL pagination pages
TWITCH_CHAT_RATE_LIMIT_MIN 0.05 Min sleep between GQL pages (s)
TWITCH_CHAT_RATE_LIMIT_MAX 0.5 Max sleep between GQL pages (s)
LOG_LEVEL INFO DEBUG, INFO, WARNING, ERROR

Configuration from dict / YAML

import yaml
from twitch_vod import TwitchVodClient, TwitchConfig

with open("config.yaml") as f:
    raw = yaml.safe_load(f)

cfg = TwitchConfig.from_dict(raw["twitch"])
client = TwitchVodClient(cfg)

Example config.yaml:

twitch:
  client_id: abc123
  client_secret: secret
  download_quality: 720p
  output_dir: data/raw

Project layout

twitch_vod/
├── __init__.py          # Public API: TwitchVodClient, TwitchConfig, VODInfo, ChatMessage
├── client.py            # TwitchVodClient — façade / entry point
├── config.py            # TwitchConfig — env-based configuration
├── api/
│   ├── helix_client.py  # Twitch Helix REST API (auth, VOD metadata)
│   └── gql_client.py    # Twitch GQL (chat pagination)
├── downloader/
│   ├── video.py         # yt-dlp wrapper
│   └── chat.py          # GQL chat downloader with caching
├── models/
│   ├── vod.py           # VODInfo dataclass
│   └── chat.py          # ChatMessage dataclass
└── utils/
    └── logger.py        # Structured logging (structlog / stdlib)

Running tests

pytest # or poetry run pytest

With coverage:

pytest --cov=twitch_vod --cov-report=term-missing

Linting & type-checking

ruff check .
mypy ./

Caching behaviour

File When created Skip condition
output/raw/{vod_id}.mp4 download_video() File exists and > 1 MB
output/raw/{vod_id}_chat.json download_chat() File exists

Delete the relevant file to force a re-download.

License

MIT

Known issues

Chat pagination may miss messages in high-traffic streams

The Twitch GQL API paginates chat by contentOffsetSeconds, meaning each page is fetched starting from the timestamp of the last seen message.

This approach has a fundamental limitation:

  • The API returns messages matching ts >= offset
  • Multiple messages can share the same ts (same second)
  • If more messages exist within a single second than the page size allows, the overflow messages will never appear in any subsequent page request

Deduplication by message id prevents duplicates but cannot recover messages that were never returned by the API in the first place.

In practice this means very popular streams (e.g. large hype moments with thousands of messages per second) may have small gaps in the chat log. This is a limitation of the Twitch GQL API itself, not of this library.

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

twitch_vod_lib-1.0.0.tar.gz (15.7 kB view details)

Uploaded Source

Built Distribution

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

twitch_vod_lib-1.0.0-py3-none-any.whl (18.3 kB view details)

Uploaded Python 3

File details

Details for the file twitch_vod_lib-1.0.0.tar.gz.

File metadata

  • Download URL: twitch_vod_lib-1.0.0.tar.gz
  • Upload date:
  • Size: 15.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.0.1 CPython/3.13.1 Darwin/24.6.0

File hashes

Hashes for twitch_vod_lib-1.0.0.tar.gz
Algorithm Hash digest
SHA256 98aa16498893880bfc27f7a68175ba7185e280ea4e8cc6ba20fef4370cc353c4
MD5 59b9e1c293a6a64e73755bfa8f0d98c3
BLAKE2b-256 227e5ec0ad1a6b1058a08d26116fdc5dc31712d8640b1cc32d17e78507bca0b6

See more details on using hashes here.

File details

Details for the file twitch_vod_lib-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: twitch_vod_lib-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 18.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.0.1 CPython/3.13.1 Darwin/24.6.0

File hashes

Hashes for twitch_vod_lib-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1a6aa7621f4e20e598af98eb830ee83c8e2a276ef8bfc3100aedadc00feb189c
MD5 85db47a8d1fc8f42d6d18acf4c3fbbb1
BLAKE2b-256 7cea74a644c83d4a783e8b9ec500a02fa98650d2fa0820b46f96ac16a6f22b9f

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