{
  "version": "1.0.0",
  "exported_at": "2026-05-31T08:45:00.000Z",
  "project": {
    "name": "YouTube Details  Comments Scraper",
    "description": "Scrapes YouTube video details and comments from multiple YouTube video URLs. Uses navigate.urls with loop-continue to process all supplied URLs. Native scroll/sleep blocks load the YouTube comments section before exporting one row per loaded comment with video metadata repeated. The workflow caches visible metadata such as date before scrolling, then extracts comments. If YouTube blocks comments, requires login, throttles the browser, or shows bot verification, the fallback branch exports video-level fields with blank comment fields.",
    "color": "bg-[#ff0000]",
    "template_id": "ai-generated"
  },
  "blocks": [
    {
      "block_id": "set-window-size-1",
      "block_type": "process",
      "title": "Set Window Size",
      "description": "Set browser window dimensions",
      "position_x": 120,
      "position_y": 80,
      "config": {
        "width": 1920,
        "height": 1080,
        "color": "bg-[#4589ff]"
      }
    },
    {
      "block_id": "navigate-1",
      "block_type": "process",
      "title": "Navigate",
      "description": "Go to a URL",
      "position_x": 120,
      "position_y": 260,
      "config": {
        "urls": [
          "https://youtu.be/WOuzDxHdz6I",
          "https://youtu.be/Vjayaft_1Pc"
        ],
        "color": "bg-[#4589ff]"
      }
    },
    {
      "block_id": "wait-for-page-load-1",
      "block_type": "process",
      "title": "Wait for Page Load",
      "description": "Wait for page to finish loading",
      "position_x": 480,
      "position_y": 260,
      "config": {
        "timeout": 45,
        "color": "bg-[#08bdba]"
      }
    },
    {
      "block_id": "wait-for-element-1",
      "block_type": "process",
      "title": "Wait for Element",
      "description": "Wait until element appears",
      "position_x": 840,
      "position_y": 260,
      "config": {
        "selector": "ytd-watch-flexy",
        "timeout": 45,
        "visible": true,
        "color": "bg-[#08bdba]"
      }
    },
    {
      "block_id": "inject-javascript-1",
      "block_type": "process",
      "title": "Inject JavaScript",
      "description": "Execute custom JavaScript",
      "position_x": 1200,
      "position_y": 260,
      "config": {
        "jsCode": "(() => {\n  const textOf = el => ((el && (el.innerText || el.textContent || el.getAttribute('aria-label'))) || '').trim();\n  const bodyText = document.body.innerText || '';\n  const mf = window.ytInitialPlayerResponse?.microformat?.playerMicroformatRenderer || {};\n  const videoDetails = window.ytInitialPlayerResponse?.videoDetails || {};\n  const scripts = Array.from(document.scripts).map(s => s.textContent || '').join('\\n');\n  const scriptDate = (scripts.match(/\"publishDate\":\"([^\"]+)\"/) || scripts.match(/\"uploadDate\":\"([^\"]+)\"/) || scripts.match(/\"datePublished\":\"([^\"]+)\"/) || [])[1] || '';\n  const absoluteDate = (bodyText.match(/\\b(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Sept|Oct|Nov|Dec)[a-z]*\\s+\\d{1,2},\\s+\\d{4}\\b/i) || [''])[0];\n  const relativeAfterViews = (bodyText.match(/[\\d,.]+[KMB]?\\s+views\\s+([^\\n#•]+?ago)\\b/i) || [])[1] || '';\n  const relativeAny = (bodyText.match(/\\b\\d+\\s+(?:second|minute|hour|day|week|month|year)s?\\s+ago\\b/i) || [''])[0];\n  window.USCRAPER_VIDEO_META = {\n    title: (videoDetails.title || document.querySelector('meta[name=\"title\"]')?.content || document.querySelector('ytd-watch-metadata h1 yt-formatted-string')?.textContent || document.querySelector('h1')?.textContent || '').trim(),\n    view: videoDetails.viewCount ? Number(videoDetails.viewCount).toLocaleString() + ' views' : ((bodyText.match(/[\\d,.]+[KMB]?\\s+views/i) || [''])[0]),\n    date: (mf.publishDate || mf.uploadDate || document.querySelector('meta[itemprop=\"datePublished\"], meta[itemprop=\"uploadDate\"]')?.content || scriptDate || absoluteDate || relativeAfterViews || relativeAny || '').trim(),\n    youtuber: (videoDetails.author || document.querySelector('ytd-video-owner-renderer #channel-name a')?.textContent || '').trim(),\n    subscribers: (document.querySelector('#owner-sub-count')?.textContent?.trim() || ((bodyText.match(/[\\d,.]+[KMB]?\\s+subscribers/i) || [''])[0])),\n    description: (videoDetails.shortDescription || document.querySelector('ytd-text-inline-expander')?.innerText || '').trim()\n  };\n  try {\n    const video = document.querySelector('video');\n    if (video) video.pause();\n  } catch (e) {}\n  try {\n    const buttons = Array.from(document.querySelectorAll('button, tp-yt-paper-button, ytd-button-renderer, [role=\"button\"]'));\n    for (const el of buttons) {\n      const text = textOf(el).toLowerCase();\n      if (text.includes('accept all') || text.includes('i agree') || text.includes('reject all') || text.includes('not now')) {\n        try { el.click(); } catch (e) {}\n      }\n    }\n  } catch (e) {}\n  try {\n    const expanders = Array.from(document.querySelectorAll('tp-yt-paper-button#expand, ytd-text-inline-expander #expand, #description-inline-expander button, #more, button'));\n    for (const el of expanders) {\n      const text = textOf(el).toLowerCase();\n      if (el.id === 'expand' || text.includes('show more') || text === 'more' || text.includes('...more')) {\n        try { el.click(); } catch (e) {}\n      }\n    }\n  } catch (e) {}\n  return true;\n})()",
        "waitForCompletion": true,
        "timeout": 10,
        "color": "bg-[#a56eff]"
      }
    },
    {
      "block_id": "sleep-1",
      "block_type": "process",
      "title": "Sleep",
      "description": "Wait for specified time",
      "position_x": 1560,
      "position_y": 260,
      "config": {
        "duration": 2,
        "color": "bg-[#a56eff]"
      }
    },
    {
      "block_id": "scroll-1",
      "block_type": "process",
      "title": "Scroll",
      "description": "Scroll page or element",
      "position_x": 1920,
      "position_y": 260,
      "config": {
        "direction": "down",
        "amount": 1400,
        "color": "bg-[#a56eff]"
      }
    },
    {
      "block_id": "sleep-2",
      "block_type": "process",
      "title": "Sleep",
      "description": "Wait for specified time",
      "position_x": 2280,
      "position_y": 260,
      "config": {
        "duration": 2,
        "color": "bg-[#a56eff]"
      }
    },
    {
      "block_id": "scroll-2",
      "block_type": "process",
      "title": "Scroll",
      "description": "Scroll page or element",
      "position_x": 2640,
      "position_y": 260,
      "config": {
        "direction": "down",
        "amount": 1400,
        "color": "bg-[#a56eff]"
      }
    },
    {
      "block_id": "sleep-3",
      "block_type": "process",
      "title": "Sleep",
      "description": "Wait for specified time",
      "position_x": 3000,
      "position_y": 260,
      "config": {
        "duration": 2,
        "color": "bg-[#a56eff]"
      }
    },
    {
      "block_id": "scroll-3",
      "block_type": "process",
      "title": "Scroll",
      "description": "Scroll page or element",
      "position_x": 3360,
      "position_y": 260,
      "config": {
        "direction": "down",
        "amount": 1400,
        "color": "bg-[#a56eff]"
      }
    },
    {
      "block_id": "sleep-4",
      "block_type": "process",
      "title": "Sleep",
      "description": "Wait for specified time",
      "position_x": 3720,
      "position_y": 260,
      "config": {
        "duration": 2,
        "color": "bg-[#a56eff]"
      }
    },
    {
      "block_id": "inject-javascript-2",
      "block_type": "process",
      "title": "Inject JavaScript",
      "description": "Execute custom JavaScript",
      "position_x": 4080,
      "position_y": 260,
      "config": {
        "jsCode": "(() => {\n  const textOf = el => ((el && (el.innerText || el.textContent || el.getAttribute('aria-label'))) || '').trim().toLowerCase();\n  try {\n    const expanders = Array.from(document.querySelectorAll('ytd-comment-thread-renderer #more, ytd-comment-thread-renderer tp-yt-paper-button#more, ytd-comment-thread-renderer button'));\n    for (const el of expanders) {\n      const text = textOf(el);\n      if (text.includes('read more') || text.includes('show more') || text === 'more') {\n        try { el.click(); } catch (e) {}\n      }\n    }\n  } catch (e) {}\n  return true;\n})()",
        "waitForCompletion": true,
        "timeout": 10,
        "color": "bg-[#a56eff]"
      }
    },
    {
      "block_id": "sleep-5",
      "block_type": "process",
      "title": "Sleep",
      "description": "Wait for specified time",
      "position_x": 4440,
      "position_y": 260,
      "config": {
        "duration": 1,
        "color": "bg-[#a56eff]"
      }
    },
    {
      "block_id": "element-exists-1",
      "block_type": "process",
      "title": "Element Exists",
      "description": "Check if element exists",
      "position_x": 4800,
      "position_y": 260,
      "config": {
        "selector": "ytd-comment-thread-renderer",
        "color": "bg-[#ff832b]"
      }
    },
    {
      "block_id": "structured-export-1",
      "block_type": "process",
      "title": "Structured Export",
      "description": "Export data with custom columns",
      "position_x": 5160,
      "position_y": 260,
      "config": {
        "rowSelector": "ytd-comment-thread-renderer",
        "fileName": "youtube-details-comments-scraper.csv",
        "saveLocation": "C:\\Users\\theskd\\Documents\\UScraper\\templates",
        "includeHeaders": true,
        "fileMode": "append",
        "color": "bg-[#42be65]",
        "columns": [
          {
            "name": "title",
            "selector": "(window.USCRAPER_VIDEO_META?.title || window.ytInitialPlayerResponse?.videoDetails?.title || document.querySelector('meta[name=\"title\"]')?.content || document.querySelector('ytd-watch-metadata h1 yt-formatted-string')?.textContent || document.querySelector('h1')?.textContent || '').trim()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "view",
            "selector": "(() => { if (window.USCRAPER_VIDEO_META?.view) return window.USCRAPER_VIDEO_META.view; const v = window.ytInitialPlayerResponse?.videoDetails?.viewCount; if (v) return Number(v).toLocaleString() + ' views'; return ((document.body.innerText || '').match(/[\\d,.]+[KMB]?\\s+views/i) || [''])[0]; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "date",
            "selector": "(() => { if (window.USCRAPER_VIDEO_META?.date) return window.USCRAPER_VIDEO_META.date; const txt = document.body.innerText || ''; return ((txt.match(/\\b(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Sept|Oct|Nov|Dec)[a-z]*\\s+\\d{1,2},\\s+\\d{4}\\b/i) || txt.match(/\\b\\d+\\s+(?:second|minute|hour|day|week|month|year)s?\\s+ago\\b/i) || [''])[0]); })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "thumbs_up",
            "selector": "(() => { const labels = Array.from(document.querySelectorAll('button, [role=\"button\"]')).map(el => el.getAttribute('aria-label') || el.title || '').filter(Boolean); return labels.find(t => /like/i.test(t) && !/dislike/i.test(t)) || ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "youtuber",
            "selector": "(window.USCRAPER_VIDEO_META?.youtuber || window.ytInitialPlayerResponse?.videoDetails?.author || document.querySelector('ytd-video-owner-renderer #channel-name a')?.textContent || '').trim()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "subscribers",
            "selector": "(() => { if (window.USCRAPER_VIDEO_META?.subscribers) return window.USCRAPER_VIDEO_META.subscribers; const txt = document.body.innerText || ''; return (txt.match(/[\\d,.]+[KMB]?\\s+subscribers/i) || [''])[0]; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "description",
            "selector": "(window.USCRAPER_VIDEO_META?.description || window.ytInitialPlayerResponse?.videoDetails?.shortDescription || document.querySelector('ytd-text-inline-expander')?.innerText || '').trim()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "comment_count",
            "selector": "(() => { const txt = [document.querySelector('ytd-comments-header-renderer h2')?.innerText, document.querySelector('ytd-comments-header-renderer #count')?.innerText, document.querySelector('#comments #count')?.innerText, document.querySelector('#count .count-text')?.innerText, document.body.innerText.match(/Comments\\s+([\\d,]+)/i)?.[0]].filter(Boolean).join(' '); const m = txt.match(/([\\d,]+)\\s*(?:comments?)?/i); return m ? m[1] : ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "author",
            "selector": "#author-text",
            "attribute": "text"
          },
          {
            "name": "comment_date",
            "selector": "#published-time-text a",
            "attribute": "text"
          },
          {
            "name": "comment",
            "selector": "#content-text",
            "attribute": "text"
          },
          {
            "name": "comment_likes",
            "selector": "#vote-count-middle",
            "attribute": "text"
          },
          {
            "name": "video_url",
            "selector": "location.href",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "video_id",
            "selector": "(new URL(location.href)).searchParams.get('v') || location.pathname.split('/').filter(Boolean).pop() || ''",
            "attribute": "text",
            "isJs": true
          }
        ]
      }
    },
    {
      "block_id": "loop-continue-1",
      "block_type": "process",
      "title": "Loop Continue",
      "description": "Continue multi-input loop",
      "position_x": 5520,
      "position_y": 260,
      "config": {
        "color": "bg-[#8d8d8d]"
      }
    },
    {
      "block_id": "structured-export-2",
      "block_type": "process",
      "title": "Structured Export",
      "description": "Export data with custom columns",
      "position_x": 4800,
      "position_y": 600,
      "config": {
        "rowSelector": "body",
        "fileName": "youtube-details-comments-scraper.csv",
        "saveLocation": "C:\\Users\\theskd\\Documents\\UScraper\\templates",
        "includeHeaders": true,
        "fileMode": "append",
        "color": "bg-[#42be65]",
        "columns": [
          {
            "name": "title",
            "selector": "(window.USCRAPER_VIDEO_META?.title || window.ytInitialPlayerResponse?.videoDetails?.title || document.querySelector('meta[name=\"title\"]')?.content || document.querySelector('ytd-watch-metadata h1 yt-formatted-string')?.textContent || document.querySelector('h1')?.textContent || '').trim()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "view",
            "selector": "(() => { if (window.USCRAPER_VIDEO_META?.view) return window.USCRAPER_VIDEO_META.view; const v = window.ytInitialPlayerResponse?.videoDetails?.viewCount; if (v) return Number(v).toLocaleString() + ' views'; return ((document.body.innerText || '').match(/[\\d,.]+[KMB]?\\s+views/i) || [''])[0]; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "date",
            "selector": "(() => { if (window.USCRAPER_VIDEO_META?.date) return window.USCRAPER_VIDEO_META.date; const txt = document.body.innerText || ''; return ((txt.match(/\\b(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Sept|Oct|Nov|Dec)[a-z]*\\s+\\d{1,2},\\s+\\d{4}\\b/i) || txt.match(/\\b\\d+\\s+(?:second|minute|hour|day|week|month|year)s?\\s+ago\\b/i) || [''])[0]); })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "thumbs_up",
            "selector": "(() => { const labels = Array.from(document.querySelectorAll('button, [role=\"button\"]')).map(el => el.getAttribute('aria-label') || el.title || '').filter(Boolean); return labels.find(t => /like/i.test(t) && !/dislike/i.test(t)) || ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "youtuber",
            "selector": "(window.USCRAPER_VIDEO_META?.youtuber || window.ytInitialPlayerResponse?.videoDetails?.author || document.querySelector('ytd-video-owner-renderer #channel-name a')?.textContent || '').trim()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "subscribers",
            "selector": "(() => { if (window.USCRAPER_VIDEO_META?.subscribers) return window.USCRAPER_VIDEO_META.subscribers; const txt = document.body.innerText || ''; return (txt.match(/[\\d,.]+[KMB]?\\s+subscribers/i) || [''])[0]; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "description",
            "selector": "(window.USCRAPER_VIDEO_META?.description || window.ytInitialPlayerResponse?.videoDetails?.shortDescription || document.querySelector('ytd-text-inline-expander')?.innerText || '').trim()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "comment_count",
            "selector": "(() => { const txt = [document.querySelector('ytd-comments-header-renderer h2')?.innerText, document.querySelector('ytd-comments-header-renderer #count')?.innerText, document.querySelector('#comments #count')?.innerText, document.querySelector('#count .count-text')?.innerText, document.body.innerText.match(/Comments\\s+([\\d,]+)/i)?.[0]].filter(Boolean).join(' '); const m = txt.match(/([\\d,]+)\\s*(?:comments?)?/i); return m ? m[1] : ''; })()",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "author",
            "selector": "''",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "comment_date",
            "selector": "''",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "comment",
            "selector": "''",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "comment_likes",
            "selector": "''",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "video_url",
            "selector": "location.href",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "video_id",
            "selector": "(new URL(location.href)).searchParams.get('v') || location.pathname.split('/').filter(Boolean).pop() || ''",
            "attribute": "text",
            "isJs": true
          }
        ]
      }
    },
    {
      "block_id": "loop-continue-2",
      "block_type": "process",
      "title": "Loop Continue",
      "description": "Continue multi-input loop",
      "position_x": 5160,
      "position_y": 600,
      "config": {
        "color": "bg-[#8d8d8d]"
      }
    }
  ],
  "connections": [
    {
      "from_block_id": "set-window-size-1",
      "from_connector_id": "right",
      "to_block_id": "navigate-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "navigate-1",
      "from_connector_id": "right",
      "to_block_id": "wait-for-page-load-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "wait-for-page-load-1",
      "from_connector_id": "right",
      "to_block_id": "wait-for-element-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "wait-for-element-1",
      "from_connector_id": "right",
      "to_block_id": "inject-javascript-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "inject-javascript-1",
      "from_connector_id": "right",
      "to_block_id": "sleep-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "sleep-1",
      "from_connector_id": "right",
      "to_block_id": "scroll-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "scroll-1",
      "from_connector_id": "right",
      "to_block_id": "sleep-2",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "sleep-2",
      "from_connector_id": "right",
      "to_block_id": "scroll-2",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "scroll-2",
      "from_connector_id": "right",
      "to_block_id": "sleep-3",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "sleep-3",
      "from_connector_id": "right",
      "to_block_id": "scroll-3",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "scroll-3",
      "from_connector_id": "right",
      "to_block_id": "sleep-4",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "sleep-4",
      "from_connector_id": "right",
      "to_block_id": "inject-javascript-2",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "inject-javascript-2",
      "from_connector_id": "right",
      "to_block_id": "sleep-5",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "sleep-5",
      "from_connector_id": "right",
      "to_block_id": "element-exists-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "element-exists-1",
      "from_connector_id": "true",
      "to_block_id": "structured-export-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "structured-export-1",
      "from_connector_id": "right",
      "to_block_id": "loop-continue-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "element-exists-1",
      "from_connector_id": "false",
      "to_block_id": "structured-export-2",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "structured-export-2",
      "from_connector_id": "right",
      "to_block_id": "loop-continue-2",
      "to_connector_id": "left"
    }
  ],
  "canvas_elements": [
    {
      "id": "group-entry",
      "element_type": "group",
      "title": "Entry & Setup",
      "color": "#4589ff",
      "position_x": 48,
      "position_y": -24,
      "width": 380,
      "height": 296,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "set-window-size-1"
        ]
      }
    },
    {
      "id": "group-load",
      "element_type": "group",
      "title": "Page Load",
      "color": "#08bdba",
      "position_x": 48,
      "position_y": 156,
      "width": 4640,
      "height": 296,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "navigate-1",
          "wait-for-page-load-1",
          "wait-for-element-1",
          "sleep-1",
          "sleep-2",
          "sleep-3",
          "sleep-4",
          "sleep-5"
        ]
      }
    },
    {
      "id": "group-interaction",
      "element_type": "group",
      "title": "Interaction",
      "color": "#a56eff",
      "position_x": 1128,
      "position_y": 156,
      "width": 3200,
      "height": 296,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "inject-javascript-1",
          "scroll-1",
          "scroll-2",
          "scroll-3",
          "inject-javascript-2"
        ]
      }
    },
    {
      "id": "group-pagination",
      "element_type": "group",
      "title": "Pagination Loop",
      "color": "#ff832b",
      "position_x": 4728,
      "position_y": 156,
      "width": 1040,
      "height": 636,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "element-exists-1",
          "loop-continue-1",
          "loop-continue-2"
        ]
      }
    },
    {
      "id": "group-extract",
      "element_type": "group",
      "title": "Data Extraction",
      "color": "#42be65",
      "position_x": 4728,
      "position_y": 156,
      "width": 680,
      "height": 636,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "structured-export-1",
          "structured-export-2"
        ]
      }
    },
    {
      "id": "note-overview",
      "element_type": "note",
      "title": "Overview",
      "content": "Scrapes YouTube video details and comments from multiple YouTube video URLs. Uses navigate.urls with loop-continue to process all supplied URLs. Native scroll/sleep blocks load the YouTube comments section before exporting one row per loaded comment with video metadata repeated. The workflow caches visible metadata such as date before scrolling, then extracts comments. If YouTube blocks comments, requires login, throttles the browser, or shows bot verification, the fallback branch exports video-level fields with blank comment fields.",
      "color": "#f1c21b",
      "position_x": 80,
      "position_y": 20,
      "width": 480,
      "height": 160,
      "z_index": 22,
      "data": {}
    },
    {
      "id": "note-block-navigate-1",
      "element_type": "note",
      "title": "Note: Navigate",
      "content": "Multi-URL loop over 2 pages. Pair with loop-continue at the end of each iteration.",
      "color": "#ee5396",
      "position_x": 320,
      "position_y": 240,
      "width": 328,
      "height": 107,
      "z_index": 22,
      "data": {
        "block_id": "navigate-1"
      }
    },
    {
      "id": "note-block-inject-javascript-1",
      "element_type": "note",
      "title": "Note: Inject JavaScript",
      "content": "Runs custom JavaScript in the page: `(() => {\n  const textOf = el => ((el && (el.innerText || el.textContent || el.getAttribute('aria-lab...` Verify in browser if results are empty.",
      "color": "#ee5396",
      "position_x": 1400,
      "position_y": 240,
      "width": 340,
      "height": 140,
      "z_index": 22,
      "data": {
        "block_id": "inject-javascript-1"
      }
    },
    {
      "id": "note-block-element-exists-1",
      "element_type": "note",
      "title": "Note: Element Exists",
      "content": "Condition block: checks `ytd-comment-thread-renderer`. True / False branches control which path runs next. Keep enough space between branches so both connector lines are visible.",
      "color": "#ee5396",
      "position_x": 5000,
      "position_y": 240,
      "width": 340,
      "height": 139,
      "z_index": 22,
      "data": {
        "block_id": "element-exists-1"
      }
    },
    {
      "id": "note-block-structured-export-1",
      "element_type": "note",
      "title": "Note: Structured Export",
      "content": "Structured export with JS columns (title, view, date, thumbs_up, youtuber). These selectors are fragile — update if the site layout changes.",
      "color": "#ee5396",
      "position_x": 5360,
      "position_y": 240,
      "width": 340,
      "height": 126,
      "z_index": 22,
      "data": {
        "block_id": "structured-export-1"
      }
    },
    {
      "id": "note-block-loop-continue-1",
      "element_type": "note",
      "title": "Note: Loop Continue",
      "content": "Loop Continue advances a multi-URL or multi-text loop. Place at the end of the loop body with a clear back-edge to the loop start.",
      "color": "#ee5396",
      "position_x": 5720,
      "position_y": 240,
      "width": 340,
      "height": 123,
      "z_index": 22,
      "data": {
        "block_id": "loop-continue-1"
      }
    },
    {
      "id": "note-block-loop-continue-2",
      "element_type": "note",
      "title": "Note: Loop Continue",
      "content": "Loop Continue advances a multi-URL or multi-text loop. Place at the end of the loop body with a clear back-edge to the loop start.",
      "color": "#ee5396",
      "position_x": 5360,
      "position_y": 580,
      "width": 340,
      "height": 123,
      "z_index": 22,
      "data": {
        "block_id": "loop-continue-2"
      }
    }
  ]
}