DEV Community

Cover image for Stop Scraping Bayut - Build a Dubai Property App in 48 Hours
Happy Endpoint
Happy Endpoint

Posted on

Stop Scraping Bayut - Build a Dubai Property App in 48 Hours

Your Bayut scraper just broke again.

They updated their HTML. Your regex is wrong. The IP got blocked. You're debugging at midnight instead of shipping.

Sound familiar?

I've been there. I built a scraper for Dubai property data. It worked for two months. Then Bayut updated their site. I spent a week fixing it. Then it broke again.

That's when I found a better way.

The Problem with Scraping Bayut

Web scraping Bayut is painful for a few specific reasons:

  1. Aggressive bot detection - Bayut uses Cloudflare and fingerprinting. Your scraper gets blocked fast.
  2. Frequent HTML changes - The site structure changes regularly. Your selectors break.
  3. Proxy costs - To scrape at scale, you need rotating proxies. That's $200-500/month minimum.
  4. Legal grey area - Scraping violates Bayut's terms of service. It's a real risk.
  5. Maintenance hell - Every site update means debugging time. Time you could spend building.

The Solution: Bayut API

The Bayut API on RapidAPI gives you programmatic access to Bayut's data without any of those problems.

  • No proxies needed
  • No scraping
  • Clean JSON responses
  • UAE-wide coverage
  • Fast (sub-400ms)

Here's what you can access:

  • Property listings (sale + rent)
  • Off-plan development projects
  • Agent profiles and listings
  • Agency data
  • Transaction history
  • Location search and IDs

Building the App: Step by Step

Let's build a Dubai property search app. I'll use Node.js and Express for the backend.

Step 1: Get Your API Key

Sign up on RapidAPI and subscribe to the Bayut API:

https://rapidapi.com/happyendpoint/api/bayut14/

Step 2: Location Search

First, implement location autocomplete so users can search by area.

const axios = require('axios');

async function searchLocations(query) {
  const response = await axios.get(
    'https://bayut14.p.rapidapi.com/autocomplete',
    {
      params: { query, langs: 'en' },
      headers: {
        'x-rapidapi-host': 'bayut14.p.rapidapi.com',
        'x-rapidapi-key': process.env.RAPIDAPI_KEY
      }
    }
  );
  return response.data.data.locations;
}

// Returns: [{ id, externalID, name, slug, adCount }]
// Use externalID for property search
Enter fullscreen mode Exit fullscreen mode

Step 3: Property Search

Now the core search functionality:

async function searchProperties(params) {
  const response = await axios.get(
    'https://bayut14.p.rapidapi.com/search-property',
    {
      params: {
        purpose: params.purpose || 'for-sale',
        location_ids: params.locationId,
        property_type: params.type || 'apartments',
        rooms: params.bedrooms,
        price_min: params.minPrice,
        price_max: params.maxPrice,
        sort_order: 'popular',
        page: params.page || 1,
        langs: 'en'
      },
      headers: {
        'x-rapidapi-host': 'bayut14.p.rapidapi.com',
        'x-rapidapi-key': process.env.RAPIDAPI_KEY
      }
    }
  );

  const { properties, total, totalPages } = response.data.data;
  return { properties, total, totalPages };
}
Enter fullscreen mode Exit fullscreen mode

Each property in the response includes:

  • Title, price, bedrooms, bathrooms
  • Area in sqm
  • Location details
  • Cover photo
  • Agent info
  • Amenities
  • Completion status (ready vs off-plan)

Step 4: Property Details

When a user clicks a listing, fetch full details:

async function getPropertyDetails(externalId) {
  const response = await axios.get(
    'https://bayut14.p.rapidapi.com/property-details',
    {
      params: { external_id: externalId, langs: 'en' },
      headers: {
        'x-rapidapi-host': 'bayut14.p.rapidapi.com',
        'x-rapidapi-key': process.env.RAPIDAPI_KEY
      }
    }
  );
  return response.data.data;
}
Enter fullscreen mode Exit fullscreen mode

Step 5: Off-Plan Projects

Add a section for new developments:

async function searchOffPlan(locationId) {
  const response = await axios.get(
    'https://bayut14.p.rapidapi.com/search-new-projects',
    {
      params: {
        location_ids: locationId,
        property_type: 'residential',
        sort_order: 'latest',
        page: 1
      },
      headers: {
        'x-rapidapi-host': 'bayut14.p.rapidapi.com',
        'x-rapidapi-key': process.env.RAPIDAPI_KEY
      }
    }
  );
  return response.data.data.properties;
}
Enter fullscreen mode Exit fullscreen mode

What I Built in 48 Hours

Using this API, I built a working property search app with:

  • Location autocomplete (powered by /autocomplete)
  • Property search with filters (powered by /search-property)
  • Property detail pages (powered by /property-details)
  • Off-plan project listings (powered by /search-new-projects)
  • Agent profiles (powered by /agent-details)

Total development time: 48 hours.

With a scraper, this would have taken 3-4 weeks - and it would break every month.

The Numbers

Scraper Bayut API
Setup time 3-4 weeks 2 days
Monthly cost $300-500 (proxies) $10-50
Uptime ~70% 99.9%
Maintenance 10+ hrs/month 0 hrs/month
Legal risk High None

What to Build Next

Once you have the basics working, here are some features to add:

  • Price alerts - notify users when a property drops in price
  • Saved searches - let users save their filters
  • Market analytics - use /transactions to show price trends
  • Agent comparison - rank agents by listing count and area

Get Started

The Bayut API is available on RapidAPI with a free plan:

🔗 https://rapidapi.com/happyendpoint/api/bayut14/

Full documentation:

📖 https://bayutapi.dev/

Questions? Reach out: happyendpointhq@gmail.com


Built by Happy Endpoint - developer-friendly APIs for real-world data.

🌐 https://happyendpoint.com | 🐦 https://x.com/happyendpointhq

Top comments (0)