DatafetchPro
    May 31, 20265 min read0 views

    How to Export Facebook Comments Quickly in Seconds?

    Looking for a simple way to export Facebook comments? Extract comments, reactions, profiles, and timestamps to CSV, JSON, or Markdown.

    Facebook Comments Exporter: Export Comments in Seconds

    Collecting Facebook comments manually is a slow and frustrating process, especially if you need data for research, lead generation, audience analysis or content monitoring. The Facebook Comments Exporter makes the process easier, allowing you to scrape comments directly from Facebook posts and export them in different formats.




    The script with one click parses the loaded comments and exports them to JSON, CSV or Markdown files. It also supports copy-to-clipboard, which makes it easy to move comment data into spreadsheets, databases or reporting tools.

    This script can be used by people working on data extraction, web scraping and web automation to collect comments with less hassle of set-up or API access. The exported data includes commenter names, comment text, reaction counts, profile links, timestamps, and reply depth if applicable.

    Key Features

    • Export Facebook comments to JSON, CSV and Markdown
    • Instantly copy all comments to clipboard
    • Author names, reactions, timestamps, profile links
    • Floating toolbar for easy access
    • Comment scanning in one click
    • Automatic detection of facebook posts and pages.
    • Export formats are clean and organised
    • Works right in your browser

    Whether you're analysing engagement, collecting customer feedback, monitoring discussions or building datasets for web scraping projects, this tool offers a fast and practical way to extract Facebook comments.


      // ==UserScript==

    // @name FB Comments Exporter Pro ✦

    // @namespace https://github.com/fb-comments-exporter

    // @version 2.0.0

    // @description Export Facebook post comments to JSON, CSV, or Markdown — with copy-to-clipboard for everything. A floating toolbar appears on any post with comments.

    // @author Ali Raza

    // @match https://www.facebook.com/*

    // @match https://web.facebook.com/*

    // @match https://m.facebook.com/*

    // @grant GM_setClipboard

    // @grant GM_addStyle

    // @grant GM_getValue

    // @grant GM_setValue

    // @run-at document-idle

    // ==/UserScript==




    (function () {

    'use strict';




    /* ─────────────────────────────────────────────

    STYLES

    ───────────────────────────────────────────── */

    GM_addStyle(`

    /* Floating toolbar */

    #fce-toolbar {

    position: fixed;

    bottom: 28px;

    right: 28px;

    z-index: 2147483647;

    display: flex;

    flex-direction: column;

    align-items: flex-end;

    gap: 10px;

    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;

    user-select: none;

    }




    /* Badge (count pill) */

    #fce-badge {

    background: linear-gradient(135deg, #1877f2, #0a5fd8);

    color: #fff;

    font-size: 11px;

    font-weight: 700;

    letter-spacing: .5px;

    padding: 4px 10px;

    border-radius: 20px;

    box-shadow: 0 2px 8px rgba(24,119,242,.45);

    transition: opacity .25s;

    pointer-events: none;

    }




    /* Main panel */

    #fce-panel {

    background: #fff;

    border-radius: 18px;

    box-shadow: 0 8px 40px rgba(0,0,0,.18), 0 2px 8px rgba(0,0,0,.10);

    overflow: hidden;

    width: 290px;

    transition: transform .3s cubic-bezier(.4,0,.2,1), opacity .3s;

    transform-origin: bottom right;

    }

    #fce-panel.fce-hidden {

    transform: scale(.85) translateY(20px);

    opacity: 0;

    pointer-events: none;

    }




    /* Panel header */

    #fce-header {

    background: linear-gradient(135deg, #1877f2 0%, #0a5fd8 100%);

    padding: 14px 18px 12px;

    display: flex;

    align-items: center;

    gap: 10px;

    }

    #fce-header-icon {

    font-size: 20px;

    line-height: 1;

    }

    #fce-header-text {

    flex: 1;

    }

    #fce-title {

    color: #fff;

    font-size: 14px;

    font-weight: 700;

    line-height: 1.2;

    margin: 0;

    }

    #fce-subtitle {

    color: rgba(255,255,255,.75);

    font-size: 11px;

    margin: 0;

    }

    #fce-close-btn {

    background: rgba(255,255,255,.15);

    border: none;

    color: #fff;

    width: 26px;

    height: 26px;

    border-radius: 50%;

    cursor: pointer;

    font-size: 14px;

    display: flex;

    align-items: center;

    justify-content: center;

    transition: background .2s;

    flex-shrink: 0;

    }

    #fce-close-btn:hover { background: rgba(255,255,255,.28); }




    /* Stats row */

    #fce-stats {

    padding: 12px 18px 8px;

    border-bottom: 1px solid #f0f2f5;

    display: flex;

    align-items: center;

    gap: 8px;

    }

    .fce-stat {

    display: flex;

    align-items: center;

    gap: 5px;

    color: #65676b;

    font-size: 12px;

    }

    .fce-stat-num {

    color: #1877f2;

    font-weight: 700;

    }




    /* Scan button */

    #fce-scan-btn {

    display: flex;

    align-items: center;

    gap: 7px;

    background: #e7f0fd;

    border: 1.5px solid #1877f2;

    color: #1877f2;

    font-size: 12.5px;

    font-weight: 600;

    padding: 6px 14px;

    border-radius: 20px;

    cursor: pointer;

    margin-left: auto;

    transition: background .2s, transform .15s;

    }

    #fce-scan-btn:hover { background: #d0e4fc; transform: scale(1.04); }

    #fce-scan-btn:active { transform: scale(.97); }

    #fce-scan-btn.scanning { animation: fce-spin-border .9s linear infinite; }




    /* Divider */

    .fce-divider {

    height: 1px;

    background: #f0f2f5;

    margin: 0 18px;

    }




    /* Export buttons grid */

    #fce-export-section {

    padding: 12px 18px 16px;

    }

    #fce-export-section h4 {

    margin: 0 0 10px;

    color: #65676b;

    font-size: 11px;

    font-weight: 600;

    text-transform: uppercase;

    letter-spacing: .7px;

    }

    #fce-buttons-grid {

    display: grid;

    grid-template-columns: 1fr 1fr;

    gap: 8px;

    }

    .fce-btn {

    display: flex;

    align-items: center;

    justify-content: center;

    gap: 6px;

    border: none;

    border-radius: 10px;

    cursor: pointer;

    font-size: 12.5px;

    font-weight: 600;

    padding: 9px 10px;

    transition: transform .15s, filter .15s, opacity .2s;

    letter-spacing: .2px;

    }

    .fce-btn:disabled { opacity: .45; cursor: not-allowed; }

    .fce-btn:not(:disabled):hover { transform: scale(1.04); filter: brightness(1.06); }

    .fce-btn:not(:disabled):active { transform: scale(.96); }




    .fce-btn-json { background: #fff4e0; color: #e67e22; border: 1.5px solid #f5c67f; }

    .fce-btn-csv { background: #e8f8f0; color: #1a9e5c; border: 1.5px solid #7ddfb1; }

    .fce-btn-md { background: #f0ebff; color: #7c3aed; border: 1.5px solid #c4a8fa; }

    .fce-btn-copy { background: #e8f0fe; color: #1877f2; border: 1.5px solid #9bbef8; }

    .fce-btn-span { grid-column: 1 / -1; }

    .fce-btn-all { background: linear-gradient(135deg, #1877f2, #0a5fd8); color: #fff; border: none; }




    /* Toast notification */

    #fce-toast {

    position: fixed;

    bottom: 90px;

    right: 28px;

    z-index: 2147483647;

    background: #1a1a1a;

    color: #fff;

    padding: 10px 18px;

    border-radius: 12px;

    font-size: 13px;

    font-weight: 500;

    box-shadow: 0 4px 20px rgba(0,0,0,.25);

    display: flex;

    align-items: center;

    gap: 8px;

    max-width: 280px;

    transition: opacity .3s, transform .3s;

    pointer-events: none;

    }

    #fce-toast.fce-toast-hide {

    opacity: 0;

    transform: translateY(10px);

    }

    .fce-toast-icon { font-size: 16px; flex-shrink: 0; }




    /* FAB toggle button */

    #fce-fab {

    width: 54px;

    height: 54px;

    border-radius: 50%;

    background: linear-gradient(135deg, #1877f2, #0a5fd8);

    border: none;

    cursor: pointer;

    color: #fff;

    font-size: 22px;

    display: flex;

    align-items: center;

    justify-content: center;

    box-shadow: 0 4px 18px rgba(24,119,242,.5);

    transition: transform .2s, box-shadow .2s;

    flex-shrink: 0;

    }

    #fce-fab:hover { transform: scale(1.1); box-shadow: 0 6px 24px rgba(24,119,242,.65); }

    #fce-fab:active { transform: scale(.93); }




    /* Progress bar */

    #fce-progress-wrap {

    padding: 0 18px 10px;

    display: none;

    }

    #fce-progress-wrap.visible { display: block; }

    #fce-progress-bar-bg {

    height: 4px;

    background: #e4e6ea;

    border-radius: 4px;

    overflow: hidden;

    }

    #fce-progress-bar {

    height: 100%;

    background: linear-gradient(90deg, #1877f2, #4fa3f7);

    border-radius: 4px;

    width: 0%;

    transition: width .3s;

    }

    #fce-progress-label {

    font-size: 11px;

    color: #65676b;

    margin-top: 4px;

    text-align: right;

    }




    @keyframes fce-spin-border {

    0% { box-shadow: 0 0 0 2px #1877f2; }

    50% { box-shadow: 0 0 0 4px rgba(24,119,242,.2); }

    100% { box-shadow: 0 0 0 2px #1877f2; }

    }

    `);




    /* ─────────────────────────────────────────────

    STATE

    ───────────────────────────────────────────── */

    let comments = [];

    let panelOpen = GM_getValue('fce_panel_open', true);




    /* ─────────────────────────────────────────────

    DOM HELPERS

    ───────────────────────────────────────────── */

    function el(tag, attrs = {}, ...children) {

    const node = document.createElement(tag);

    Object.entries(attrs).forEach(([k, v]) => {

    if (k === 'class') node.className = v;

    else if (k === 'text') node.textContent = v;

    else node.setAttribute(k, v);

    });

    children.forEach(c => c && node.appendChild(typeof c === 'string' ? document.createTextNode(c) : c));

    return node;

    }




    /* ─────────────────────────────────────────────

    SCRAPER

    ───────────────────────────────────────────── */

    function scrapeComments() {

    const articles = document.querySelectorAll('[role="article"][aria-label]');

    const result = [];

    const seen = new Set();




    articles.forEach((article, idx) => {

    const label = article.getAttribute('aria-label') || '';

    // Match "Comment by NAME TIME"

    const match = label.match(/^Comment by (.+?) (\d+ \w+ ago|just now|[\w ]+ ago)$/i);

    if (!match) return;




    const author = match[1].trim();

    const timeAgo = match[2].trim();




    // Get comment text — look for the main text block inside the bubble

    // The comment bubble is typically the first div with substantial text

    let text = '';

    const textSpans = article.querySelectorAll('div[dir="auto"] > span[dir="auto"], div[dir="auto"]');

    for (const span of textSpans) {

    const t = span.innerText?.trim();

    if (t && t.length > 0 && t !== author && !t.match(/^(Like|Reply|See translation|\d+ reactions?)$/i)) {

    text = t;

    break;

    }

    }

    // Fallback: grab all visible text except known UI labels

    if (!text) {

    const clone = article.cloneNode(true);

    // Remove buttons/icons text

    clone.querySelectorAll('[role="button"], [aria-label="Like"], [aria-label="React"], [data-visualcompletion]')

    .forEach(n => n.remove());

    const raw = clone.innerText || '';

    const lines = raw.split('\n').map(l => l.trim()).filter(l =>

    l && l !== author && !l.match(/^(Like|Reply|See translation|\d+ reactions?|just now|\d+ \w+ ago)$/i)

    );

    text = lines[0] || '';

    }




    // Profile link

    let profileLink = '';

    const profileAnchor = article.querySelector('a[role="link"][href*="facebook.com"]');

    if (profileAnchor) {

    try {

    const url = new URL(profileAnchor.href);

    // Strip tracking params — keep base path

    profileLink = url.origin + url.pathname;

    } catch (_) {}

    }




    // Reactions

    let reactions = 0;

    const reactEl = article.querySelector('[aria-label*="reaction"]');

    if (reactEl) {

    const m = (reactEl.getAttribute('aria-label') || '').match(/^(\d+)/);

    if (m) reactions = parseInt(m[1]);

    }




    // Depth: nested replies have deeper nesting

    let depth = 0;

    let parent = article.parentElement;

    while (parent) {

    if (parent.getAttribute && parent.getAttribute('role') === 'article') depth++;

    parent = parent.parentElement;

    }




    const key = `${author}::${text}`;

    if (seen.has(key)) return;

    seen.add(key);




    result.push({

    index: result.length + 1,

    author,

    timeAgo,

    text,

    reactions,

    depth, // 0 = top-level, 1+ = reply

    profileLink,

    scrapedAt: new Date().toISOString(),

    });

    });




    return result;

    }




    /* ─────────────────────────────────────────────

    EXPORT FORMATTERS

    ───────────────────────────────────────────── */

    function toJSON(data) {

    return JSON.stringify({ exportedAt: new Date().toISOString(), total: data.length, comments: data }, null, 2);

    }




    function toCSV(data) {

    const headers = ['#', 'Author', 'Time', 'Text', 'Reactions', 'Depth', 'Profile URL', 'Scraped At'];

    const escape = v => `"${String(v ?? '').replace(/"/g, '""')}"`;

    const rows = data.map(c => [

    c.index, escape(c.author), escape(c.timeAgo), escape(c.text),

    c.reactions, c.depth, escape(c.profileLink), escape(c.scrapedAt)

    ].join(','));

    return [headers.join(','), ...rows].join('\r\n');

    }




    function toMarkdown(data) {

    const lines = [

    `# Facebook Comments Export`,

    ``,

    `> **Exported:** ${new Date().toLocaleString()} `,

    `> **Total comments:** ${data.length}`,

    ``,

    `---`,

    ``,

    ];

    data.forEach(c => {

    const indent = ' '.repeat(c.depth);

    lines.push(`${indent}### ${c.index}. ${c.author}`);

    lines.push(`${indent}*${c.timeAgo}* ${c.reactions > 0 ? `· 👍 ${c.reactions} reactions` : ''}`);

    lines.push(``);

    if (c.text) lines.push(`${indent}> ${c.text.replace(/\n/g, `\n${indent}> `)}`);

    if (c.profileLink) lines.push(`${indent}[View Profile](${c.profileLink})`);

    lines.push(``);

    lines.push(`${indent}---`);

    lines.push(``);

    });

    return lines.join('\n');

    }




    /* ─────────────────────────────────────────────

    FILE DOWNLOAD

    ───────────────────────────────────────────── */

    function download(content, filename, mime) {

    const blob = new Blob([content], { type: mime });

    const url = URL.createObjectURL(blob);

    const a = document.createElement('a');

    a.href = url;

    a.download = filename;

    document.body.appendChild(a);

    a.click();

    document.body.removeChild(a);

    setTimeout(() => URL.revokeObjectURL(url), 5000);

    }




    function stamp() {

    return new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);

    }




    /* ─────────────────────────────────────────────

    TOAST

    ───────────────────────────────────────────── */

    let toastTimer = null;

    function showToast(icon, msg, color = '#1a1a1a') {

    let toast = document.getElementById('fce-toast');

    if (!toast) {

    toast = el('div', { id: 'fce-toast', class: 'fce-toast-hide' });

    document.body.appendChild(toast);

    }

    toast.innerHTML = `<span class="fce-toast-icon">${icon}</span><span>${msg}</span>`;

    toast.style.background = color;

    toast.classList.remove('fce-toast-hide');

    clearTimeout(toastTimer);

    toastTimer = setTimeout(() => toast.classList.add('fce-toast-hide'), 2800);

    }




    /* ─────────────────────────────────────────────

    BUILD UI

    ───────────────────────────────────────────── */

    function buildToolbar() {

    if (document.getElementById('fce-toolbar')) return;




    const toolbar = el('div', { id: 'fce-toolbar' });




    // Panel

    const panel = el('div', { id: 'fce-panel', class: panelOpen ? '' : 'fce-hidden' });




    // Header

    const header = el('div', { id: 'fce-header' });

    const headerIcon = el('div', { id: 'fce-header-icon', text: '💬' });

    const headerText = el('div', { id: 'fce-header-text' });

    const title = el('p', { id: 'fce-title', text: 'Comments Exporter' });

    const subtitle = el('p', { id: 'fce-subtitle', text: 'Scan & export with one click' });

    headerText.append(title, subtitle);

    const closeBtn = el('button', { id: 'fce-close-btn', title: 'Minimize' });

    closeBtn.innerHTML = '✕';

    closeBtn.onclick = () => togglePanel(false);

    header.append(headerIcon, headerText, closeBtn);

    panel.appendChild(header);




    // Stats row

    const statsRow = el('div', { id: 'fce-stats' });

    const statComments = el('div', { class: 'fce-stat' });

    statComments.innerHTML = `<span class="fce-stat-num" id="fce-count">0</span> comments found`;

    const scanBtn = el('button', { id: 'fce-scan-btn' });

    scanBtn.innerHTML = `🔍 Scan`;

    scanBtn.onclick = handleScan;

    statsRow.append(statComments, scanBtn);

    panel.appendChild(statsRow);




    // Progress bar

    const progressWrap = el('div', { id: 'fce-progress-wrap' });

    progressWrap.innerHTML = `

    <div id="fce-progress-bar-bg"><div id="fce-progress-bar"></div></div>

    <div id="fce-progress-label">Scanning…</div>

    `;

    panel.appendChild(progressWrap);




    // Divider

    panel.appendChild(el('div', { class: 'fce-divider' }));




    // Export section

    const exportSec = el('div', { id: 'fce-export-section' });

    exportSec.innerHTML = `<h4>Export / Copy</h4>`;

    const grid = el('div', { id: 'fce-buttons-grid' });




    // JSON download

    const btnJSON = el('button', { class: 'fce-btn fce-btn-json', disabled: 'true' });

    btnJSON.id = 'fce-btn-json';

    btnJSON.innerHTML = `📄 JSON`;

    btnJSON.title = 'Download as JSON file';

    btnJSON.onclick = () => {

    if (!comments.length) return;

    download(toJSON(comments), `fb_comments_${stamp()}.json`, 'application/json');

    showToast('📄', `JSON downloaded (${comments.length} comments)`, '#e67e22');

    };




    // CSV download

    const btnCSV = el('button', { class: 'fce-btn fce-btn-csv', disabled: 'true' });

    btnCSV.id = 'fce-btn-csv';

    btnCSV.innerHTML = `📊 CSV`;

    btnCSV.title = 'Download as CSV file';

    btnCSV.onclick = () => {

    if (!comments.length) return;

    download(toCSV(comments), `fb_comments_${stamp()}.csv`, 'text/csv;charset=utf-8;');

    showToast('📊', `CSV downloaded (${comments.length} comments)`, '#1a9e5c');

    };




    // Markdown download

    const btnMD = el('button', { class: 'fce-btn fce-btn-md', disabled: 'true' });

    btnMD.id = 'fce-btn-md';

    btnMD.innerHTML = `📝 Markdown`;

    btnMD.title = 'Download as Markdown file';

    btnMD.onclick = () => {

    if (!comments.length) return;

    download(toMarkdown(comments), `fb_comments_${stamp()}.md`, 'text/markdown');

    showToast('📝', `Markdown downloaded (${comments.length} comments)`, '#7c3aed');

    };




    // Copy all

    const btnCopyAll = el('button', { class: 'fce-btn fce-btn-copy', disabled: 'true' });

    btnCopyAll.id = 'fce-btn-copy-all';

    btnCopyAll.innerHTML = `📋 Copy All`;

    btnCopyAll.title = 'Copy all comments as plain text';

    btnCopyAll.onclick = () => {

    if (!comments.length) return;

    const plain = comments.map(c => `${c.author} (${c.timeAgo}):\n${c.text}`).join('\n\n---\n\n');

    GM_setClipboard(plain, 'text');

    showToast('📋', `${comments.length} comments copied!`);

    };




    // Download all (ZIP-like bundle as JSON with all formats)

    const btnAll = el('button', { class: 'fce-btn fce-btn-all fce-btn-span', disabled: 'true' });

    btnAll.id = 'fce-btn-all';

    btnAll.innerHTML = `⬇️ Download All Formats`;

    btnAll.title = 'Download JSON, CSV and Markdown at once';

    btnAll.onclick = () => {

    if (!comments.length) return;

    setTimeout(() => download(toJSON(comments), `fb_comments_${stamp()}.json`, 'application/json'), 0);

    setTimeout(() => download(toCSV(comments), `fb_comments_${stamp()}.csv`, 'text/csv'), 300);

    setTimeout(() => download(toMarkdown(comments), `fb_comments_${stamp()}.md`, 'text/markdown'), 600);

    showToast('⬇️', `3 files downloading…`, '#0a5fd8');

    };




    grid.append(btnJSON, btnCSV, btnMD, btnCopyAll, btnAll);

    exportSec.appendChild(grid);

    panel.appendChild(exportSec);




    // FAB

    const fab = el('button', { id: 'fce-fab', title: 'FB Comments Exporter' });

    fab.innerHTML = `💬`;

    fab.onclick = () => togglePanel(!panelOpen);




    // Badge

    const badge = el('div', { id: 'fce-badge', text: 'Comments Exporter' });




    toolbar.append(panel, badge, fab);

    document.body.appendChild(toolbar);




    // Auto-scan on load if on a post page

    if (isPostPage()) {

    setTimeout(handleScan, 1800);

    }

    }




    /* ─────────────────────────────────────────────

    PANEL TOGGLE

    ───────────────────────────────────────────── */

    function togglePanel(open) {

    panelOpen = open;

    GM_setValue('fce_panel_open', open);

    const panel = document.getElementById('fce-panel');

    const fab = document.getElementById('fce-fab');

    if (panel) panel.classList.toggle('fce-hidden', !open);

    if (fab) fab.innerHTML = open ? `` : `💬`;

    }




    /* ─────────────────────────────────────────────

    SCAN HANDLER

    ───────────────────────────────────────────── */

    function handleScan() {

    const scanBtn = document.getElementById('fce-scan-btn');

    const progressWrap = document.getElementById('fce-progress-wrap');

    const progressBar = document.getElementById('fce-progress-bar');

    const progressLabel = document.getElementById('fce-progress-label');

    const countEl = document.getElementById('fce-count');




    if (scanBtn) {

    scanBtn.innerHTML = `⏳ Scanning…`;

    scanBtn.disabled = true;

    }

    if (progressWrap) progressWrap.classList.add('visible');




    // Animate progress bar

    let prog = 0;

    const progInterval = setInterval(() => {

    prog = Math.min(prog + Math.random() * 18, 88);

    if (progressBar) progressBar.style.width = prog + '%';

    if (progressLabel) progressLabel.textContent = `Scanning page…`;

    }, 120);




    setTimeout(() => {

    clearInterval(progInterval);

    if (progressBar) progressBar.style.width = '100%';




    comments = scrapeComments();




    if (countEl) countEl.textContent = comments.length;




    // Enable buttons

    ['fce-btn-json', 'fce-btn-csv', 'fce-btn-md', 'fce-btn-copy-all', 'fce-btn-all'].forEach(id => {

    const b = document.getElementById(id);

    if (b) b.disabled = comments.length === 0;

    });




    if (scanBtn) {

    scanBtn.innerHTML = `🔄 Re-scan`;

    scanBtn.disabled = false;

    }




    // Update badge

    const badge = document.getElementById('fce-badge');

    if (badge) badge.textContent = `${comments.length} comment${comments.length !== 1 ? 's' : ''} ready`;




    if (progressLabel) progressLabel.textContent = `Found ${comments.length} comments`;

    setTimeout(() => {

    if (progressWrap) progressWrap.classList.remove('visible');

    }, 1400);




    if (comments.length > 0) {

    showToast('✅', `${comments.length} comments scraped!`, '#1a9e5c');

    } else {

    showToast('⚠️', 'No comments found. Try scrolling to load them first.', '#e67e22');

    }

    }, 900);

    }




    /* ─────────────────────────────────────────────

    PAGE DETECTION

    ───────────────────────────────────────────── */

    function isPostPage() {

    const url = location.href;

    return url.includes('/posts/') || url.includes('/photo/') || url.includes('/video/') ||

    url.includes('/reel/') || url.includes('/permalink/') || url.includes('story_fbid=');

    }




    /* ─────────────────────────────────────────────

    INIT: inject toolbar when DOM is ready

    ───────────────────────────────────────────── */

    function init() {

    buildToolbar();

    }




    if (document.readyState === 'loading') {

    document.addEventListener('DOMContentLoaded', init);

    } else {

    init();

    }




    // Also re-init on Facebook SPA navigation

    let lastUrl = location.href;

    const navObserver = new MutationObserver(() => {

    if (location.href !== lastUrl) {

    lastUrl = location.href;

    comments = [];

    // Remove old toolbar and rebuild

    const old = document.getElementById('fce-toolbar');

    if (old) old.remove();

    const oldToast = document.getElementById('fce-toast');

    if (oldToast) oldToast.remove();

    setTimeout(init, 1200);

    }

    });

    navObserver.observe(document.body, { childList: true, subtree: true });




    })();
    0