Youtube Live Chat Scraper avatar

Youtube Live Chat Scraper

Pricing

from $1.00 / 1,000 chat events

Go to Apify Store
Youtube Live Chat Scraper

Youtube Live Chat Scraper

YouTube Live Chat Scraper extracts live chat from YouTube live streams and replays. Supports full replay chat (most reliable) and best-effort live polling. Outputs messages with timestamps, authors, badges (owner/mod/member), Super Chats/Stickers, and stream metadata for analytics and AI.

Pricing

from $1.00 / 1,000 chat events

Rating

5.0

(1)

Developer

Delowar Munna

Delowar Munna

Maintained by Community

Actor stats

3

Bookmarked

122

Total users

14

Monthly active users

17 days ago

Last modified

Share

YouTube Live Chat & Replay Scraper — Super Chats, Memberships, No API Key

Scrape YouTube live chat and full chat replays — from streams airing right now, from streams that ended months ago, or from an entire channel by handle. Messages, Super Chats, memberships, moderation events, badges and timestamps, as a clean one-row-per-event dataset.

No API key. No login. No browser.

YouTube Live Chat Scraper Banner


⚡ Quick start

  1. Paste a YouTube live stream or replay URL into Video URLs or IDs.
  2. Leave Extraction mode on Replay.
  3. Click Start.
{
"videoRefs": ["https://www.youtube.com/watch?v=BZ_UzbpMjMg"],
"mode": "replay"
}

That's it — every chat message from that stream lands in your dataset, ready to export as CSV, JSON or Excel.


Why not just use the official YouTube API?

This is the core reason this Actor exists.

Official YouTube Data API v3This Actor
Chat from a stream that already endedNot possible at all✅ Full replay, first message to last
Chat from a live stream🟡 Yes, but needs OAuth + a liveChatId you must find yourself✅ Paste the watch URL
Your own API key required✅ Required❌ Not needed
Daily quota limits✅ 10,000 units/day❌ None
Super Chat amounts & currency🟡 Limited✅ Amount, currency and tier colour
Moderation & deleted-message events
Find streams from just a channel handle✅ Channel discovery

The official API genuinely cannot return chat from an ended broadcast — the endpoint only serves currently-active chats. That is the gap this Actor fills.


Live vs Replay — which mode do I want?

Replay mode (default)Live mode
Use it forStreams that have endedStreams airing right now
What you getThe complete chat historyOnly messages posted while the run is active
CompletenessEverything, first to lastWhatever arrives during your capture window
ReliabilityHighest — recommendedBest-effort polling
Typical useAnalytics, revenue reports, research, ML datasetsLive monitoring, event dashboards
RequirementChat replay must still be enabled on the videoStream must be live now

💡 If in doubt, use Replay. Live mode on an ended stream returns nothing.


What you can do with it

  • Find the moments that mattered — every event carries videoOffsetText, its exact position in the recording. Sort by it, spot where chat spiked, and jump straight to 1:23:45 in the video. This is what turns a chat log into highlight detection.
  • Revenue tracking — every Super Chat with amount, currency and the message that came with it, plus a numeric superChatAmountValue you can sum directly.
  • Moderation auditing — deleted messages, banned users and auto-mod actions. No other Actor surfaces these.
  • Audience research — find the moments a chat exploded, and what people were saying.
  • Community monitoring — hand it a channel @handle and it tracks that creator's streams for you.
  • AI / NLP datasets — clean, structured conversational data with emoji runs preserved.
  • Campaign measurement — capture audience reaction during a sponsored stream or product launch.

Input

Provide videos, channels, or both. At least one is required.

Example 1 — a single replay

{
"videoRefs": ["https://www.youtube.com/watch?v=BZ_UzbpMjMg"],
"mode": "replay",
"maxMessagesPerVideo": 5000
}

Example 2 — Super Chats only (cheapest monetization export)

Turn off normal messages and you are charged only for the paid events, not the thousands of ordinary ones scraped along the way.

{
"videoRefs": ["https://www.youtube.com/watch?v=BZ_UzbpMjMg"],
"mode": "replay",
"includeNormalMessages": false,
"includeSuperChats": true,
"includeMembershipEvents": true,
"maxMessagesPerVideo": 0
}

Example 3 — track a whole channel, with a hard spend ceiling

{
"channelRefs": ["@LofiGirl"],
"channelDiscoveryMode": "current_live_then_replays",
"maxVideosPerChannel": 5,
"lookbackDays": 30,
"mode": "replay",
"maxTotalItems": 5000
}

💡 Match the discovery mode to the channel. current_live_then_replays suits channels that are often live; use latest_replays_only for channels whose streams have ended.

Key input fields

