This workflow corresponds to n8n.io template #11672 — we link there as the canonical source.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"id": "",
"meta": {
"templateCredsSetupCompleted": false
},
"name": "Direct Booking Site Generator",
"tags": [],
"nodes": [
{
"id": "911dcafa-b919-400e-b11c-dd5ef469c244",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1088,
-720
],
"parameters": {
"width": 1968,
"height": 352,
"content": "## \ud83c\udfe0 Direct Booking Site Generator\n\nThis workflow creates a professional direct booking website from any Airbnb listing and publishes it to Netlify for free.\n\n### How it works\n1. Enter your Airbnb listing ID\n2. The scraper fetches all listing data\n3. A beautiful static site is generated\n4. Site is deployed to Netlify automatically\n\n### Required Credentials\n- **Airbnb Scraper API** - Get your token at [shortrentals.ai](https://scraper.shortrentals.ai)\n- **Netlify API** - Create a personal access token at [Netlify](https://app.netlify.com/user/applications#personal-access-tokens)"
},
"typeVersion": 1
},
{
"id": "75e9e3a1-4cec-43c6-912b-5c56914c50fa",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1088,
-336
],
"parameters": {
"width": 416,
"height": 256,
"content": "## \u2699\ufe0f Configuration\n\nEdit the **listingId** field below with your Airbnb listing ID.\n\nFind it in the URL:\n`airbnb.com/rooms/`**1234567890**"
},
"typeVersion": 1
},
{
"id": "325d5852-bd4a-4037-9d9c-7ece2de50695",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-640,
-336
],
"parameters": {
"width": 320,
"height": 256,
"content": "## \ud83d\udd0d Scrape Data\n\nFetches comprehensive listing data including:\n- Title & description\n- Photos\n- Amenities\n- Pricing\n- Host info\n- Reviews"
},
"typeVersion": 1
},
{
"id": "022c3063-e0ca-4249-8144-07714c8db90a",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-288,
-336
],
"parameters": {
"width": 560,
"height": 256,
"content": "## \ud83c\udfa8 Generate Site and Zip File\n\nCreates a beautiful, responsive HTML page with:\n- Photo gallery\n- Property details\n- Booking form\n- Host section\n- Mobile-friendly design"
},
"typeVersion": 1
},
{
"id": "3d948039-5672-4df8-a130-e54946ed6e94",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
304,
-336
],
"parameters": {
"width": 576,
"height": 256,
"content": "## \ud83d\ude80 Deploy to Netlify\n\nPublishes the site to Netlify's free hosting.\n\nThe site URL will be returned in the final output.\n\n**Note:** First deploy creates a new site. Save the site ID if you want to update it later."
},
"typeVersion": 1
},
{
"id": "manual-trigger-1",
"name": "Manual Trigger",
"type": "n8n-nodes-base.manualTrigger",
"position": [
-1088,
-48
],
"parameters": {},
"typeVersion": 1
},
{
"id": "set-params-1",
"name": "Set Listing ID",
"type": "n8n-nodes-base.set",
"position": [
-800,
-48
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "listingId",
"name": "listingId",
"type": "string",
"value": "1501733424018064312"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "airbnb-scraper-1",
"name": "Airbnb Scraper",
"type": "n8n-nodes-airbnb-scraper.airbnbScraper",
"position": [
-560,
-48
],
"parameters": {
"options": {
"timeout": 120
},
"listingId": "={{ $json.listingId }}",
"operation": "scrapeListing"
},
"credentials": {
"airbnbScraperApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "code-generate-html-1",
"name": "Generate HTML Site",
"type": "n8n-nodes-base.code",
"position": [
-288,
-48
],
"parameters": {
"mode": "runOnceForAllItems",
"jsCode": "const payload = $input.first().json || {};\nconst data = payload.data || payload;\n\nconst cleanText = (value, fallback = '') => {\n if (Array.isArray(value)) return fallback;\n if (typeof value === 'number') return value.toString();\n return value || fallback;\n};\n\nconst buildGallery = () => {\n if (!Array.isArray(data.images) || data.images.length === 0) {\n return '<div class=\"gallery-item\"><div class=\"placeholder-image\">No photos available</div></div>';\n }\n return data.images.slice(0, 6).map((url, index) => '<div class=\"gallery-item\"><img src=\"' + url + '\" alt=\"Property photo ' + (index + 1) + '\" loading=\"lazy\"></div>').join('');\n};\n\nconst formatAmenity = (amenity) => {\n if (typeof amenity === 'string') return amenity;\n if (amenity && (amenity.name || amenity.title)) return amenity.name || amenity.title;\n return '';\n};\n\nconst buildAmenities = () => {\n if (!Array.isArray(data.amenities) || data.amenities.length === 0) {\n return '<li><span class=\"amenity-icon\">\u2713</span> Basic amenities</li>';\n }\n return data.amenities.slice(0, 12).map((amenity) => formatAmenity(amenity)).filter(Boolean).map((label) => '<li><span class=\"amenity-icon\">\u2713</span> ' + label + '</li>').join('');\n};\n\nconst buildHouseRules = () => {\n const rules = Array.isArray(data.houseRules) ? data.houseRules.slice(0, 6).map((rule) => {\n if (typeof rule === 'string') return rule;\n if (rule && (rule.title || rule.name)) return rule.title || rule.name;\n return '';\n }).filter(Boolean) : [];\n if (!rules.length) {\n return '<li>Check-in: 3:00 PM</li><li>Checkout: 11:00 AM</li><li>No smoking</li>';\n }\n return rules.map((rule) => '<li>' + rule + '</li>').join('');\n};\n\nconst galleryHtml = buildGallery();\nconst amenitiesHtml = buildAmenities();\nconst houseRulesHtml = buildHouseRules();\n\nconst locationParts = [data.location?.city, data.location?.state, data.location?.country].filter(Boolean).join(', ');\nconst price = data.pricing?.pricePerNight || data.price || data.pricing?.basePrice || 100;\nconst currency = data.pricing?.currency || '$';\nconst title = cleanText(data.title, 'Beautiful Vacation Rental');\nconst description = cleanText(data.description, 'A wonderful place to stay');\n\nconst html = '<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><title>' + title + ' | Direct Booking</title><meta name=\"description\" content=\"' + description.substring(0, 160) + '\"><style>* { margin: 0; padding: 0; box-sizing: border-box; } :root { --primary: #FF5A5F; --primary-dark: #E04850; --text: #222222; --text-light: #717171; --border: #DDDDDD; --background: #FFFFFF; --background-light: #F7F7F7; } body { font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, sans-serif; color: var(--text); line-height: 1.6; background: var(--background); } .container { max-width: 1120px; margin: 0 auto; padding: 0 24px; } header { border-bottom: 1px solid var(--border); padding: 20px 0; position: sticky; top: 0; background: var(--background); z-index: 100; } .header-content { display: flex; justify-content: space-between; align-items: center; } .logo { font-size: 24px; font-weight: 700; color: var(--primary); text-decoration: none; } .book-now-btn { background: var(--primary); color: white; padding: 12px 24px; border-radius: 8px; text-decoration: none; font-weight: 600; transition: background 0.2s; } .book-now-btn:hover { background: var(--primary-dark); } .gallery { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin: 24px 0; border-radius: 12px; overflow: hidden; } .gallery-item:first-child { grid-column: span 2; grid-row: span 2; } .gallery-item img { width: 100%; height: 100%; object-fit: cover; min-height: 200px; } .gallery-item:first-child img { min-height: 416px; } .placeholder-image { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; display: flex; align-items: center; justify-content: center; min-height: 200px; font-size: 18px; } .main-content { display: grid; grid-template-columns: 1fr 380px; gap: 48px; padding: 32px 0; } .listing-title { font-size: 26px; font-weight: 600; margin-bottom: 8px; } .listing-location { color: var(--text-light); margin-bottom: 16px; } .listing-stats { display: flex; gap: 16px; padding: 16px 0; border-bottom: 1px solid var(--border); flex-wrap: wrap; } .stat { display: flex; align-items: center; gap: 6px; } .rating { display: flex; align-items: center; gap: 4px; } .star { color: var(--primary); } .host-section { display: flex; align-items: center; gap: 16px; padding: 24px 0; border-bottom: 1px solid var(--border); } .host-photo { width: 56px; height: 56px; border-radius: 50%; object-fit: cover; background: var(--border); } .host-info h3 { font-size: 16px; font-weight: 600; } .superhost-badge { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; color: var(--text-light); margin-top: 4px; } .section { padding: 32px 0; border-bottom: 1px solid var(--border); } .section-title { font-size: 22px; font-weight: 600; margin-bottom: 16px; } .description { color: var(--text); white-space: pre-line; } .amenities-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; } .amenities-grid li { list-style: none; display: flex; align-items: center; gap: 12px; } .amenity-icon { color: var(--primary); font-weight: bold; } .rules-list { list-style: none; } .rules-list li { padding: 8px 0; border-bottom: 1px solid var(--border); } .rules-list li:last-child { border-bottom: none; } .booking-card { position: sticky; top: 100px; background: var(--background); border: 1px solid var(--border); border-radius: 12px; padding: 24px; box-shadow: 0 6px 16px rgba(0,0,0,0.12); } .price-line { display: flex; align-items: baseline; gap: 4px; margin-bottom: 24px; } .price { font-size: 22px; font-weight: 600; } .price-period { color: var(--text-light); } .booking-form { border: 1px solid var(--border); border-radius: 8px; margin-bottom: 16px; } .form-row { display: grid; grid-template-columns: 1fr 1fr; } .form-field { padding: 12px; border-bottom: 1px solid var(--border); } .form-field:nth-child(odd) { border-right: 1px solid var(--border); } .form-field.full-width { grid-column: span 2; border-bottom: none; } .form-field label { display: block; font-size: 10px; font-weight: 600; text-transform: uppercase; margin-bottom: 4px; } .form-field input, .form-field select { width: 100%; border: none; font-size: 14px; background: transparent; outline: none; } .reserve-btn { width: 100%; background: linear-gradient(to right, var(--primary), var(--primary-dark)); color: white; border: none; padding: 14px; border-radius: 8px; font-size: 16px; font-weight: 600; cursor: pointer; transition: transform 0.2s, box-shadow 0.2s; } .reserve-btn:hover { transform: translateY(-1px); box-shadow: 0 4px 12px rgba(255, 90, 95, 0.4); } .booking-note { text-align: center; color: var(--text-light); font-size: 14px; margin-top: 16px; } footer { background: var(--background-light); padding: 48px 0; margin-top: 48px; } .footer-content { text-align: center; color: var(--text-light); } @media (max-width: 768px) { .main-content { grid-template-columns: 1fr; } .gallery { grid-template-columns: 1fr; } .gallery-item:first-child { grid-column: span 1; grid-row: span 1; } .booking-card { position: relative; top: 0; } .amenities-grid { grid-template-columns: 1fr; } }</style></head><body><header><div class=\"container header-content\"><a href=\"#\" class=\"logo\">StayDirect</a><a href=\"#booking\" class=\"book-now-btn\">Book Now</a></div></header><main class=\"container\"><div class=\"gallery\">' + galleryHtml + '</div><div class=\"main-content\"><div class=\"listing-details\"><h1 class=\"listing-title\">' + title + '</h1><p class=\"listing-location\">' + locationParts + '</p><div class=\"listing-stats\"><span class=\"stat\">\ud83c\udfe0 ' + (data.maxGuests || 4) + ' guests</span><span class=\"stat\">\ud83d\udecf\ufe0f ' + (data.bedrooms || 1) + ' bedroom' + ((data.bedrooms || 1) > 1 ? 's' : '') + '</span><span class=\"stat\">\ud83d\udec1 ' + (data.bathrooms || 1) + ' bath' + ((data.bathrooms || 1) > 1 ? 's' : '') + '</span><span class=\"stat\">\ud83d\udecf\ufe0f ' + (data.beds || 1) + ' bed' + ((data.beds || 1) > 1 ? 's' : '') + '</span><span class=\"rating\"><span class=\"star\">\u2605</span><strong>' + (data.reviewScore?.overallRating || 4.8) + '</strong><span>(' + (data.reviewScore?.reviewsCount || 0) + ' reviews)</span></span></div><div class=\"host-section\">' + (data.hostProfile?.photo ? '<img src=\"' + data.hostProfile.photo + '\" alt=\"' + (data.hostProfile?.name || 'Your Host') + '\" class=\"host-photo\">' : '<div class=\"host-photo\"></div>') + '<div class=\"host-info\"><h3>Hosted by ' + (data.hostProfile?.name || 'Your Host') + '</h3>' + (data.hostProfile?.isSuperhost ? '<span class=\"superhost-badge\">\ud83c\udfc6 Superhost</span>' : '') + '</div></div><div class=\"section\"><h2 class=\"section-title\">About this place</h2><p class=\"description\">' + description + '</p></div><div class=\"section\"><h2 class=\"section-title\">What this place offers</h2><ul class=\"amenities-grid\">' + amenitiesHtml + '</ul></div><div class=\"section\"><h2 class=\"section-title\">House Rules</h2><ul class=\"rules-list\">' + houseRulesHtml + '</ul></div></div><div class=\"booking-sidebar\"><div class=\"booking-card\" id=\"booking\"><div class=\"price-line\"><span class=\"price\">' + currency + price + '</span><span class=\"price-period\">/ night</span></div><form class=\"booking-form\"><div class=\"form-row\"><div class=\"form-field\"><label>Check-in</label><input type=\"date\" name=\"checkin\" required></div><div class=\"form-field\"><label>Checkout</label><input type=\"date\" name=\"checkout\" required></div></div><div class=\"form-row\"><div class=\"form-field full-width\"><label>Guests</label><select name=\"guests\">' + Array.from({length: data.maxGuests || 4}, (_, i) => '<option value=\"' + (i+1) + '\">' + (i+1) + ' guest' + (i > 0 ? 's' : '') + '</option>').join('') + '</select></div></div></form><button type=\"submit\" class=\"reserve-btn\">Reserve</button><p class=\"booking-note\">You won\\'t be charged yet</p></div></div></div></main><footer><div class=\"container footer-content\"><p>\u00a9 2025 ' + title + '. All rights reserved.</p><p style=\"margin-top: 8px;\">Book directly and save on fees!</p><p style=\"margin-top: 16px;\">Powered by <a href=\"https://sitebuilder.shortrentals.ai/\" target=\"_blank\" style=\"color: var(--primary); text-decoration: none;\">shortrentals.ai</a></p></div></footer></body></html>';\n\nconst slug = title.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '').substring(0, 30) || 'direct-booking';\nconst siteName = 'booking-' + slug + '-' + Date.now().toString(36);\n\nreturn { html, siteName, title, description: description.substring(0, 160) };"
},
"typeVersion": 2
},
{
"id": "code-prepare-binary",
"name": "Prepare Binary",
"type": "n8n-nodes-base.code",
"position": [
-80,
-48
],
"parameters": {
"mode": "runOnceForAllItems",
"jsCode": "const html = $input.first().json.html;\nconst siteName = $input.first().json.siteName;\nconst title = $input.first().json.title;\n\nconst binaryData = await this.helpers.prepareBinaryData(\n Buffer.from(html, 'utf-8'),\n 'index.html',\n 'text/html'\n);\n\nreturn {\n json: { siteName, title, html },\n binary: { data: binaryData }\n};"
},
"typeVersion": 2
},
{
"id": "compression-zip",
"name": "Create ZIP",
"type": "n8n-nodes-base.compression",
"position": [
112,
-48
],
"parameters": {
"fileName": "site.zip",
"operation": "compress",
"outputFormat": "zip",
"binaryPropertyName": "data"
},
"typeVersion": 1
},
{
"id": "http-create-site",
"name": "Create Netlify Site",
"type": "n8n-nodes-base.httpRequest",
"position": [
304,
-48
],
"parameters": {
"url": "https://api.netlify.com/api/v1/sites",
"method": "POST",
"options": {},
"jsonBody": "={{ JSON.stringify({ name: $('Prepare Binary').item.json.siteName }) }}",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"authentication": "genericCredentialType",
"genericAuthType": "httpBearerAuth",
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"credentials": {
"httpBearerAuth": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "http-deploy-zip",
"name": "Deploy ZIP",
"type": "n8n-nodes-base.httpRequest",
"position": [
528,
-48
],
"parameters": {
"url": "=https://api.netlify.com/api/v1/sites/{{ $json.site_id }}/builds",
"method": "POST",
"options": {},
"sendBody": true,
"contentType": "binaryData",
"sendHeaders": true,
"authentication": "genericCredentialType",
"genericAuthType": "httpBearerAuth",
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/zip"
}
]
},
"inputDataFieldName": "={{ $(\"Create ZIP\").item.binary.data }}"
},
"credentials": {
"httpBearerAuth": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "code-output-1",
"name": "Output Results",
"type": "n8n-nodes-base.code",
"position": [
752,
-48
],
"parameters": {
"mode": "runOnceForAllItems",
"jsCode": "const siteData = $('Create Netlify Site').item.json;\nconst deployData = $input.first().json;\nconst prepData = $('Prepare Binary').item.json;\n\nreturn {\n success: true,\n message: 'Direct booking site deployed successfully!',\n title: prepData.title,\n siteUrl: siteData.ssl_url || siteData.url,\n adminUrl: siteData.admin_url,\n siteId: siteData.site_id,\n deployId: deployData.id,\n deployState: deployData.state,\n note: 'Your site is now live! Visit the siteUrl to see your direct booking page.'\n};"
},
"typeVersion": 2
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "",
"connections": {
"Create ZIP": {
"main": [
[
{
"node": "Create Netlify Site",
"type": "main",
"index": 0
}
]
]
},
"Deploy ZIP": {
"main": [
[
{
"node": "Output Results",
"type": "main",
"index": 0
}
]
]
},
"Airbnb Scraper": {
"main": [
[
{
"node": "Generate HTML Site",
"type": "main",
"index": 0
}
]
]
},
"Manual Trigger": {
"main": [
[
{
"node": "Set Listing ID",
"type": "main",
"index": 0
}
]
]
},
"Prepare Binary": {
"main": [
[
{
"node": "Create ZIP",
"type": "main",
"index": 0
}
]
]
},
"Set Listing ID": {
"main": [
[
{
"node": "Airbnb Scraper",
"type": "main",
"index": 0
}
]
]
},
"Generate HTML Site": {
"main": [
[
{
"node": "Prepare Binary",
"type": "main",
"index": 0
}
]
]
},
"Create Netlify Site": {
"main": [
[
{
"node": "Deploy ZIP",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
airbnbScraperApihttpBearerAuth
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow instantly transforms any Airbnb listing into a polished, mobile-ready direct booking site hosted on the Netlify platform.
Source: https://n8n.io/workflows/11672/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This workflow uses the Zyte API to automatically detect and extract structured data from E-commerce sites, Articles, Job Boards, and Search Engine Results (SERP) - no custom CSS selectors required.
Automate LinkedIn lead generation by scraping comments from targeted posts and enriching profiles with detailed data
This workflow contains community nodes that are only compatible with the self-hosted version of n8n.
This workflow runs a spider job in the background via Scrapyd, using a YAML config that defines selectors and parsing rules. When triggered, it schedules the spider with parameters (query, project ID,
This n8n workflow collects leads from Google Maps, scrapes their websites via direct HTTP requests, and extracts valid email addresses — all while mimicking real user behavior to improve scraping reli