Skip to content

Instantly share code, notes, and snippets.

@n0mimono
Last active March 13, 2025 09:22
Show Gist options
  • Save n0mimono/7743e0112fb975975704f0beb0a9fab8 to your computer and use it in GitHub Desktop.
Save n0mimono/7743e0112fb975975704f0beb0a9fab8 to your computer and use it in GitHub Desktop.
YouTubeLiveChat with Chromium
const puppeteer = require("puppeteer");
const VIDEO_ID = "VIDEO_ID";
const YOUTUBE_LIVE_URL = `https://www.youtube.com/watch?v=${VIDEO_ID}`;
const INTERVAL_MS = 2000;
(async () => {
console.log("🟒 Launching browser...");
const browser = await puppeteer.launch({
headless: true,
args: ["--disable-features=site-per-process", "--no-sandbox", "--disable-setuid-sandbox"],
});
console.log(`🟒 Accessing YouTube Live page... ${YOUTUBE_LIVE_URL}`);
const page = await browser.newPage();
await page.setUserAgent(
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36"
)
await page.goto(YOUTUBE_LIVE_URL, { waitUntil: "networkidle2" });
console.log("🟒 Getting ytInitialPlayerResponse...");
const html = await page.content();
const match = html.match(/ytInitialPlayerResponse\s*=\s*(\{.+?\});/);
if (!match) {
console.error("❌ ytInitialPlayerResponse not found");
await browser.close();
return;
}
const status = JSON.parse(match[1]).playabilityStatus.status
console.log(`🟒 Status: ${status}`);
console.log("🟒 Searching for frame...");
await page.waitForSelector("iframe#chatframe", { timeout: 10000 });
const frame = await page.$("iframe#chatframe");
if (!frame) {
console.error("❌ iframe#chatframe not found");
await browser.close();
return;
}
console.log("🟒 Getting contentFrame...");
const contentFrame = await frame.contentFrame();
if (!contentFrame) {
console.error("❌ iframe contentFrame not found");
await browser.close();
return;
}
console.log("🟒 Waiting for items...");
await contentFrame.waitForSelector("#items", { timeout: 10000 });
// scrape chat messages
async function scrape() {
const messages = await contentFrame.evaluate(() => {
const items = document.querySelector("#items");
if (!items) {
return [];
}
let chatMessages = [];
const contents = items.querySelectorAll("yt-live-chat-text-message-renderer");
for (let content of contents) {
const id = content.id;
const timestamp = content.querySelector("#timestamp")?.innerText.trim() || '';
const author = content.querySelector("#author-name")?.innerText.trim() || '';
const message = content.querySelector("#message")?.innerText.trim() || '';
chatMessages.push({ id, timestamp, author, message });
}
return chatMessages;
});
console.clear();
console.log(`🟒 Latest chat (${new Date().toLocaleTimeString()}):`);
console.table(messages);
}
setInterval(scrape, INTERVAL_MS);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment