Methodology
How we count watch hours
For each tracked Twitch channel, we poll Twitch Helix once per minute during match windows and record the concurrent viewer count. Watch hours are concurrent_viewers × 1 minutesummed across a match, divided by 60. Match windows come from Riot's LoL Esports schedule API, refreshed every minute via /getLive so the LIVE flag flips within ~60s of kickoff.
For tracked YouTube channels broadcasting live, we poll the YouTube Data API every 5 minutes instead of every minute - a quota constraint. Watch hours are computed the same way: concurrent_viewers × 5 minutes summed across a match, divided by 60. If a channel runs multiple simultaneous live broadcasts (rare alt-cam or multi-camera setups), we record only the highest-viewer broadcast per tick and drop the rest.
We track Twitch and YouTube independently. The homepage shows a Twitch table keyed by streamer and a YouTube table keyed by channel; we don't roll YouTube watch hours into a per-streamer aggregate or report a joined cross-platform total. Each platform's numbers stand alone, with separate methodology.
How channels enter the tracked roster
We track channels two ways: manual seeding via YAML config, or automated discovery followed by LLM-based promotion review.
The automated pipeline covers both platforms:
- Twitch. A discovery cron monitors channels broadcasting LoL content during match windows and queues them as candidates.
- YouTube. During live match windows, a search-based discoverer queries the YouTube Data API for live LoL broadcasts and queues any channel above the minimum CCV floor as a candidate. Outside live windows the job is a no-op to preserve API quota.
Every 30 minutes, a promotion job reviews PENDING candidates using Claude Sonnet. It issues a verdict - PROMOTE, IGNORE, or SKIP - with a confidence level (high / med / low). A candidate is promoted into the tracked roster only if:
- Peak concurrent viewers ≥ 500 at the time of discovery
- LLM confidence is medium or high (low-confidence verdicts are never acted on)
- LLM verdict is PROMOTE (not IGNORE or SKIP)
When a Twitch co-streamer is promoted, the pipeline immediately searches for their YouTube channel - one YouTube Data API search call, linked automatically if the match is high-confidence. This cross-platform link is best-effort: errors are caught and don't roll back the Twitch promotion.
Official broadcast channels (Riot-owned or Riot-affiliated league channels, flagged is_official: true) are seeded manually and never enter the candidate queue - they are always tracked regardless of CCV. Official channels are excluded from co-stream share calculations; peak viewer figures on the trend chart are derived from official channels only.
What's not in this dataset
Co-stream share figures and watch-hour totals on this site reflect what we directly observe. These categories are deliberately excluded - read before drawing conclusions about any event.
- Asian streaming platforms not yet tracked. We currently ingest only Twitch and YouTube. Naver, AfreecaTV, Bilibili, and Huya are not polled, so any co-stream share % we report for LCK, LPL, Worlds, or MSI understates the true co-streamed audience by an unknown but material margin. This is the highest-impact omission in the dataset.
- Inter-match hours excluded from per-event totals.Minutes where a tracked channel was classified as co-streaming but couldn't be pinned to a specific match (pre-game shows, between-series breaks, ambiguous broadcasts) are reported per channel as inter_match_hours and excluded from headline event watch-hour totals.
- Per-sample attribution cutover on 2026-04-26. Samples written before this date use a looser legacy time-window-overlap method; samples after use stricter per-sample classification. Figures that span the cutover compare a stricter post-period against a looser pre-period - see Per-sample match attribution for details.
Coverage log
Dated milestones in what this dataset covers. Oldest first.
- 2026-04-25 - Twitch live ingestion begins.
- 2026-04-26 - per-sample match attribution cutover.
- 2026-04-29 - YouTube live concurrent-viewer ingest and Twitch VOD view-count ingest go live.
- 2026-05-01 - automated co-streamer discovery and LLM-based auto-promotion pipeline goes live for both Twitch and YouTube. From this date the tracked roster grows autonomously; channels promoted before this date were manually seeded.
- 2026-05-01 - YouTube live candidate discovery (live-window-gated YouTube search) goes live.
- 2026-05-02 - is_official tagging corrected for several regional channels. cblol, lolesportsla, lolesportstw, lolesportsjp, lckcl, lolpacificen, and lolpcstw were incorrectly marked as co-streamers and are now correctly tagged as official broadcast channels. lolthek4sen (a Riot-supported streamer tournament, not a Riot-owned broadcast) was flipped to co-streamer. Watch-hour samples attributed before this date may have counted official channels toward co-stream share or vice versa.
Per-sample match attribution
When two leagues run concurrently - common on LCK/LPL/LEC weekends - a single co-streamer's minute can overlap multiple match windows at once. From 2026-04-26onwards, every viewer sample is classified by Claude Haiku against the set of currently-live tracked matches and attributed to at most one. Samples the classifier flagged as co-streaming but couldn't pin to a specific match (pre-game, breaks, ambiguous broadcasts) are reported per channel as inter_match_hours on the event API and excluded from the headline watch-hour total. Samples written before the cutover still use the legacy time-window-overlap method, so figures spanning the cutover compare a stricter post-period against a looser pre-period.
YouTube highlight VODs
For YouTube highlight VODs we report a view-hours estimate as views × match_duration × retention(match_duration), where match_duration is the estimated length of the covered match(es) based on best-of format - not the raw video length. A 10-hour co-stream VOD covering one BO3 uses 2.5 h, not 10 h. The retention coefficient is bucketed by this effective match duration:
- < 10 min → 0.50 (short recaps and shorts-style clips tend to be watched closer to completion)
- 10–60 min → 0.25 (highlight reels and segment edits)
- ≥ 60 min → 0.10 (full-broadcast VODs - long tail rarely finishes)
These figures are estimates drawn from published YouTube retention research, not per-channel measurements. They're assumptions that matter, and we'll revisit them once we gain per-channel YouTube Analytics access - until then, treat VOD-derived hours as directional rather than exact.
For tracked YouTube channels that publish per-match highlight VODs (the official broadcast channels and co-streamer mirrors in our YouTube inventory), we count viewership accrued within 7 days of match end. The 7-day window deliberately excludes long-tail rewatches so per-match value reflects the news cycle, not evergreen content.
View counts are snapshotted hourly for the first 24 hours after a VOD is published, then every 6 hours up to 7 days post-match. After the 7-day window we stop snapshotting, so values shown reflect the most recent snapshot taken within that window.
View tracking begins from the moment our pipeline first samples a newly-uploaded VOD, not from the VOD's publication time. Discovery runs hourly, so up to 60 minutesof fresh-upload views may have accrued before our first sample - those views are not counted. We don't synthesise them; this follows our no-backfill rule.
Multi-match VODs (full-stream-day compilations - e.g. an official 5h LCK broadcast covering two matches) are credited to each covered match in proportion. Currently we split watch-hours uniformly: a 2-match VOD contributes 50% of estimated hours-watched to each match. The headline-vs-undercard skew this misses is a known limitation we plan to address once we have view-count comparisons across single-match siblings.
Twitch VODs
From 2026-04-29 onwards, for Twitch broadcasts that overlap a tracked match we ingest and snapshot the auto-recorded VOD on the same cadence as YouTube (hourly for the first 24 hours, every 6 hours thereafter, within a 7-day attribution window).
Twitch deletes non-highlighted VODs after 14 days for regular accounts (60 days for affiliates/partners), so any view-count tail beyond the platform's retention window is lost permanently. Our 7-day capture window is a tighter ceiling than the equivalent YouTube number - both reflect the news cycle rather than evergreen views, but Twitch VODs are less complete for channels that don't highlight their broadcasts. Matches before 2026-04-29 carry no Twitch-VOD contribution to vod_hours_watched; this is consistent with the project's no-backfill rule.
Total reach
total_reachis our cross-platform headline metric for a match: cumulative live + replay impressions summed across the match's Twitch and YouTube VODs. For each attributed VOD we take the latest view_count snapshot whose timestamp is between match_end and match_end + 7 days(inclusive on both ends), multiply by the VOD's weight (a multi-match VOD splits its reach across the matches it covers), and sum across the contributing VODs. The same value rolls up to EventMetric.total_reach per channel.
The two platforms count an “impression” differently, and this matters for how you read the number. Twitch counts any VOD play, including silent autoplay and short bounces; YouTube generally only counts views after roughly 30 seconds of intentional playback. So Twitch contributions skew higher per impression while YouTube contributions skew toward genuinely-engaged viewers. Treat total_reach as a directional cross-platform indicator rather than an apples-to-apples viewer count.
Once a match's 7-day window closes, snapshotting stops and the total_reach value is frozen. Matches you check more than 7 days after kickoff report the same number every time - long-tail rewatch is deliberately excluded so per-match reach reflects the news cycle rather than evergreen views.
On the events page the column shows four states:
- Numeric (1.2M, 340K) - both platforms have an attributed VOD contributing.
- Numeric with asterisk (340K*) - partial coverage: only one platform's VOD is attributed; the other is missing or still in review. The asterisk warns that the value reflects only the attributed platform.
- Em-dash (-) - no attributed VOD on either platform yet, so we have no data to report. This is distinct from a real zero - we never synthesise a number we didn't observe.
- “Pre-collection era” badge- the match ended before our 2026-04-25 collection-start cutoff. Per the no-backfill rule, we don't reconstruct reach for matches we weren't observing live, so these rows never carry a numeric value.
Known limitations
- Attribution for a channel streaming LoL during a match window is heuristic - we flag ambiguous cases for manual review.
Data quality log
Known collection gaps and operational incidents are listed on the status page. Per the no-backfill rule, gaps are real and will not be synthesised — surfacing them is part of being honest about what this dataset measures.