Without jitter, multiple concurrent instances that hit the same transient error will wake up and retry simultaneously, creating a stampede. Adding up to 0.5 s of uniform random jitter spreads the retries out without meaningfully increasing average wait time. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Chat Downloader
chat-downloader-2026 is a maintained fork of
xenova/chat-downloader for
retrieving chat messages from YouTube and Twitch. It supports CLI usage, a
small Python API, multiple output formats, and focused tooling for debugging
parser changes.
This fork targets Python 3.10+ and keeps the project source-compatible for users who already know the upstream package, while improving typing, testing, Twitch coverage, and internal maintainability.
Highlights
- Download chat from YouTube and Twitch URLs through one interface.
- Use the CLI or embed the library in Python code.
- Write to
json,jsonl,csv, andtxt. - Attach more than one output at the same time with repeated
--output. - Supply cookies, proxy settings, custom headers, and a custom user agent when the platform requires them.
- Filter by time range, message groups, message types, and message limits.
- Use typed request/config dataclasses:
ChatRequestandDownloaderConfig.
Installation
Install from a local checkout:
python3 -m pip install .
For development work:
python3 -m pip install -e ".[dev]"
Quick Start
Print messages to stdout:
chat_downloader "https://www.youtube.com/watch?v=jfKfPfyJRdk" --max_messages 20
Capture a Twitch VOD to JSONL:
chat_downloader "https://www.twitch.tv/videos/123456789" \
--output vod-chat.jsonl \
--max_messages 500
Write the same run to two formats:
chat_downloader "https://www.youtube.com/watch?v=jfKfPfyJRdk" \
--output chat.jsonl \
--output chat.txt
Use cookies and custom headers:
chat_downloader "https://www.youtube.com/watch?v=jfKfPfyJRdk" \
--cookies cookies.txt \
--request_profile youtube_android \
--header "Accept-Language: en-US,en;q=0.9"
Enable automatic YouTube profile fallback on incomplete continuations:
chat_downloader "https://www.youtube.com/watch?v=jfKfPfyJRdk" \
--request_profile youtube_web \
--auto_profile_fallback true
Restrict output to a time window:
chat_downloader "https://www.youtube.com/watch?v=jfKfPfyJRdk" \
--start_time 00:10:00 \
--end_time 00:12:30
Python API
The simplest entry point is ChatDownloader.get_chat():
from chat_downloader import ChatDownloader
downloader = ChatDownloader()
chat = downloader.get_chat(
"https://www.youtube.com/watch?v=jfKfPfyJRdk",
max_messages=10,
)
for message in chat:
print(message["author"]["name"], ":", message["message"])
You can also use the typed request objects exposed by the package:
from chat_downloader import ChatDownloader, ChatRequest, DownloaderConfig
config = DownloaderConfig(cookies="cookies.txt", read_timeout=45.0)
request = ChatRequest(
url="https://www.twitch.tv/videos/123456789",
max_messages=100,
output=["chat.jsonl", "chat.txt"],
)
downloader = ChatDownloader(**config.as_dict())
chat = downloader.get_chat(**request.to_legacy_kwargs())
for message in chat:
pass
For the current export list and dataclass details, see
docs/python-api-reference.md.
Output Formats
| Format | Notes |
|---|---|
json |
Final JSON array written on close. Best for finite captures. |
jsonl |
One JSON object per line. Best for long or live captures. |
csv |
Flattens nested fields and rewrites the file when new columns appear. |
txt |
Applies the configured message formatter. |
When a live capture targets a .json path, the runtime upgrades it to .jsonl
so the output stays crash-safe. Pass --format json to keep JSON-array output
for live captures.
Supported Platforms
| Platform | Current focus |
|---|---|
| YouTube | Live chat, replay chat, URL discovery, optional cookies/auth headers |
| Twitch | Live IRC chat, VOD chat, clip/VOD metadata lookups, richer notice parsing |
Support still depends on the platform exposing chat data. Subscriber-only, login-gated, or platform-throttled content may require cookies or may not be accessible.
CLI Notes
Run chat_downloader --help for the complete argument list. Common flags:
--message_groupsor--message_typesto filter events.--formator--format_fileto change rendered text output.--outputto write one or more files.--timeoutand--inactivity_timeoutto bound long-running captures.--proxy,--cookies,--user-agent, and--headerfor request control.--request_profileto apply Grayjay-inspired request header presets.--auto_profile_fallbackto rotate YouTube request profiles when continuation payloads are repeatedly incomplete.--logging debugor--verbosefor transport/parser debugging.
Documentation Map
docs/python-api-reference.md: public Python API and typed dataclass referencedocs/developer-workflow-guide.md: development workflow, commands, and contributor notesdocs/youtube-integration-guide.md: current YouTube capture flow and module mapdocs/twitch-integration-guide.md: current Twitch capture flow and transport mapdocs/compatibility-and-deprecation-policy.md: compatibility surfaces and target retirement datesCLAUDE.md: maintainer-oriented architecture and workflow notes
Troubleshooting
403,429, orLoginRequirederrors usually mean the platform wants cookies, a slower request pace, or both.- Use
jsonlfor long or live captures; plainjsonis finalized only when the writer closes cleanly. - If a platform changes its private APIs, run again with
--logging debugand review the site-specific code underchat_downloader/sites/. - Network tests are opt-in. The default local and CI path is the offline test suite.
Development
See docs/developer-workflow-guide.md for the canonical development
workflow, commands, and contributor guidance.
Credits
- Original project:
xenova/chat-downloader - Maintained fork:
farrakhan1986