Skip to content

InnerTube API for YouTube LiveChat to get Live Chat messages without API restrictions. Mainly intended for use in application for the streamer. Supports AOT.

License

Notifications You must be signed in to change notification settings

Agash/YTLiveChat

Repository files navigation

YTLiveChat

Unofficial .NET library for reading YouTube live chat via InnerTube (the same web-facing surface YouTube uses), without Data API quotas or OAuth setup.

GitHub Actions Workflow Status NuGet Version NuGet Version License: MIT

Targets

  • net10.0
  • netstandard2.1
  • netstandard2.0

Install

Core package:

dotnet add package Agash.YTLiveChat

With DI helpers:

dotnet add package Agash.YTLiveChat.DependencyInjection

What You Get

  • Chat messages (liveChatTextMessageRenderer)
  • Super Chats / Super Stickers with parsed amount + currency
  • Membership events (new/milestone/gift purchase/gift redemption)
  • Ticker support (addLiveChatTickerItemAction) including:
    • ticker paid messages
    • ticker membership items
    • ticker gift purchase announcements
  • Viewer leaderboard rank extraction (YouTube points crown tags like #1)
  • Raw InnerTube action access (RawActionReceived) including unsupported actions
  • Async streaming APIs (StreamChatItemsAsync, StreamRawActionsAsync)

Important Caveats

  • This is an unofficial parser over YouTube’s internal schema. Payloads can change at any time.
  • This library reads chat only (no sending messages).
  • Respect request frequency to avoid rate limits or temporary blocks.

Beta API Notice

Continuous livestream monitor mode is currently BETA/UNSUPPORTED and can change or break at any time:

  • YTLiveChatOptions.EnableContinuousLivestreamMonitor
  • YTLiveChatOptions.LiveCheckFrequency
  • IYTLiveChat.LivestreamStarted
  • IYTLiveChat.LivestreamEnded

These members intentionally emit compiler warnings via [Obsolete] to signal unstable API status.

Quick Start (DI)

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using YTLiveChat.Contracts;
using YTLiveChat.Contracts.Services;
using YTLiveChat.DependencyInjection;

HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddYTLiveChat(builder.Configuration);

builder.Services.Configure<YTLiveChatOptions>(options =>
{
    options.RequestFrequency = 1000;
    options.DebugLogReceivedJsonItems = true;
    options.DebugLogFilePath = "logs/ytlivechat_debug.json";
});

builder.Services.AddHostedService<ChatWorker>();
await builder.Build().RunAsync();

Worker example:

using YTLiveChat.Contracts.Models;
using YTLiveChat.Contracts.Services;

public sealed class ChatWorker(IYTLiveChat chat) : IHostedService
{
    public Task StartAsync(CancellationToken ct)
    {
        chat.InitialPageLoaded += (_, e) => Console.WriteLine($"Loaded: {e.LiveId}");
        chat.ChatReceived += (_, e) => HandleChat(e.ChatItem);
        chat.RawActionReceived += (_, e) =>
        {
            if (e.ParsedChatItem is null)
            {
                // Unsupported action still available here
                Console.WriteLine("RAW action received.");
            }
        };
        chat.ChatStopped += (_, e) => Console.WriteLine($"Stopped: {e.Reason}");
        chat.ErrorOccurred += (_, e) => Console.WriteLine($"Error: {e.GetException().Message}");

        chat.Start(handle: "@channelHandle");
        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken ct)
    {
        chat.Stop();
        return Task.CompletedTask;
    }

    private static void HandleChat(ChatItem item)
    {
        // inspect item.Superchat / item.MembershipDetails / item.ViewerLeaderboardRank / item.IsTicker
    }
}

Async Streaming APIs

await foreach (ChatItem item in chat.StreamChatItemsAsync(handle: "@channel", cancellationToken: ct))
{
    Console.WriteLine($"{item.Author.Name}: {string.Join("", item.Message.Select(ToText))}");
}

await foreach (RawActionReceivedEventArgs raw in chat.StreamRawActionsAsync(liveId: "videoId", cancellationToken: ct))
{
    if (raw.ParsedChatItem is null)
    {
        Console.WriteLine(raw.RawAction.ToString());
    }
}

static string ToText(MessagePart part) => part switch
{
    TextPart t => t.Text,
    EmojiPart e => e.EmojiText ?? e.Alt ?? "",
    _ => ""
};

Raw JSON Capture for Schema Analysis

Enable:

options.DebugLogReceivedJsonItems = true;
options.DebugLogFilePath = "logs/ytlivechat_debug.json";

The file is written as a valid JSON array, so it is directly parseable by tools/scripts.

Example App

YTLiveChat.Example includes:

  • UTF-8 console setup for multilingual output
  • colorized one-line TUI rendering
  • rank/ticker/membership/superchat tagging
  • unsupported raw action hints
  • optional raw JSON capture prompt
  • optional continuous monitor mode prompt (beta)

Current Schema Coverage Gaps

  • Poll update/action-panel payloads are captured in tests as raw fixtures, but not yet projected into first-class contracts.
  • Creator goals are not mapped yet (awaiting enough stable raw samples).

Contributing

Bug reports and raw payload samples are highly valuable.
If you add parser support for new payloads, include:

  • response model updates in YTLiveChat/Models/Response/LiveChatResponse.cs
  • parser updates in YTLiveChat/Helpers/Parser.cs
  • tests + fixtures in YTLiveChat.Tests

License

MIT. See LICENSE.txt.

About

InnerTube API for YouTube LiveChat to get Live Chat messages without API restrictions. Mainly intended for use in application for the streamer. Supports AOT.

Topics

Resources

License

Stars

Watchers

Forks

Sponsor this project

 

Packages

No packages published

Contributors 3

  •  
  •  
  •  

Languages