FieldDefaultWhat it does
videoRefs[]Watch URLs, short URLs, or bare 11-character video IDs
channelRefs[]Channel @handle, channel URL or UC… ID — the Actor finds the streams
modereplayreplay (ended streams) or live (airing now)
maxMessagesPerVideo5000Per-video cap. 0 = the entire chat replay
maxTotalItems0Hard ceiling for the whole run. 0 = no limit
maxTimePerVideoSecs600Give up on one video after this long
includeNormalMessagestrueTurn off for a monetization-only export
includeSuperChatstrueSuper Chats and Super Stickers, with amounts
includeMembershipEventstrueJoins, renewals and gifted memberships
includeModerationEventstrueDeletions, bans, auto-mod and system notices

Channel discovery, live-mode timing, localization and reliability tuning have their own sections in the input form — every field there carries an inline explanation and example.


Output

One dataset row per chat event. Flat and spreadsheet-safe — export straight to CSV, JSON, Excel or pull it from the API.

Event types: message, super_chat, super_sticker, membership, moderation, system, error

Dataset views

The dataset ships with three ready-made table views you can switch between in the Apify console or the API:

  • Chat Events — the everyday view: who said what, when, and how far into the stream.
  • Super Chats & Memberships — a monetization view with numeric amounts, currencies and membership tiers.
  • All Fields — every column.

Output example — a chat message

A real record from a replay run (the channel owner posting three custom channel emotes — note isOwner: true, and messageParts preserving each emote as a structured run with its image URL rather than flattening to text):

{
"videoId": "BZ_UzbpMjMg",
"videoUrl": "https://www.youtube.com/watch?v=BZ_UzbpMjMg",
"videoTitle": "Crypto Cypher Live Stream...3/9/26...Bear Market wk 23...Weekend Trap...",
"channelId": "UCrmxhDnT1xyCzYJ2dwM9Ikg",
"channelTitle": "Crypto Cypher",
"channelUrl": "https://www.youtube.com/channel/UCrmxhDnT1xyCzYJ2dwM9Ikg",
"streamStatus": "replay",
"streamStartedAt": "2026-03-09T22:05:58.179Z",
"streamEndedAt": null,
"eventType": "message",
"messageId": "ChwKGkNLM1hyLVhwazVNREZRYTdyZ1Vkd0VzNGxB",
"seq": 5,
"publishedAt": "2026-03-09T22:06:17.322Z",
"timestampUsec": 1773093977322079,
"videoOffsetMsec": 19507,
"videoOffsetText": "0:19",
"authorChannelId": "UCrmxhDnT1xyCzYJ2dwM9Ikg",
"authorName": "@TheCypherbyDbloc",
"authorHandle": "@TheCypherbyDbloc",
"authorProfileUrl": "https://www.youtube.com/channel/UCrmxhDnT1xyCzYJ2dwM9Ikg",
"authorPhotoUrl": "https://yt4.ggpht.com/fidZVQwGqkP5zXR0VVCIlzeQon-agYmZh2fw1jty54T7vSc5NPwhHuATyTjDCZPsU6vo77tlUVU=s32-c-k-c0x00ffffff-no-rj",
"authorBadges": ["OWNER"],
"isOwner": true,
"isModerator": false,
"isMember": false,
"isVerified": false,
"messageText": ":_win::_bitcoin::_cypher:",
"messageParts": [
{ "type": "emoji", "emojiId": "UCrmxhDnT1xyCzYJ2dwM9Ikg/xox4Z52iLaC8_9EP-YPL6A4", "text": ":_win:", "url": "https://yt3.ggpht.com/ulTHwdn0lVK5j3uxS2CzVHBDSRAJ6y1jVvXKS-LRgsu-RvebcyOwtsxGYwgMRKNrKiSatOT9Cg=w24-h24-c-k-nd" },
{ "type": "emoji", "emojiId": "UCrmxhDnT1xyCzYJ2dwM9Ikg/6ll4Z9eqB7i8_9EP297ouQk", "text": ":_bitcoin:", "url": "https://yt3.ggpht.com/aw_Gs1YIT5z58TOb0veJic2Zt3TSwfVDNmE9RvEMOtJXnNsKgGS42_Bs9-Ffv55hmSjzJp8KYw=w24-h24-c-k-nd" }
],
"superChatAmount": null,
"superChatAmountValue": null,
"superChatCurrency": null,
"superChatColor": null,
"membershipLevel": null,
"moderationAction": null,
"language": "en",
"regionCode": "US",
"retrievedAt": "2026-07-25T07:23:11.961Z",
"runId": "VBUnU0k5ldRqViLxQ",
"discoverySource": "direct_videoRef",
"channelRef": null,
"discoveredAt": null,
"isDiscoveredLive": null,
"isDiscoveredUpcoming": null
}

Output example — a Super Chat

