{
  "version": "1.0.0",
  "exported_at": "2026-06-02T22:05:00.000Z",
  "project": {
    "name": "Iadfrance Data Scraper",
    "description": "Extracts IAD France real-estate listing data from https://www.iadfrance.fr/annonces/paris/vente: location, phone, prices, title, surface, room/bedroom counts, listing label, photo URL, advisor name, rating, and listing URL. Uses JavaScript to create visible synthetic export rows from listing links/cards and embedded JSON. Pagination is conservative: it only follows real forward page links with a changed URL/page number and remembers visited page URLs to prevent infinite loops. Some fields such as phone, advisor, rating, and price may be blank when IAD France exposes them only on detail pages or behind interactions.",
    "color": "bg-[#4589ff]",
    "template_id": "ai-generated"
  },
  "blocks": [
    {
      "block_id": "navigate-1",
      "block_type": "process",
      "title": "Navigate",
      "description": "Go to a URL",
      "position_x": 120,
      "position_y": 220,
      "config": {
        "url": "https://www.iadfrance.fr/annonces/paris/vente",
        "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": 456,
      "position_y": 220,
      "config": {
        "timeout": 30
      }
    },
    {
      "block_id": "element-exists-1",
      "block_type": "process",
      "title": "Element Exists",
      "description": "Check if element exists",
      "position_x": 792,
      "position_y": 220,
      "config": {
        "selector": "#didomi-notice-agree-button, button[id*='accept'], button[class*='accept'], button[id*='agree'], button[class*='agree']"
      }
    },
    {
      "block_id": "click-1",
      "block_type": "process",
      "title": "Click",
      "description": "Click on element",
      "position_x": 1128,
      "position_y": 520,
      "config": {
        "selector": "#didomi-notice-agree-button, button[id*='accept'], button[class*='accept'], button[id*='agree'], button[class*='agree']",
        "timeout": 8
      }
    },
    {
      "block_id": "sleep-1",
      "block_type": "process",
      "title": "Sleep",
      "description": "Wait for specified time",
      "position_x": 1464,
      "position_y": 520,
      "config": {
        "duration": 1
      }
    },
    {
      "block_id": "wait-for-element-1",
      "block_type": "process",
      "title": "Wait for Element",
      "description": "Wait until element appears",
      "position_x": 1800,
      "position_y": 520,
      "config": {
        "selector": "main, body",
        "timeout": 30,
        "visible": true
      }
    },
    {
      "block_id": "sleep-2",
      "block_type": "process",
      "title": "Sleep",
      "description": "Wait for specified time",
      "position_x": 2136,
      "position_y": 520,
      "config": {
        "duration": 3
      }
    },
    {
      "block_id": "inject-javascript-1",
      "block_type": "process",
      "title": "Inject JavaScript",
      "description": "Execute custom JavaScript",
      "position_x": 2472,
      "position_y": 520,
      "config": {
        "jsCode": "(() => { const norm = s => (s == null ? '' : String(s)).replace(/\\s+/g, ' ').trim(); const visible = el => { if (!el) return false; const st = getComputedStyle(el); const r = el.getBoundingClientRect(); return st.display !== 'none' && st.visibility !== 'hidden' && st.opacity !== '0' && r.width > 0 && r.height > 0; }; const abs = u => { try { return new URL(u || '', location.href).href; } catch(e) { return u || ''; } }; const cap = s => norm(s).replace(/(^|[-\\s])\\p{L}/gu, m => m.toUpperCase()).replace(/-/g, ' '); const currentKey = location.origin + location.pathname + location.search; const visited = new Set(JSON.parse(sessionStorage.getItem('uscraper_iad_visited_pages') || '[]')); visited.add(currentKey); sessionStorage.setItem('uscraper_iad_visited_pages', JSON.stringify(Array.from(visited).slice(-200))); document.querySelectorAll('#uscraper-iad-rows,[data-uscraper-iad-next]').forEach(e => { if (e.id === 'uscraper-iad-rows') e.remove(); else e.removeAttribute('data-uscraper-iad-next'); }); const rows = []; const seen = new Set(); function parseFromUrl(url) { let out = {}; try { const u = new URL(url, location.href); const path = decodeURIComponent(u.pathname); const m = path.match(/\\/annonce\\/([a-z-]+)-(vente|location)(?:-(\\d+)-pieces?)?-([a-zA-ZÀ-ÿ-]+?)-(\\d+(?:[,.]\\d+)?)m2\\//i); if (m) { out.type = cap(m[1]); out.transaction = m[2]; out.piece = m[3] || ''; out.city = cap(m[4]); out.surface = m[5].replace('.', ',') + ' m²'; } const id = path.match(/\\/r(\\d+)/i); out.id = id ? id[1] : ''; } catch(e) {} return out; } function add(o) { o = o || {}; const url = abs(o.url || o.href || o.link || ''); const parsed = parseFromUrl(url); const localisation = norm(o.localisation || o.location || o.city || o.ville || parsed.city || ''); const piece = norm(o.piece || o.pieces || o.rooms || parsed.piece || ''); const surface = norm(o.surface || o.area || parsed.surface || ''); let titre = norm(o.titre || o.title || o.name || o.label || ''); if (!titre && parsed.type) titre = parsed.type + (piece ? ' ' + piece + ' pièce' + (piece === '1' ? '' : 's') : '') + (surface ? ' de ' + surface : '') + (localisation ? ' à ' + localisation : ''); if (titre && localisation && !/\\([0-9]{5}\\)/.test(titre)) { const zip = (url.match(/-(\\d{5})(?:-|\\/)/) || [,''])[1]; if (zip && !titre.includes(zip)) titre += ' (' + zip + ')'; } const img = abs(o.photo || o.image || o.img || o.picture || ''); const key = (url || titre + '|' + img).toLowerCase(); if (!key || seen.has(key)) return; const looks = /\\/annonce\\//i.test(url) || /(appartement|maison|studio|duplex|terrain|villa|parking|garage|local|commerce|m²|m2|pi[eè]ces?)/i.test([titre, surface, norm(o.text || '')].join(' ')); if (!looks) return; seen.add(key); rows.push({ localisation, telephone: norm(o.telephone || o.phone || o.tel || ''), prix_1: norm(o.prix_1 || o.prix || o.price || ''), prix_2: norm(o.prix_2 || o.price_m2 || o.prix_m2 || ''), titre, surface, piece, chambre: norm(o.chambre || o.chambres || o.bedrooms || ''), etiquette: norm(o.etiquette || o.tag || o.badge || ''), photo: img, conseiller_immobilier: norm(o.conseiller_immobilier || o.conseiller || o.agent || o.advisor || ''), rating_du_personnel: norm(o.rating_du_personnel || o.rating || o.note || ''), url }); } function fromElement(el) { const txt = norm(el.innerText || el.textContent || ''); const a = el.matches && el.matches('a[href]') ? el : el.querySelector && el.querySelector('a[href*=\"/annonce/\"]'); const url = a ? abs(a.getAttribute('href')) : ''; const img = el.querySelector && el.querySelector('img'); const imgUrl = img ? (img.currentSrc || img.src || img.getAttribute('data-src') || img.getAttribute('srcset') || '') : ''; const imgAlt = norm(img && img.getAttribute('alt')); const price2 = (txt.match(/\\d[\\d\\s\\u202f\\u00a0.]*\\s*€\\s*\\/\\s*m[²2]/i) || [''])[0]; const prices = Array.from(txt.matchAll(/\\d[\\d\\s\\u202f\\u00a0.]*\\s*€/g)).map(m => norm(m[0])); const price1 = prices.find(p => !price2.includes(p)) || prices[0] || ''; const surface = (txt.match(/\\d+(?:[,.]\\d+)?\\s*m[²2]/i) || [''])[0].replace('m2', 'm²'); const piece = (txt.match(/(\\d+)\\s*pi[eè]ces?/i) || [,''])[1]; const chambre = (txt.match(/(\\d+)\\s*chambres?/i) || [,''])[1]; const etiquette = (txt.match(/Exclusivité|Nouveauté|Sous offre|Coup de cœur|Coup de coeur/i) || [''])[0]; const telephone = ((txt.match(/(?:\\+33|0)\\s*[1-9](?:[\\s.\\-]*\\d{2}){4}/) || [''])[0]).replace(/[\\s.\\-]/g, ''); const rating = (txt.match(/\\d(?:[,.]\\d)?\\s*\\/\\s*5/) || [''])[0].replace(/\\s+/g, ''); let title = norm(el.querySelector && (el.querySelector('h1,h2,h3,[class*=\"title\" i],[class*=\"titre\" i]') || {}).innerText) || imgAlt || norm(a && a.innerText) || ''; add({ titre: title, prix_1: price1, prix_2: price2, surface, piece, chambre, etiquette, telephone, rating_du_personnel: rating, photo: imgUrl, url, text: txt }); } Array.from(document.querySelectorAll('a[href*=\"/annonce/\"]')).forEach(a => { if (!visible(a)) return; const href = abs(a.getAttribute('href')); if (!/\\/annonce\\//i.test(href)) return; let card = a; for (let i = 0; i < 8 && card && card !== document.body; i++) { const r = card.getBoundingClientRect(); const txt = norm(card.innerText || ''); if (visible(card) && r.width > 120 && r.height > 40 && (/(€|m²|m2|pi[eè]ces?|chambres?|appartement|maison|studio|duplex|terrain|villa|parking|garage|local)/i.test(txt) || card.querySelector('img'))) break; card = card.parentElement; } fromElement(card && card !== document.body ? card : a); }); function flat(o, p = '', r = {}) { if (!o || typeof o !== 'object') return r; Object.entries(o).forEach(([k, v]) => { const nk = (p ? p + '_' : '') + k; if (v && typeof v === 'object' && !Array.isArray(v)) flat(v, nk, r); else if (!Array.isArray(v)) r[nk] = v; }); return r; } function pick(f, names) { const keys = Object.keys(f); for (const n of names) { const k = keys.find(x => x.toLowerCase().endsWith(n) || x.toLowerCase() === n); if (k && f[k] != null && f[k] !== '') return f[k]; } return ''; } function walk(x, depth = 0) { if (!x || depth > 6) return; if (Array.isArray(x)) { x.forEach(v => walk(v, depth + 1)); return; } if (typeof x === 'object') { const f = flat(x); const all = norm(Object.values(f).slice(0, 80).join(' ')); if (/(annonce|prix|price|surface|appartement|maison|studio|duplex|terrain|iad|\\/annonce\\/)/i.test(all)) add({ titre: pick(f, ['titre','title','name','nom','label']), prix_1: pick(f, ['prix','price','amount','loyer']), prix_2: pick(f, ['prixm2','prix_m2','price_m2']), surface: pick(f, ['surface','area','surfacehabitable']), piece: pick(f, ['pieces','piece','rooms','nbpieces','nb_pieces']), chambre: pick(f, ['chambres','chambre','bedrooms','nbchambres','nb_chambres']), localisation: pick(f, ['ville','city','localisation','location']), telephone: pick(f, ['telephone','phone','tel']), photo: pick(f, ['photo','image','img','src','urlphoto']), conseiller_immobilier: pick(f, ['conseiller','agent','advisor','nomconseiller']), rating_du_personnel: pick(f, ['rating','note']), url: pick(f, ['url','link','href','permalink','slug']), text: all }); Object.values(x).forEach(v => { if (v && typeof v === 'object') walk(v, depth + 1); }); } } ['__NUXT__','__NEXT_DATA__','__INITIAL_STATE__','__APOLLO_STATE__'].forEach(k => { try { if (window[k]) walk(window[k]); } catch(e) {} }); Array.from(document.querySelectorAll('script[type=\"application/json\"],script:not([src])')).forEach(s => { const txt = s.textContent || ''; if (!/(annonce|prix|price|surface|appartement|maison|iad)/i.test(txt)) return; try { walk(JSON.parse(txt)); } catch(e) {} }); const root = document.createElement('div'); root.id = 'uscraper-iad-rows'; root.style.cssText = 'display:block; position:relative; z-index:1; padding:1px; margin:1px; background:transparent;'; rows.forEach(o => { const row = document.createElement('div'); row.setAttribute('data-uscraper-iad-card', '1'); row.style.cssText = 'display:block; min-height:2px; width:2px; overflow:hidden; opacity:0.01;'; row.dataset.localisation = o.localisation || ''; row.dataset.telephone = o.telephone || ''; row.dataset.prix1 = o.prix_1 || ''; row.dataset.prix2 = o.prix_2 || ''; row.dataset.titre = o.titre || ''; row.dataset.surface = o.surface || ''; row.dataset.piece = o.piece || ''; row.dataset.chambre = o.chambre || ''; row.dataset.etiquette = o.etiquette || ''; row.dataset.photo = o.photo || ''; row.dataset.conseiller = o.conseiller_immobilier || ''; row.dataset.rating = o.rating_du_personnel || ''; row.dataset.url = o.url || ''; row.textContent = [o.titre, o.prix_1, o.surface, o.localisation, o.url].filter(Boolean).join(' | '); root.appendChild(row); }); document.body.prepend(root); const curPage = Number(new URL(location.href).searchParams.get('page') || (location.pathname.match(/\\/page\\/?(\\d+)/i) || [])[1] || 1); const candidates = Array.from(document.querySelectorAll('a[href]')).filter(visible).map(a => { let u; try { u = new URL(a.href, location.href); } catch(e) { return null; } const label = norm(a.innerText || a.getAttribute('aria-label') || a.getAttribute('title') || ''); const key = u.origin + u.pathname + u.search; const qp = Number(u.searchParams.get('page') || 0); const pp = Number((u.pathname.match(/(?:page|p)\\/?(\\d+)/i) || [])[1] || 0); const pg = qp || pp || 0; return { a, u, label, key, pg }; }).filter(x => x && x.key !== currentKey && !visited.has(x.key)); const next = candidates.find(x => x.pg && x.pg > curPage && x.pg <= curPage + 1) || candidates.find(x => /(suivant|next|›|»)/i.test(x.label) && (x.pg === 0 || x.pg > curPage)); if (next) next.a.setAttribute('data-uscraper-iad-next', '1'); return { rows: rows.length, hasNext: !!next, currentPage: curPage }; })();",
        "waitForCompletion": true,
        "timeout": 15
      }
    },
    {
      "block_id": "wait-for-element-2",
      "block_type": "process",
      "title": "Wait for Element",
      "description": "Wait until element appears",
      "position_x": 2808,
      "position_y": 520,
      "config": {
        "selector": "#uscraper-iad-rows [data-uscraper-iad-card='1']",
        "timeout": 20,
        "visible": true
      }
    },
    {
      "block_id": "structured-export-1",
      "block_type": "process",
      "title": "Structured Export",
      "description": "Export data with custom columns",
      "position_x": 3144,
      "position_y": 520,
      "config": {
        "rowSelector": "#uscraper-iad-rows [data-uscraper-iad-card='1']",
        "fileName": "iadfrance-data-scraper.csv",
        "saveLocation": "C:\\Users\\theskd\\Documents\\UScraper\\templates",
        "includeHeaders": true,
        "fileMode": "append",
        "columns": [
          {
            "name": "localisation",
            "selector": "ROW.dataset.localisation || ''",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "telephone",
            "selector": "ROW.dataset.telephone || ''",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "prix_1",
            "selector": "ROW.dataset.prix1 || ''",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "prix_2",
            "selector": "ROW.dataset.prix2 || ''",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "titre",
            "selector": "ROW.dataset.titre || ROW.textContent || ''",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "surface",
            "selector": "ROW.dataset.surface || ''",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "piece",
            "selector": "ROW.dataset.piece || ''",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "chambre",
            "selector": "ROW.dataset.chambre || ''",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "etiquette",
            "selector": "ROW.dataset.etiquette || ''",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "photo",
            "selector": "ROW.dataset.photo || ''",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "conseiller_immobilier",
            "selector": "ROW.dataset.conseiller || ''",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "rating_du_personnel",
            "selector": "ROW.dataset.rating || ''",
            "attribute": "text",
            "isJs": true
          },
          {
            "name": "url",
            "selector": "ROW.dataset.url || ''",
            "attribute": "text",
            "isJs": true
          }
        ]
      }
    },
    {
      "block_id": "element-exists-2",
      "block_type": "process",
      "title": "Element Exists",
      "description": "Check if element exists",
      "position_x": 3480,
      "position_y": 520,
      "config": {
        "selector": "[data-uscraper-iad-next='1']"
      }
    },
    {
      "block_id": "click-2",
      "block_type": "process",
      "title": "Click",
      "description": "Click on element",
      "position_x": 3816,
      "position_y": 520,
      "config": {
        "selector": "[data-uscraper-iad-next='1']",
        "timeout": 10
      }
    },
    {
      "block_id": "wait-for-page-load-2",
      "block_type": "process",
      "title": "Wait for Page Load",
      "description": "Wait for page to finish loading",
      "position_x": 4152,
      "position_y": 520,
      "config": {
        "timeout": 30
      }
    },
    {
      "block_id": "sleep-3",
      "block_type": "process",
      "title": "Sleep",
      "description": "Wait for specified time",
      "position_x": 4488,
      "position_y": 758,
      "config": {
        "duration": 2
      }
    },
    {
      "block_id": "end-1",
      "block_type": "output",
      "title": "End",
      "description": "Terminate execution flow",
      "position_x": 3480,
      "position_y": 520,
      "config": {}
    }
  ],
  "connections": [
    {
      "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": "element-exists-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "element-exists-1",
      "from_connector_id": "true",
      "to_block_id": "click-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "click-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": "wait-for-element-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "element-exists-1",
      "from_connector_id": "false",
      "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-2",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "sleep-2",
      "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": "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": "element-exists-2",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "element-exists-2",
      "from_connector_id": "true",
      "to_block_id": "click-2",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "click-2",
      "from_connector_id": "right",
      "to_block_id": "wait-for-page-load-2",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "wait-for-page-load-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": "inject-javascript-1",
      "to_connector_id": "left"
    },
    {
      "from_block_id": "element-exists-2",
      "from_connector_id": "false",
      "to_block_id": "end-1",
      "to_connector_id": "left"
    }
  ],
  "canvas_elements": [
    {
      "id": "group-load",
      "element_type": "group",
      "title": "Page Load",
      "color": "#08bdba",
      "position_x": 48,
      "position_y": 116,
      "width": 4688,
      "height": 834,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "navigate-1",
          "wait-for-page-load-1",
          "sleep-1",
          "wait-for-element-1",
          "sleep-2",
          "wait-for-element-2",
          "wait-for-page-load-2",
          "sleep-3"
        ]
      }
    },
    {
      "id": "group-pagination",
      "element_type": "group",
      "title": "Pagination Loop",
      "color": "#ff832b",
      "position_x": 720,
      "position_y": 116,
      "width": 3344,
      "height": 596,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "element-exists-1",
          "click-1",
          "element-exists-2",
          "click-2"
        ]
      }
    },
    {
      "id": "group-interaction",
      "element_type": "group",
      "title": "Interaction",
      "color": "#a56eff",
      "position_x": 2400,
      "position_y": 416,
      "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": 3072,
      "position_y": 416,
      "width": 380,
      "height": 296,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "structured-export-1"
        ]
      }
    },
    {
      "id": "group-control",
      "element_type": "group",
      "title": "Control Flow",
      "color": "#8d8d8d",
      "position_x": 3408,
      "position_y": 416,
      "width": 380,
      "height": 296,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "end-1"
        ]
      }
    },
    {
      "id": "note-overview",
      "element_type": "note",
      "title": "Overview",
      "content": "Extracts IAD France real-estate listing data from https://www.iadfrance.fr/annonces/paris/vente: location, phone, prices, title, surface, room/bedroom counts, listing label, photo URL, advisor name, rating, and listing URL. Uses JavaScript to create visible synthetic export rows from listing links/cards and embedded JSON. Pagination is conservative: it only follows real forward page links with a changed URL/page number and remembers visited page URLs to prevent infinite loops. Some fields such as phone, advisor, rating, and price may be blank when IAD France exposes them only on detail pages or behind interactions.",
      "color": "#f1c21b",
      "position_x": 80,
      "position_y": 20,
      "width": 480,
      "height": 160,
      "z_index": 22,
      "data": {}
    },
    {
      "id": "note-block-element-exists-1",
      "element_type": "note",
      "title": "Note: Element Exists",
      "content": "Condition block: checks `#didomi-notice-agree-button, button[id*='accept'], button[class*='accept'], button[id*='agree'], button[class*='agree']`. True / False branches control which path runs next. Keep enough space between branches so both connector lines are visible.",
      "color": "#ee5396",
      "position_x": 992,
      "position_y": 200,
      "width": 340,
      "height": 170,
      "z_index": 22,
      "data": {
        "block_id": "element-exists-1"
      }
    },
    {
      "id": "note-block-inject-javascript-1",
      "element_type": "note",
      "title": "Note: Inject JavaScript",
      "content": "Runs custom JavaScript in the page: `(() => { const norm = s => (s == null ? '' : String(s)).replace(/\\s+/g, ' ').trim(); const visible =...` Verify in browser if results are empty.",
      "color": "#ee5396",
      "position_x": 2672,
      "position_y": 500,
      "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": "Structured export with JS columns (localisation, telephone, prix_1, prix_2, titre). These selectors are fragile — update if the site layout changes.",
      "color": "#ee5396",
      "position_x": 3344,
      "position_y": 500,
      "width": 340,
      "height": 129,
      "z_index": 22,
      "data": {
        "block_id": "structured-export-1"
      }
    },
    {
      "id": "note-block-element-exists-2",
      "element_type": "note",
      "title": "Note: Element Exists",
      "content": "Condition block: checks `[data-uscraper-iad-next='1']`. True / False branches control which path runs next. Keep enough space between branches so both connector lines are visible.",
      "color": "#ee5396",
      "position_x": 3680,
      "position_y": 500,
      "width": 340,
      "height": 139,
      "z_index": 22,
      "data": {
        "block_id": "element-exists-2"
      }
    },
    {
      "id": "note-block-click-2",
      "element_type": "note",
      "title": "Note: Click",
      "content": "Pagination click — add waits after this block; the page reloads asynchronously.",
      "color": "#ee5396",
      "position_x": 4016,
      "position_y": 500,
      "width": 316,
      "height": 106,
      "z_index": 22,
      "data": {
        "block_id": "click-2"
      }
    }
  ]
}