{
  "version": "1.0.0",
  "exported_at": "2026-06-01T00:00:00.000Z",
  "project": {
    "name": "Bookingcom Hotel Details Scraper for Germany",
    "description": "Equivalent best-effort UScraper template for the Octoparse Booking.com Hotel Details Scraper for Germany. It visits multiple Booking.com German hotel detail URLs and exports hotel title, address, hotel-level review score/grade/count, reviewer name, nationality, review date/title, advantage, disadvantage, personal score, room type, stay details, and traveler type. Navigation strategy: uses a multi-URL navigate loop for supplied hotel detail URLs. For each hotel, an injected script calls Booking.com's same-origin reviewlist.html endpoint in paginated offsets and creates stable .uscraper-review-row elements for all fetched reviews up to a safety cap; Structured Export appends those rows to one CSV. Limitations: Booking.com may block/rate-limit automation or restrict review endpoint responses; if review access is blocked, the template emits a hotel-level fallback row so the run completes.",
    "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": 220,
      "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": 220,
      "config": {
        "urls": [
          "https://www.booking.com/hotel/de/park-inn-berlin-alexanderplatz.de.html?aid=304142&label=gen173nr-1DCAEoggI46AdIM1gEaIkCiAEBmAEHuAEXyAEM2AED6AEBiAIBqAIDuALHzL2aBsACAdICJDhmZGFlYjk5LTZiNzEtNGM0Yy05MzFjLWRmNTRlZTBmODExNNgCBOACAQ&sid=5f5663f2632c256f06c3d5a0becc6bd3&all_sr_blocks=6384732_129565388_0_34_0;checkin=2022-10-26;checkout=2022-10-27;dcs_click=1;dest_id=-1746443;dest_type=city;dist=0;group_adults=2;group_children=0;hapos=4;highlighted_blocks=6384732_129565388_0_34_0;hpos=4;matching_block_id=6384732_129565388_0_34_0;no_rooms=1;req_adults=2;req_children=0;room1=A,A;sb_price_type=total;sr_order=popularity;sr_pri_blocks=6384732_129565388_0_34_0__19900;srepoch=1666148128;srpvid=fe4a148fd401027c;type=total;ucfs=1&#hotelTmpl",
          "https://www.booking.com/hotel/de/grimms-am-potsdamer-platz.de.html?aid=2311236&label=de-row-booking-desktop-ygp5roBi33Y2htC7dIGmcgS652829002552%3Apl%3Ata%3Ap1%3Ap2%3Aac%3Aap%3Aneg%3Afi%3Atikwd-334113629%3Alp2158%3Ali%3Adec%3Adm&sid=010aaa979e4b24fac1245a444a401290&dest_id=-1746443;dest_type=city;dist=0;group_adults=1;group_children=0;hapos=1;hpos=1;no_rooms=1;req_adults=1;req_children=0;room1=A;sb_price_type=total;sr_order=popularity;srepoch=1715142576;srpvid=ca9c1f93846a016f;type=total;ucfs=1&"
        ],
        "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": 220,
      "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": 1200,
      "position_y": 220,
      "config": {
        "selector": "body",
        "timeout": 30,
        "visible": true,
        "color": "bg-[#08bdba]"
      }
    },
    {
      "block_id": "sleep-1",
      "block_type": "process",
      "title": "Sleep",
      "description": "Wait for specified time",
      "position_x": 1560,
      "position_y": 220,
      "config": {
        "duration": 2,
        "color": "bg-[#08bdba]"
      }
    },
    {
      "block_id": "inject-javascript-1",
      "block_type": "process",
      "title": "Inject JavaScript",
      "description": "Run JavaScript on the page",
      "position_x": 1920,
      "position_y": 220,
      "config": {
        "jsCode": "(async()=>{const clean=s=>(s||'').replace(/\\s+/g,' ').trim();const pick=(root,sels)=>{for(const sel of sels){try{const el=root.querySelector(sel);const t=clean(el&&(el.textContent||el.getAttribute('content')||el.getAttribute('aria-label')));if(t)return t;}catch(e){}}return '';};const pickAll=(root,sels)=>{for(const sel of sels){try{const els=[...root.querySelectorAll(sel)].map(e=>clean(e.textContent)).filter(Boolean);if(els.length)return els;}catch(e){}}return [];};const path=location.pathname;let slug='';let m=path.match(/\\/hotel\\/de\\/([^/]+?)\\.html/i);if(m)slug=m[1].replace(/\\.[a-z]{2}(?:-[a-z]{2})?$/i,'');if(!slug){const parts=path.split('/').filter(Boolean);slug=(parts.pop()||'').replace(/\\.html.*$/,'').replace(/\\.[a-z]{2}(?:-[a-z]{2})?$/i,'');}const hotelTitle=(()=>{const t=pick(document,['h2.pp-header__title','h2[data-testid=title]','.pp-header__title','.standalone_header_hotel_link','.hp__hotel-name','[data-testid=title]','h2','h1']);return clean(t.replace(/\\s*\\(.*?\\)\\s*$/,'').replace(/\\s*Deals$/i,'').replace(/\\s*Angebote$/i,''));})();const address=pick(document,['[data-testid=address]','.hp_address_subtitle','.hotel_address','.address']);const scoreText=pick(document,['[data-testid=review-score-right-component]','.big_review_score_detailed','.review-score-widget','.average_score','a[href*=blockdisplay4]']);const scoreMatch=scoreText.match(/\\d+[\\.,]?\\d*/);const hotelScore=scoreMatch?scoreMatch[0]:'';const bodyText=clean(document.body.textContent);const gradeMatch=bodyText.match(/(Sehr gut|Gut|Hervorragend|Fabelhaft|Ausgezeichnet|Ansprechend|Very Good|Good|Excellent|Wonderful|Superb|Fabulous|Pleasant)/i);const hotelGrade=gradeMatch?gradeMatch[0]:'';const countMatch=bodyText.match(/([\\d.,]+)\\s*(reviews|Bewertungen)/i);const reviewCount=countMatch?countMatch[1]:'';const old=document.getElementById('uscraper-synthetic-reviews');if(old)old.remove();const container=document.createElement('div');container.id='uscraper-synthetic-reviews';container.style.cssText='display:block;position:absolute;left:0;top:0;width:20px;min-height:20px;opacity:0.02;background:#fff;color:#000;z-index:1;';document.body.prepend(container);const seen=new Set();const makeRow=(data)=>{const row=document.createElement('div');row.className='uscraper-review-row';row.style.cssText='display:block;width:12px;height:12px;margin:1px;overflow:hidden;background:#fff;color:#000;';const base={input_url:location.href,titel:hotelTitle,adresse:address,kundenbewertung:hotelScore,bewertungsgrad:hotelGrade,anzahl_der_bewertungen:reviewCount};Object.entries({...base,...data}).forEach(([k,v])=>row.setAttribute('data-'+k,clean(v)));row.textContent=clean((data.name||'review')+' '+(data.bewertungstitel||'')+' '+(data.vorteil||'')+' '+(data.nachteil||''))||hotelTitle||'booking review';container.appendChild(row);};const extractReview=(el)=>{const txt=clean(el.textContent);const name=pick(el,['[data-testid=reviewer-name]','.reviewer_name','.bui-avatar-block__title','.bui-avatar-block__title a','.review_item_reviewer h4','.review_item_reviewer']);const nationality=pick(el,['[data-testid=reviewer-country]','.reviewer_country','.bui-avatar-block__subtitle','[class*=country]'])||clean((el.querySelector('img[alt]')||{}).alt);const date=pick(el,['[data-testid=review-date]','.review_item_date','.c-review-block__date','[class*=review-date]']).replace(/^Reviewed:\\s*/i,'').replace(/^Bewertet:\\s*/i,'');const title=pick(el,['[data-testid=review-title]','.review_item_header_content','.review_item_header h3','h3','.c-review-block__title','[class*=review-title]']).replace(/^“|”$/g,'');const positive=pick(el,['[data-testid=review-positive-text]','[data-testid=review-positive]','.review_pos .review_item_review_content','.review_pos','.c-review__row--positive','[class*=positive]']).replace(/^Liked\\s*·\\s*/i,'').replace(/^Positiv\\s*·\\s*/i,'');const negative=pick(el,['[data-testid=review-negative-text]','[data-testid=review-negative]','.review_neg .review_item_review_content','.review_neg','.c-review__row--negative','[class*=negative]']).replace(/^Disliked\\s*·\\s*/i,'').replace(/^Negativ\\s*·\\s*/i,'');const personalText=pick(el,['[data-testid=review-score]','.review-score-badge','.bui-review-score__badge','.review_item_review_score','[class*=review-score]']);const pm=personalText.match(/\\d+[\\.,]?\\d*/);const room=pick(el,['[data-testid=review-room-name]','[data-testid=review-room]','.room_info_heading','.review_room_info .room_info_heading','.c-review-block__room-info','[class*=room]']);const details=pick(el,['[data-testid=review-stay-date]','[data-testid=review-num-nights]','.review_staydate','.c-review-block__stay-date','[class*=stay]']);let person='';const tags=pickAll(el,['.review_info_tags .review_info_tag','.bui-list__item','.review_info_tag','[data-testid=review-traveler-type]','[data-testid=review-traveller-type]','.c-review-block__guest-type','[class*=traveler]','[class*=traveller]']);person=tags.find(x=>/(Alleinreisende:r|Alleinreisende|Familie|Paar|Gruppe|Geschäftsreisende|Solo traveler|Family|Couple|Group|Business traveler|Friends)/i.test(x))||'';if(!person){const mm=txt.match(/(Alleinreisende:r|Alleinreisende|Familie|Paar|Gruppe|Geschäftsreisende|Solo traveler|Family|Couple|Group|Business traveler|Friends)/i);person=mm?mm[0]:'';}return {name,nationalitaet:nationality,bewertung_abgegeben:date,bewertungstitel:title,vorteil:positive,nachteil:negative,persoenliche_kundenbewertung:pm?pm[0]:'',zimmer_typ:room,details,person_typ:person,_text:txt};};const addFromDoc=(doc)=>{let rows=[...doc.querySelectorAll('.review_item,[data-testid=\"review-card\"],li[data-testid=\"review-card\"],[itemprop=\"review\"]')];rows=rows.filter(el=>clean(el.textContent).length>80);let added=0;for(const el of rows){const d=extractReview(el);const key=(d.name+'|'+d.bewertung_abgegeben+'|'+d.bewertungstitel+'|'+d.vorteil+'|'+d.nachteil).slice(0,300);if(seen.has(key)||(!d.name&&!d.vorteil&&!d.nachteil&&!d.bewertungstitel))continue;seen.add(key);delete d._text;makeRow(d);added++;}return added;};let totalAdded=0;if(slug){for(let offset=0;offset<=475;offset+=25){try{const params=new URLSearchParams({cc1:'de',pagename:slug,type:'total',sort:'f_recent_desc',rows:'25',offset:String(offset),lang:'de',r_lang:'de'});const res=await fetch('/reviewlist.html?'+params.toString(),{credentials:'include'});if(!res.ok&&res.status!==0)break;const html=await res.text();if(!html||html.length<200)break;const doc=new DOMParser().parseFromString(html,'text/html');const added=addFromDoc(doc);totalAdded+=added;if(added===0)break;if(totalAdded>=500)break;}catch(e){break;}}}if(totalAdded===0){const visible=[...document.querySelectorAll('[data-testid=\"review-card\"],.review_item,[itemprop=\"review\"]')].filter(el=>{const t=clean(el.textContent);return t.length>80&&!/Guests who stayed here loved|Select topics to read reviews/i.test(t)&&/(Liked|Disliked|Positiv|Negativ|Reviewed|Bewertet|reviewer|traveler|traveller)/i.test(t);});for(const el of visible){const d=extractReview(el);const key=(d.name+'|'+d.bewertung_abgegeben+'|'+d.bewertungstitel+'|'+d.vorteil+'|'+d.nachteil).slice(0,300);if(seen.has(key)||(!d.name&&!d.vorteil&&!d.nachteil&&!d.bewertungstitel))continue;seen.add(key);delete d._text;makeRow(d);totalAdded++;}}if(!container.querySelector('.uscraper-review-row')){makeRow({name:'',nationalitaet:'',bewertung_abgegeben:'',bewertungstitel:'',vorteil:'',nachteil:'',persoenliche_kundenbewertung:'',zimmer_typ:'',details:'',person_typ:''});}})();",
        "waitForCompletion": true,
        "timeout": 30,
        "color": "bg-[#a56eff]"
      }
    },
    {
      "block_id": "wait-for-element-2",
      "block_type": "process",
      "title": "Wait for Element",
      "description": "Wait until element appears",
      "position_x": 2280,
      "position_y": 220,
      "config": {
        "selector": ".uscraper-review-row",
        "timeout": 30,
        "visible": true,
        "color": "bg-[#08bdba]"
      }
    },
    {
      "block_id": "structured-export-1",
      "block_type": "process",
      "title": "Structured Export",
      "description": "Export data with custom columns",
      "position_x": 2640,
      "position_y": 220,
      "config": {
        "rowSelector": ".uscraper-review-row",
        "fileName": "booking-hotel-details-scraper-for-germany.csv",
        "saveLocation": "C:\\Users\\theskd\\Documents\\UScraper\\templates",
        "includeHeaders": true,
        "fileMode": "append",
        "color": "bg-[#42be65]",
        "columns": [
          {
            "name": "input_url",
            "selector": "",
            "attribute": "data-input_url"
          },
          {
            "name": "titel",
            "selector": "",
            "attribute": "data-titel"
          },
          {
            "name": "adresse",
            "selector": "",
            "attribute": "data-adresse"
          },
          {
            "name": "kundenbewertung",
            "selector": "",
            "attribute": "data-kundenbewertung"
          },
          {
            "name": "bewertungsgrad",
            "selector": "",
            "attribute": "data-bewertungsgrad"
          },
          {
            "name": "anzahl_der_bewertungen",
            "selector": "",
            "attribute": "data-anzahl_der_bewertungen"
          },
          {
            "name": "name",
            "selector": "",
            "attribute": "data-name"
          },
          {
            "name": "nationalitaet",
            "selector": "",
            "attribute": "data-nationalitaet"
          },
          {
            "name": "bewertung_abgegeben",
            "selector": "",
            "attribute": "data-bewertung_abgegeben"
          },
          {
            "name": "bewertungstitel",
            "selector": "",
            "attribute": "data-bewertungstitel"
          },
          {
            "name": "vorteil",
            "selector": "",
            "attribute": "data-vorteil"
          },
          {
            "name": "nachteil",
            "selector": "",
            "attribute": "data-nachteil"
          },
          {
            "name": "persoenliche_kundenbewertung",
            "selector": "",
            "attribute": "data-persoenliche_kundenbewertung"
          },
          {
            "name": "zimmer_typ",
            "selector": "",
            "attribute": "data-zimmer_typ"
          },
          {
            "name": "details",
            "selector": "",
            "attribute": "data-details"
          },
          {
            "name": "person_typ",
            "selector": "",
            "attribute": "data-person_typ"
          }
        ]
      }
    },
    {
      "block_id": "loop-continue-1",
      "block_type": "process",
      "title": "Loop Continue",
      "description": "Continue multi-input loop",
      "position_x": 3000,
      "position_y": 220,
      "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": "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": "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": 116,
      "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": 116,
      "width": 2120,
      "height": 296,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "navigate-1",
          "wait-for-page-load-1",
          "wait-for-element-1",
          "sleep-1",
          "wait-for-element-2"
        ]
      }
    },
    {
      "id": "group-interaction",
      "element_type": "group",
      "title": "Interaction",
      "color": "#a56eff",
      "position_x": 1848,
      "position_y": 116,
      "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": 2568,
      "position_y": 116,
      "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": 2928,
      "position_y": 116,
      "width": 380,
      "height": 296,
      "z_index": 20,
      "data": {
        "memberBlockIds": [
          "loop-continue-1"
        ]
      }
    },
    {
      "id": "note-overview",
      "element_type": "note",
      "title": "Overview",
      "content": "Equivalent best-effort UScraper template for the Octoparse Booking.com Hotel Details Scraper for Germany. It visits multiple Booking.com German hotel detail URLs and exports hotel title, address, hotel-level review score/grade/count, reviewer name, nationality, review date/title, advantage, disadvantage, personal score, room type, stay details, and traveler type. Navigation strategy: uses a multi-URL navigate loop for supplied hotel detail URLs. For each hotel, an injected script calls Booking.com's same-origin reviewlist.html endpoint in paginated offsets and creates stable .uscraper-review-row elements for all fetched reviews up to a safety cap; Structured Export appends those rows to one CSV. Limitations: Booking.com may block/rate-limit automation or restrict review endpoint responses; if review access is blocked, the template emits a hotel-level fallback row so the run completes.",
      "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: `(async()=>{const clean=s=>(s||'').replace(/\\s+/g,' ').trim();const pick=(root,sels)=>{for(const sel ...` Verify in browser if results are empty.",
      "color": "#ee5396",
      "position_x": 2120,
      "position_y": 200,
      "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-review-row`. Confirm row count > 0 before running at scale.",
      "color": "#ee5396",
      "position_x": 2840,
      "position_y": 200,
      "width": 340,
      "height": 111,
      "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": 3200,
      "position_y": 200,
      "width": 340,
      "height": 123,
      "z_index": 22,
      "data": {
        "block_id": "loop-continue-1"
      }
    }
  ]
}