The same run also captured this $5 Super Chat. Note superChatAmountValue: 5 (a number you can SUM()), the split currency, and videoOffsetText: "2:10:19"jump straight to 2:10:19 in the video to see the moment it was sent:

{
"videoId": "BZ_UzbpMjMg",
"videoTitle": "Crypto Cypher Live Stream...3/9/26...Bear Market wk 23...Weekend Trap...",
"channelTitle": "Crypto Cypher",
"streamStatus": "replay",
"eventType": "super_chat",
"seq": 554,
"publishedAt": "2026-03-10T00:16:17.553Z",
"videoOffsetMsec": 7819483,
"videoOffsetText": "2:10:19",
"authorName": "@matiss6895",
"authorHandle": "@matiss6895",
"authorProfileUrl": "https://www.youtube.com/channel/UCb51Z-DWlNJdqkV4xNNskuA",
"authorBadges": ["MEMBER"],
"isMember": true,
"messageText": "d bloc!!!! when florida meet up? :smiling_face_with_halo:",
"messageParts": [
{ "type": "text", "text": "d bloc!!!! when florida meet up? " },
{ "type": "emoji", "emojiId": "😇", "text": ":smiling_face_with_halo:", "url": "https://fonts.gstatic.com/s/e/notoemoji/15.1/1f607/72.png" }
],
"superChatAmount": "$5.00",
"superChatAmountValue": 5,
"superChatCurrency": "USD",
"superChatColor": "#ff1de9b6",
"language": "en",
"regionCode": "US",
"retrievedAt": "2026-07-25T07:23:12.909Z",
"discoverySource": "direct_videoRef"
}

(Some always-null fields trimmed from the Super Chat example for brevity — the full row carries every column shown in the message example above.)

Output screenshot — All fields table view

YouTube Live Chat Scraper Output — All Fields Table View

Output fields

Stream context — so a multi-video export is readable without a join:

FieldTypeDescription
videoIdstringYouTube video ID
videoUrlstringCanonical watch URL
videoTitlestringTitle of the stream
channelIdstringChannel that owns the stream
channelTitlestringChannel display name
channelUrlstringCanonical channel URL
streamStatusstringlive, replay, ended, or unknown
streamStartedAtstring (ISO)When the broadcast started
streamEndedAtstring (ISO)When the broadcast ended

Event & timing — including the replay position:

FieldTypeDescription
eventTypestringmessage, super_chat, super_sticker, membership, moderation, system, error
messageIdstringStable message ID
seqintegerSequential index per video (1..N)
publishedAtstring (ISO)Wall-clock time the message was posted
timestampUsecintegerRaw microsecond timestamp
videoOffsetMsecintegerHow far into the recording the message appeared, in ms. Replay only
videoOffsetTextstringReadable form of the above, e.g. "1:23:45"
retrievedAtstring (ISO)When this Actor captured the event

Author:

FieldTypeDescription
authorChannelIdstringAuthor's channel ID
authorNamestringVisible author name — an @handle on most modern streams
authorHandlestringThe @handle, when the author name is one
authorProfileUrlstringClickable channel URL for the author
authorPhotoUrlstringAvatar URL
authorBadgesstring[]e.g. ["OWNER", "MODERATOR", "MEMBER"]
isOwner / isModerator / isMember / isVerifiedbooleanFilterable flags derived from the badges — you can't filter an array in Sheets, but you can filter a boolean

Content, money & moderation:

FieldTypeDescription
messageTextstringChat message text
messagePartsobject[]Structured runs (text + emojis, with emote image URLs)
superChatAmountstringAs displayed, e.g. "$5.00"
superChatAmountValuenumberNumeric value, e.g. 5 — use this to SUM() revenue
superChatCurrencystringe.g. "USD"
superChatColorstringTier colour
membershipLevelstringe.g. "Silver Member", when YouTube exposes it
moderationActionstringe.g. "AUTO_MOD"
language / regionCodestringLocale used for the request
runIdstringApify run ID
discoverySourcestringdirect_videoRef, channel_discovery_api, or channel_discovery_html
channelRefstring|nullChannel input that produced this video; null for direct videos
discoveredAtstring (ISO)|nullWhen the video was discovered; null for direct videos
isDiscoveredLiveboolean|nullWhether the video was live when discovered; null for direct videos
isDiscoveredUpcomingboolean|nullWhether the video was upcoming when discovered; null for direct videos

Why some fields are null on system events. system rows are YouTube's own notices (for example "Live chat replay is on"). They have no author, so the author fields are legitimately empty. Similarly, the four discovery fields are only populated for videos found via channel discovery — for videos you pass directly, discoverySource is direct_videoRef and those four are null. That is expected, not missing data.

Run summary

The Actor writes RUN_SUMMARY.json to the key-value store with per-video totals, errors, channel discovery results, and a truncation block telling you plainly whether a cap cut the run short.


💰 Pricing

