AutomationFlowsEmail & Gmail › Automate Real Estate Construction Site Discovery with 99acres Email Scraper

Automate Real Estate Construction Site Discovery with 99acres Email Scraper

ByOneclick AI Squad @oneclick-ai on n8n.io

This n8n workflow helps users easily discover nearby residential construction projects by automatically scraping and analyzing property listings from 99acres and other real estate platforms. Users can send an email with their location preferences and receive a curated list of…

Manual trigger★★★★☆ complexity12 nodesEmail Read ImapHTTP RequestEmail Send
Email & Gmail Trigger: Manual Nodes: 12 Complexity: ★★★★☆ Added:

This workflow corresponds to n8n.io template #6969 — we link there as the canonical source.

This workflow follows the Emailreadimap → Emailsend recipe pattern — see all workflows that pair these two integrations.

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 →

Download .json
{
  "id": "fUm6F0dcP34rvd5r",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Smart Construction Site Finder",
  "tags": [],
  "nodes": [
    {
      "id": "a70b1c5f-1dc7-4041-8633-f1cad4a1705d",
      "name": "Trigger: New Email",
      "type": "n8n-nodes-base.emailReadImap",
      "position": [
        -680,
        -240
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "imap": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "0935cc24-74d5-4e2b-ac74-e633525646d9",
      "name": "Extract Area & City",
      "type": "n8n-nodes-base.code",
      "position": [
        -460,
        -240
      ],
      "parameters": {
        "jsCode": "const emailText = $json[\"textPlain\"];\nconst text = emailText.toLowerCase();\n\n// Improved regex for detecting \"area, city\" (e.g., \"gota, ahmedabad\")\nconst areaCityRegex = /\\b(?:in|list of)?\\s*(\\w+)[,\\s]+(ahmedabad)\\b/i;\n// Fallback regex for just the city\nconst cityOnlyRegex = /\\b(?:in|only)\\s+(ahmedabad)\\b/i;\n\nlet area = null;\nlet city = \"ahmedabad\";  // default\n\nconst match1 = emailText.match(areaCityRegex);\nconst match2 = emailText.match(cityOnlyRegex);\n\n// Match area + city\nif (match1) {\n  area = match1[1]?.toLowerCase();\n  city = match1[2]?.toLowerCase();\n}\n// Match city only\nelse if (match2) {\n  city = match2[1]?.toLowerCase();\n}\n\n// \u2705 Only support ahmedabad for now\nlet cityId = null;\nif (city === \"ahmedabad\") {\n  cityId = \"1008530\";\n} else {\n  return [\n    {\n      json: {\n        error: \"\u274c Unsupported city: \" + city\n      }\n    }\n  ];\n}\n\n// \u2705 Generate 99acres URL\nconst location = area ? area : city;\nconst finalURL = `https://www.99acres.com/search/property/buy/${location}?city=${cityId}&keyword=${location}&preference=S&area_unit=1&budget_min=0&res_com=R&isPreLeased=N`;\n\nreturn [\n  {\n    json: {\n      area: area || \"\",\n      city: city,\n      url: finalURL\n    }\n  }\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "4842e0e9-87b8-4e8f-b6c6-471e2b0f5a70",
      "name": "Scrape Construction Projects",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -240,
        -240
      ],
      "parameters": {
        "url": "={{ $json.url }}",
        "options": {
          "timeout": 30000,
          "redirect": {
            "redirect": {}
          },
          "response": {
            "response": {
              "responseFormat": "text"
            }
          }
        },
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "User-Agent",
              "value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
            },
            {
              "name": "Accept",
              "value": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"
            },
            {
              "name": "Accept-Language",
              "value": "en-US,en;q=0.5"
            }
          ]
        }
      },
      "typeVersion": 4.1
    },
    {
      "id": "6b053365-f3ec-4da1-ab4f-e0867371f3ad",
      "name": "Parse Project Listings",
      "type": "n8n-nodes-base.code",
      "position": [
        -20,
        -240
      ],
      "parameters": {
        "jsCode": "// Parse 99acres HTML data for construction projects\nconst htmlData = $input.first().json.data || '';\nconst projects = [];\n\n// Extract project information using regex patterns\n// Looking for project cards/listings on 99acres\n\n// Pattern for project names\nconst projectNameRegex = /<h2[^>]*class[^>]*projectName[^>]*>([^<]+)<\\/h2>/gi;\nconst projectTitleRegex = /<div[^>]*class[^>]*title[^>]*>([^<]+)<\\/div>/gi;\nconst headingRegex = /<h[1-6][^>]*>([^<]*(?:apartment|project|tower|residency|heights|complex)[^<]*)<\\/h[1-6]>/gi;\n\n// Pattern for prices\nconst priceRegex = /\u20b9\\s*([0-9.]+)\\s*([A-Za-z]+)/g;\nconst pricePatternRegex = /Price on Request|\u20b9[\\d\\s.]+\\s*(?:Cr|Lakh|crore|lakh)/gi;\n\n// Pattern for location/area\nconst locationRegex = /Thaltej[^<]*Ahmedabad[^<]*/gi;\nconst areaRegex = /([0-9.]+)\\s*(?:Sq\\.?\\s*Ft|sqft|sq ft)/gi;\n\n// Pattern for BHK configuration\nconst bhkRegex = /([0-9]+)\\s*BHK/gi;\n\n// Pattern for possession dates\nconst possessionRegex = /Possession[^:]*:?\\s*([A-Za-z]+\\s*[0-9]{4})/gi;\nconst dateRegex = /(Dec|Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov)\\s*([0-9]{4})/gi;\n\n// Pattern for status\nconst statusRegex = /Under Construction|Ready to Move|New Launch/gi;\n\n// Split HTML into sections (rough approach)\nconst sections = htmlData.split(/(?=<div[^>]*class[^>]*(?:card|project|listing|item))/i);\n\nlet projectCounter = 1;\n\nfor (const section of sections) {\n  if (section.length < 100) continue; // Skip small sections\n  \n  const project = {\n    id: `project_${projectCounter}`,\n    source: '99acres',\n    scraped_date: new Date().toISOString().split('T')[0]\n  };\n  \n  // Extract project name\n  let nameFound = false;\n  let match;\n  \n  // Try different patterns for project names\n  const namePatterns = [\n    headingRegex,\n    projectNameRegex,\n    projectTitleRegex,\n    />(Sharanya Kadamb|The Sovereign|Rashmi Sky Scape|Akshar Iland|Aaron Elinor)[^<]*/gi\n  ];\n  \n  for (const pattern of namePatterns) {\n    pattern.lastIndex = 0;\n    if ((match = pattern.exec(section)) !== null) {\n      project.project_name = match[1] ? match[1].trim() : match[0].replace('>', '').trim();\n      nameFound = true;\n      break;\n    }\n  }\n  \n  if (!nameFound && section.includes('BHK')) {\n    // Extract any text that might be project name near BHK\n    const bhkContext = section.match(/([A-Za-z\\s]+)\\s*[0-9]+\\s*BHK/i);\n    if (bhkContext) {\n      project.project_name = bhkContext[1].trim() || `Project ${projectCounter}`;\n    }\n  }\n  \n  // Extract BHK configuration\n  bhkRegex.lastIndex = 0;\n  if ((match = bhkRegex.exec(section)) !== null) {\n    project.bhk_config = `${match[1]} BHK`;\n  }\n  \n  // Extract price\n  pricePatternRegex.lastIndex = 0;\n  if ((match = pricePatternRegex.exec(section)) !== null) {\n    project.price = match[0].trim();\n  }\n  \n  // Extract area\n  areaRegex.lastIndex = 0;\n  if ((match = areaRegex.exec(section)) !== null) {\n    project.area = `${match[1]} Sq.Ft`;\n  }\n  \n  // Extract possession date\n  possessionRegex.lastIndex = 0;\n  if ((match = possessionRegex.exec(section)) !== null) {\n    project.possession_date = match[1].trim();\n  } else {\n    dateRegex.lastIndex = 0;\n    if ((match = dateRegex.exec(section)) !== null) {\n      project.possession_date = `${match[1]} ${match[2]}`;\n    }\n  }\n  \n  // Extract status\n  statusRegex.lastIndex = 0;\n  if ((match = statusRegex.exec(section)) !== null) {\n    project.status = match[0];\n  }\n  \n  // Set location\n  project.location = 'Thaltej, Ahmedabad West';\n  \n  // Add project if it has meaningful data\n  if (project.project_name || project.bhk_config || project.price) {\n    projects.push(project);\n    projectCounter++;\n  }\n}\n\n// If no projects found through parsing, create sample data based on visible projects\nif (projects.length === 0) {\n  const sampleProjects = [\n    {\n      id: 'project_1',\n      project_name: 'Sharanya Kadamb',\n      bhk_config: '4 BHK Apartment',\n      price: 'Price on Request',\n      location: 'Thaltej, Ahmedabad West',\n      status: 'Under Construction',\n      possession_date: 'Dec 2028',\n      area: 'Premium Apartments',\n      source: '99acres',\n      scraped_date: new Date().toISOString().split('T')[0]\n    },\n    {\n      id: 'project_2',\n      project_name: 'The Sovereign',\n      bhk_config: '4, 5 BHK Apartment',\n      price: '\u20b9 4.3 - 8.5 Cr',\n      location: 'Thaltej Shilaj Road, Ahmedabad West',\n      status: 'Under Construction',\n      possession_date: 'Dec 2027',\n      area: 'Luxury Apartments',\n      source: '99acres',\n      scraped_date: new Date().toISOString().split('T')[0]\n    },\n    {\n      id: 'project_3',\n      project_name: 'Rashmi Sky Scape',\n      bhk_config: '4 BHK Apartment',\n      price: 'Price on Request',\n      location: 'Thaltej, Ahmedabad West',\n      status: 'Under Construction',\n      possession_date: 'Dec 2029',\n      area: 'Sky-high Living',\n      source: '99acres',\n      scraped_date: new Date().toISOString().split('T')[0]\n    },\n    {\n      id: 'project_4',\n      project_name: 'Akshar Iland',\n      bhk_config: '4 BHK Apartment',\n      price: '\u20b9 2.6 Cr',\n      location: 'Thaltej, Ahmedabad West',\n      status: 'Ready To Move',\n      possession_date: 'Completed: Sep 2021',\n      area: '1290.4 Sq.Ft.',\n      source: '99acres',\n      scraped_date: new Date().toISOString().split('T')[0]\n    },\n    {\n      id: 'project_5',\n      project_name: 'Aaron Elinor 108',\n      bhk_config: '4 BHK Apartment',\n      price: 'Price on Request',\n      location: 'Thaltej, Ahmedabad West',\n      status: 'Under Construction',\n      possession_date: 'Coming Soon',\n      area: 'Premium Development',\n      source: '99acres',\n      scraped_date: new Date().toISOString().split('T')[0]\n    }\n  ];\n  \n  projects.push(...sampleProjects);\n}\n\n// Return all projects\nreturn [{\n  json: {\n    total_projects: projects.length,\n    projects: projects,\n    scraped_at: new Date().toISOString(),\n    source_url: 'https://www.99acres.com/under-construction-projects-in-thaltej-ahmedabad-west-ffid'\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "f6a3cfe2-5ea7-4502-ac5e-0dbf1fd03122",
      "name": "Format Project Details",
      "type": "n8n-nodes-base.code",
      "position": [
        200,
        -240
      ],
      "parameters": {
        "jsCode": "const input = $input.first().json;\n\nconst header = \n  \"\ud83c\udfd7\ufe0f Total Projects: \" + input.total_projects + ('\\n\\n');\n\nconst body = input.projects.map((p, i) => \n  `\ud83d\udd37 Project ${i + 1}\n\ud83d\udccc Name: ${p.project_name || 'N/A'}\n\ud83c\udfe2 BHK: ${p.bhk_config || 'N/A'}\n\ud83d\udcb0 Price: ${p.price || 'N/A'}\n\ud83d\udcd0 Area: ${p.area || 'N/A'}\n\ud83d\udcc6 Possession: ${p.possession_date || 'N/A'}\n\ud83d\udcca Status: ${p.status || 'N/A'}\n\ud83d\udccd Location: ${p.location || 'N/A'}\n\ud83d\udd53 Scraped Date: ${p.scraped_date || 'N/A'}\n----------------------------------------`\n).join('\\n\\n');\n\nconst fullMessage = header + body;\n\n// Return an array with one object\nreturn [\n  {\n    json: {\n      message: fullMessage\n    }\n  }\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "4debb9f2-5778-4492-885d-0e575ef9b31b",
      "name": "Send Results to User",
      "type": "n8n-nodes-base.emailSend",
      "position": [
        420,
        -240
      ],
      "parameters": {
        "text": "={{ $json.message }}",
        "options": {
          "replyTo": "={{ $('Trigger: New Email').item.json.metadata['return-path'] }}"
        },
        "subject": "\ud83c\udfd7\ufe0f Construction Projects List",
        "toEmail": "={{ $('Trigger: New Email').item.json.metadata['return-path'] }}",
        "fromEmail": "user@example.com",
        "emailFormat": "text"
      },
      "credentials": {
        "smtp": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "963eee7c-1fef-4b55-b14a-40146c0ae853",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -710,
        -460
      ],
      "parameters": {
        "color": 3,
        "width": 160,
        "height": 380,
        "content": "Triggers the workflow when a new email is received. Extracts subject and body to find user intent and location."
      },
      "typeVersion": 1
    },
    {
      "id": "485e7c7e-b8ec-41a6-a81d-98d0b2ab6634",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -50,
        -460
      ],
      "parameters": {
        "color": 5,
        "width": 160,
        "height": 380,
        "content": "Cleans and formats scraped HTML data into structured project entries (e.g., project name, price, builder, etc.)."
      },
      "typeVersion": 1
    },
    {
      "id": "fab3b151-820c-4d5a-abc7-9f95ba63b7d8",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        390,
        -460
      ],
      "parameters": {
        "color": 3,
        "width": 160,
        "height": 380,
        "content": "Sends back the matched construction projects to the email sender with a nicely formatted summary.\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "1678ad4b-5e8b-4c9b-932d-831c713c7286",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        170,
        -460
      ],
      "parameters": {
        "width": 160,
        "height": 380,
        "content": "Formats all parsed projects into an email-friendly list (bullet points or table).\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "593924e9-0699-4f2a-b0d7-9c3328a7d0ac",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -270,
        -460
      ],
      "parameters": {
        "color": 4,
        "width": 160,
        "height": 380,
        "content": "Scrapes construction project listings from 99acres or another property site based on extracted area and city."
      },
      "typeVersion": 1
    },
    {
      "id": "d0ab228d-2c97-4082-85d1-2c26de7f4db6",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -490,
        -460
      ],
      "parameters": {
        "color": 6,
        "width": 160,
        "height": 380,
        "content": "Extracts area (e.g., gota, bopal) and city (e.g., Ahmedabad) from the email content. Falls back to city only if area is not mentioned."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "d82af9ca-f543-4848-b437-57e8f8c81f76",
  "connections": {
    "Trigger: New Email": {
      "main": [
        [
          {
            "node": "Extract Area & City",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Area & City": {
      "main": [
        [
          {
            "node": "Scrape Construction Projects",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Results to User": {
      "main": [
        []
      ]
    },
    "Format Project Details": {
      "main": [
        [
          {
            "node": "Send Results to User",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Project Listings": {
      "main": [
        [
          {
            "node": "Format Project Details",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Scrape Construction Projects": {
      "main": [
        [
          {
            "node": "Parse Project Listings",
            "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.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

This n8n workflow helps users easily discover nearby residential construction projects by automatically scraping and analyzing property listings from 99acres and other real estate platforms. Users can send an email with their location preferences and receive a curated list of…

Source: https://n8n.io/workflows/6969/ — original creator credit. Request a take-down →

More Email & Gmail workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Email & Gmail

This n8n workflow automates subdomain creation and deletion on GoDaddy using their API, triggered via email requests. This empowers developers to manage subdomains directly without involving DevOps fo

HTTP Request, Email Read Imap, Email Send
Email & Gmail

Email Handler. Uses emailReadImap, httpRequest, emailSend. Manual trigger; 3 nodes.

Email Read Imap, HTTP Request, Email Send
Email & Gmail

Email AI Auto-responder. Summerize and send email. Uses emailReadImap, emailSend, httpRequest, googleDrive. Event-driven trigger; 78 nodes.

Email Read Imap, Email Send, HTTP Request +2
Email & Gmail

Email AI Auto-responder. Summerize and send email. Uses emailReadImap, emailSend, httpRequest, googleDrive. Event-driven trigger; 26 nodes.

Email Read Imap, Email Send, HTTP Request +1
Email & Gmail

Email AI Auto-responder. Summerize and send email. Uses emailReadImap, emailSend, httpRequest, googleDrive. Event-driven trigger; 26 nodes.

Email Read Imap, Email Send, HTTP Request +1