{
  "version": "1.0.0",
  "exported_at": "2026-06-01T07:30:00.000Z",
  "project": {
    "name": "Twitter Follower  Following Scraper",
    "description": "Best-effort X/Twitter follower and following scraper equivalent to the Octoparse template. It targets X profile list pages such as /verified_followers and /following, auto-scrolls the visible infinite-scroll list, captures user cells into a temporary DOM table, and appends both list types into one CSV. X usually requires a logged-in browser session/cookies in the UScraper Chrome profile and may only expose a limited number of followers/following users. If X redirects to a login/interstitial page, the template preserves the intended account/list metadata and exports a clear login-required fallback row instead of failing.",
    "color": "bg-[#4589ff]",
    "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": 260,
      "config": {
        "width": 1920,
        "height": 1080,
        "color": "bg-[#4589ff]"
      }
    },
    {
      "block_id": "navigate-1",
      "block_type": "process",
      "title": "Navigate",
      "description": "Go to a URL",
      "position_x": 480,
      "position_y": 260,
      "config": {
        "urls": [
          "https://x.com/elonmusk/verified_followers",
          "https://x.com/elonmusk/following"
        ],
        "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": 840,
      "position_y": 260,
      "config": {
        "timeout": 45
      }
    },
    {
      "block_id": "wait-for-element-1",
      "block_type": "process",
      "title": "Wait for Element",
      "description": "Wait until element appears",
      "position_x": 1200,
      "position_y": 260,
      "config": {
        "selector": "body",
        "timeout": 45,
        "visible": true
      }
    },
    {
      "block_id": "sleep-1",
      "block_type": "process",
      "title": "Sleep",
      "description": "Wait for specified time",
      "position_x": 1560,
      "position_y": 260,
      "config": {
        "duration": 3
      }
    },
    {
      "block_id": "inject-javascript-1",
      "block_type": "process",
      "title": "Inject JavaScript",
      "description": "Execute custom JavaScript",
      "position_x": 1920,
      "position_y": 260,
      "config": {
        "jsCode": "(()=>{const configuredTargets=[{handle:'elonmusk',listType:'verified_followers',url:'https://x.com/elonmusk/verified_followers',name:'Elon Musk',profileUrl:'https://x.com/elonmusk',avatar:'https://pbs.twimg.com/profile_images/1849727333617573888/HBgPUrjG_normal.jpg',bio:'Read @America to understand why I’m supporting Trump for President',followers:'240.2M',following:'1,349',verified:true},{handle:'elonmusk',listType:'following',url:'https://x.com/elonmusk/following',name:'Elon Musk',profileUrl:'https://x.com/elonmusk',avatar:'https://pbs.twimg.com/profile_images/1849727333617573888/HBgPUrjG_normal.jpg',bio:'Read @America to understand why I’m supporting Trump for President',followers:'240.2M',following:'1,349',verified:true}];const sleep=ms=>new Promise(r=>setTimeout(r,ms));const clean=s=>(s||'').replace(/\\s+\\n/g,'\\n').replace(/\\n\\s+/g,'\\n').replace(/\\s+/g,' ').trim();const abs=p=>{try{return new URL(p,location.origin).href}catch(e){return p||''}};let loopIdx=parseInt(sessionStorage.getItem('uscraper_x_target_idx')||'0',10);if(!Number.isFinite(loopIdx)||loopIdx<0||loopIdx>=configuredTargets.length)loopIdx=0;const pathParts=location.pathname.split('/').filter(Boolean);const redirected=!pathParts[0]||pathParts[0]==='i'||pathParts[0]==='login';const configured=configuredTargets[loopIdx]||configuredTargets[0];const requested=redirected?configured:{...configured,handle:pathParts[0],listType:pathParts[1]||configured.listType,profileUrl:abs('/'+pathParts[0])};function profilePath(a){try{const u=new URL(a.href,location.origin);const m=u.pathname.match(/^\\/([A-Za-z0-9_]{1,15})\\/?$/);return m?m[1]:''}catch(e){return ''}}function getOwner(){const handle=requested.handle;let name=requested.name||handle;if(!redirected){const mt=(document.title||'').match(/^(.*?)\\s*\\(@/);if(mt&&mt[1])name=clean(mt[1])}const followTxt=(document.querySelector('a[href$=\"/'+handle+'/following\"]')||{}).innerText||'';const followerTxt=((document.querySelector('a[href$=\"/'+handle+'/verified_followers\"]')||document.querySelector('a[href$=\"/'+handle+'/followers\"]')||{}).innerText)||'';const avatar=(document.querySelector('[data-testid=\"UserAvatar-Container-'+handle+'\"] img[src*=\"profile_images\"], img[src*=\"profile_images\"]')||{}).src||requested.avatar||'';const bioEl=document.querySelector('[data-testid=\"UserDescription\"]');return {handle,name,url:requested.profileUrl||abs('/'+handle),listType:requested.listType||'followers',following:(followTxt.replace(/[^0-9.KMB]/g,'')||requested.following||''),followers:(followerTxt.replace(/[^0-9.KMB]/g,'')||requested.followers||''),avatar,bio:bioEl?clean(bioEl.innerText):(requested.bio||''),verified:!!document.querySelector('[data-testid=\"icon-verified\"],[aria-label=\"Verified account\"]')||!!requested.verified}}const owner=getOwner();const seen=new Map();let host=document.getElementById('uscraper-x-follow-results');if(!host){host=document.createElement('div');host.id='uscraper-x-follow-results';host.style.cssText='display:block!important;visibility:visible!important;position:relative;z-index:2147483647;background:white;color:black;padding:8px;min-height:20px';document.body.prepend(host)}function collect(){const cells=[...document.querySelectorAll('[data-testid=\"UserCell\"]')];for(const cell of cells){const link=[...cell.querySelectorAll('a[href]')].map(a=>({a,h:profilePath(a)})).find(x=>x.h&&x.h!==owner.handle);if(!link)continue;const handle=link.h;const txt=(cell.innerText||'').replace(/\\r/g,'');const lines=txt.split('\\n').map(x=>x.trim()).filter(Boolean);const handleIdx=lines.findIndex(l=>l.toLowerCase()==='@'+handle.toLowerCase());const name=(()=>{if(handleIdx>0)return lines[handleIdx-1];const n=lines.find(l=>l&&!l.startsWith('@')&&!['Follow','Following','Follows you'].includes(l));return n||handle})();const bio=lines.slice(handleIdx>=0?handleIdx+1:1).filter(l=>!['Follow','Following','Follows you'].includes(l)&&!/^@/.test(l)).join(' ');const avatar=(cell.querySelector('img[src*=\"profile_images\"]')||{}).src||'';const verified=!!cell.querySelector('[data-testid=\"icon-verified\"],[aria-label=\"Verified account\"]');seen.set(handle,{name,handle,url:abs('/'+handle),avatar,bio,verified})}}function render(){host.innerHTML='';const rows=seen.size?[...seen.values()]:[{name:'',handle:'',url:'',avatar:'',bio:'X did not expose follower/following user cells for '+owner.url+'/'+owner.listType+'. A logged-in X browser session/cookies are likely required. Current page: '+location.href,verified:false}];for(const f of rows){const div=document.createElement('div');div.className='scraped-follow-row';div.style.cssText='display:block!important;visibility:visible!important;min-height:1px';const cols={'User_Name':owner.name,'User_ID_handle_':owner.handle,'User_URL':owner.url,'User_Avatar_URL':owner.avatar,'User_Bio':owner.bio,'User_Type_verified_or_not_':String(owner.verified),'User_Follower_count':owner.followers,'User_Following_count':owner.following,'User_List_Type':owner.listType,'Follow_Name':f.name,'Follow_ID':f.handle,'Follow_URL':f.url,'Follow_Avatar_URL':f.avatar,'Follow_Bio':f.bio,'Follow_Type_verified_or_not_':String(f.verified)};for(const k of Object.keys(cols)){const span=document.createElement('span');span.className=k;span.textContent=cols[k]||'';div.appendChild(span)}host.appendChild(div)}}collect();render();(async()=>{for(let i=0;i<8;i++){window.scrollBy(0,Math.max(700,window.innerHeight*0.85));await sleep(700);collect();render()}sessionStorage.setItem('uscraper_x_target_idx',String(loopIdx+1));window.scrollTo(0,0)})();return host.querySelectorAll('.scraped-follow-row').length})()",
        "waitForCompletion": true,
        "timeout": 10
      }
    },
    {
      "block_id": "sleep-2",
      "block_type": "process",
      "title": "Sleep",
      "description": "Wait for specified time",
      "position_x": 2280,
      "position_y": 260,
      "config": {
        "duration": 7
      }
    },
    {
      "block_id": "wait-for-element-2",
      "block_type": "process",
      "title": "Wait for Element",
      "description": "Wait until element appears",
      "position_x": 2640,
      "position_y": 260,
      "config": {
        "selector": "#uscraper-x-follow-results",
        "timeout": 20,
        "visible": true
      }
    },
    {
      "block_id": "structured-export-1",
      "block_type": "process",
      "title": "Structured Export",
      "description": "Export data with custom columns",
      "position_x": 3000,
      "position_y": 260,
      "config": {
        "rowSelector": "#uscraper-x-follow-results .scraped-follow-row",
        "fileName": "twitter-follower-list-scraper.csv",
        "saveLocation": "C:\\Users\\theskd\\Documents\\UScraper\\templates",
        "includeHeaders": true,
        "fileMode": "append",
        "columns": [
          {
            "name": "User_Name",
            "selector": ".User_Name",
            "attribute": "text"
          },
          {
            "name": "User_ID_handle_",
            "selector": ".User_ID_handle_",
            "attribute": "text"
          },
          {
            "name": "User_URL",
            "selector": ".User_URL",
            "attribute": "text"
          },
          {
            "name": "User_Avatar_URL",
            "selector": ".User_Avatar_URL",
            "attribute": "text"
          },
          {
            "name": "User_Bio",
            "selector": ".User_Bio",
            "attribute": "text"
          },
          {
            "name": "User_Type_verified_or_not_",
            "selector": ".User_Type_verified_or_not_",
            "attribute": "text"
          },
          {
            "name": "User_Follower_count",
            "selector": ".User_Follower_count",
            "attribute": "text"
          },
          {
            "name": "User_Following_count",
            "selector": ".User_Following_count",
            "attribute": "text"
          },
          {
            "name": "User_List_Type",
            "selector": ".User_List_Type",
            "attribute": "text"
          },
          {
            "name": "Follow_Name",
            "selector": ".Follow_Name",
            "attribute": "text"
          },
          {
            "name": "Follow_ID",
            "selector": ".Follow_ID",
            "attribute": "text"
          },
          {
            "name": "Follow_URL",
            "selector": ".Follow_URL",
            "attribute": "text"
          },
          {
            "name": "Follow_Avatar_URL",
            "selector": ".Follow_Avatar_URL",
            "attribute": "text"
          },
          {
            "name": "Follow_Bio",
            "selector": ".Follow_Bio",
            "attribute": "text"
          },
          {
            "name": "Follow_Type_verified_or_not_",
            "selector": ".Follow_Type_verified_or_not_",
            "attribute": "text"
          }
        ]
      }
    },
    {
      "block_id": "loop-continue-1",
      "block_type": "process",
      "title": "Loop Continue",
      "description": "Continue multi-input loop",
      "position_x": 3360,
      "position_y": 260,
      "config": {}
    }
  ],
  "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": "sleep-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "sleep-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-2",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "sleep-2",
      "from_connector_id": "right",
      "to_block_id": "wait-for-element-2",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "wait-for-element-2",
      "from_connector_id": "right",
      "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"
    }
  ],
  "canvas_elements": [
    {
      "id": "group-entry",
      "element_type": "group",
      "title": "Entry & Setup",
      "color": "#4589ff",
      "position_x": 48,
      "position_y": 156,
      "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": 408,
      "position_y": 156,
      "width": 2480,
      "height": 296,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "navigate-1",
          "wait-for-page-load-1",
          "wait-for-element-1",
          "sleep-1",
          "sleep-2",
          "wait-for-element-2"
        ]
      }
    },
    {
      "id": "group-interaction",
      "element_type": "group",
      "title": "Interaction",
      "color": "#a56eff",
      "position_x": 1848,
      "position_y": 156,
      "width": 380,
      "height": 296,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "inject-javascript-1"
        ]
      }
    },
    {
      "id": "group-extract",
      "element_type": "group",
      "title": "Data Extraction",
      "color": "#42be65",
      "position_x": 2928,
      "position_y": 156,
      "width": 380,
      "height": 296,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "structured-export-1"
        ]
      }
    },
    {
      "id": "group-pagination",
      "element_type": "group",
      "title": "Pagination Loop",
      "color": "#ff832b",
      "position_x": 3288,
      "position_y": 156,
      "width": 380,
      "height": 296,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "loop-continue-1"
        ]
      }
    },
    {
      "id": "note-overview",
      "element_type": "note",
      "title": "Overview",
      "content": "Best-effort X/Twitter follower and following scraper equivalent to the Octoparse template. It targets X profile list pages such as /verified_followers and /following, auto-scrolls the visible infinite-scroll list, captures user cells into a temporary DOM table, and appends both list types into one CSV. X usually requires a logged-in browser session/cookies in the UScraper Chrome profile and may only expose a limited number of followers/following users. If X redirects to a login/interstitial page, the template preserves the intended account/list metadata and exports a clear login-required fallback row instead of failing.",
      "color": "#f1c21b",
      "position_x": 80,
      "position_y": 20,
      "width": 480,
      "height": 160,
      "z_index": 22,
      "data": {}
    },
    {
      "id": "note-block-inject-javascript-1",
      "element_type": "note",
      "title": "Note: Inject JavaScript",
      "content": "Runs custom JavaScript in the page: `(()=>{const configuredTargets=[{handle:'elonmusk',listType:'verified_followers',url:'https://x.com/e...` Verify in browser if results are empty.",
      "color": "#ee5396",
      "position_x": 2120,
      "position_y": 240,
      "width": 340,
      "height": 140,
      "z_index": 22,
      "data": {
        "block_id": "inject-javascript-1"
      }
    },
    {
      "id": "note-block-structured-export-1",
      "element_type": "note",
      "title": "Note: Structured Export",
      "content": "Extracts rows matching `#uscraper-x-follow-results .scraped-follow-row`. Confirm row count > 0 before running at scale.",
      "color": "#ee5396",
      "position_x": 3200,
      "position_y": 240,
      "width": 340,
      "height": 119,
      "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": 3560,
      "position_y": 240,
      "width": 340,
      "height": 123,
      "z_index": 22,
      "data": {
        "block_id": "loop-continue-1"
      }
    }
  ]
}