Pay-per-event: one chat-event per dataset row, plus a small per-run start fee. You are charged for chat events actually returned — filtered-out and error rows are free.

Live mode adds a small per-minute capture charge (scaled by the run's memory) for the time it spends polling a live stream — this applies only while genuinely capturing a live stream, never in replay mode or when a live request falls back to replay for an ended stream. Replay runs are never charged for time.

Worked examples:

RunEventsWhat you pay
A 1,000-message replay1,0001,000 × the per-event rate
A 10,000-message replay10,00010× the above
Super-Chat-only export of a 50,000-message stream~200You pay for ~200 events, not 50,000
A stream with chat replay disabled0Only the small Actor-start fee

What is never charged:

  • Failed or empty runs return no chat events, so no per-event charge applies.
  • error rows are pushed to your dataset so you can see what went wrong — they are not billed.
  • Messages filtered out by your own toggles are never charged, because they are filtered before billing.

💡 Controlling spend: set Max total chat events (maxTotalItems) for one hard ceiling across the whole run. This matters most with channel discovery, where a handful of channels can expand into far more videos than you expected.

Live rates are on the Actor's Pricing tab — this README deliberately doesn't quote figures, so they can never go stale here.


How it works

  1. Channel discovery (when channelRefs is given) — resolves handles/URLs to channel IDs and finds live streams and replays, with an HTML fallback if the API path is unavailable.
  2. Token extraction — fetches the watch page and reads YouTube's innertube API key, context and chat continuation token.
  3. Chat pagination — walks the chat using continuation tokens (replay), or polls at your chosen interval (live).
  4. Normalization — maps YouTube's renderer types into a stable event schema.
  5. Output — pushes clean rows and writes RUN_SUMMARY.json.

Performance

  • Replay — around 5,000 messages in 1–5 minutes
  • Live — near real time, 1–10 second latency
  • Channel discovery — adds roughly 2–5 seconds per channel
  • Concurrency — up to 10 videos in parallel
  • HTTP-only — no browser overhead

FAQ

Can I get chat from a stream that already ended? Yes — that is the primary use case, and it is the thing the official YouTube API cannot do. Use replay mode. Chat replay must still be enabled on the video.

Do I need a YouTube API key? No. No API key, no OAuth, no login, no cookies.

Does it work on premieres? Yes, when the premiere had chat and chat replay is still enabled.

Why did my run return zero messages? Almost always because chat replay is turned off for that video, or the video never had a live chat (an ordinary upload). Check that the chat replay panel appears next to the video on YouTube. Age-restricted and private videos are also inaccessible.

Can I scrape a whole channel? Yes. Put a @handle or channel URL in Channel URLs or handles and the Actor discovers the streams itself — no need to know any video IDs.

How do I get only Super Chats? Set Include normal chat messages to false and leave Super Chats on. You are charged only for the paid events returned.

How do I stop a run getting expensive? Set Max total chat events (maxTotalItems). It is a hard ceiling for the entire run, across every video and channel.

Do failed or empty runs cost me anything? No per-event charge — you are only billed for chat events actually returned. Error rows are free.

How is live mode different from replay mode? Replay gives you the complete history of a finished stream. Live captures only what is posted while your run is active. See the comparison table above.

Does it work on members-only streams? Best-effort at most. Members-only chat sits behind a login this Actor does not have.

What formats can I export? JSON, CSV, Excel, XML, and RSS via the Apify dataset, or straight from the API. The schema is flat, so it opens cleanly in Google Sheets and Excel.

Can I run it on a schedule? Yes — use Apify Scheduler to re-run it, for example to check a channel for new streams each day.


Limitations

  • Chat replay must be enabled on the video.
  • Members-only chat behind authentication is best-effort.
  • Live mode is best-effort polling, not a websocket feed.
  • Age-gated, private or region-blocked content may be inaccessible.
  • Channel discovery depends on YouTube Data API quota and/or the channel's streams tab being available; it falls back to HTML automatically.
  • Live mode polls a genuinely-live stream for new messages over liveCaptureDurationSecs, capturing the current chat buffer plus messages as they arrive. If the stream has already ended, it automatically falls back to full replay extraction (so you always get data). replay mode remains the core of this Actor for complete historical chat. A never-ending stream (24/7 cam, lofi radio) has no complete history until it ends; to keep monitoring one, use a long liveCaptureDurationSecs or re-run on a schedule.
  • streamStartedAt / streamEndedAt are best-effort. When YouTube omits them from the page they are reconstructed from chat timing (accurate to a few seconds); streamEndedAt is only available when a replay is read to the end, not when a run is capped.

Support & feedback

Found a bug or need a field that isn't here? Open an issue on the Actor's Issues tab — feature requests genuinely do get built.

If this Actor saved you time, please leave a rating — it's the main way other people find it.