How to get Bayut listings in Python
By the end of this guide you have a CSV of Dubai flats to rent, with the agent's name, phone and brokerage, from one script you can run again tomorrow. Everything below was run on 15 October 2026; the output table is what it returned.
Why scraping Bayut yourself breaks
- Bayut has no public API for reading listings. Agencies publish through an XML feed from their CRM, which Bayut reads; nothing flows the other way.
- The search pages carry their results as JSON, because Bayut's search runs on Algolia, so parsing is manageable once you have the page.
- Getting the page is the hard part: Bayut is protected against bots, and its for-sale pages add a JavaScript check.
None of that is impossible, but each point is code you then maintain. The rest of this guide uses Listingrail, which does the reading and hands back clean JSON. The Bayut API page has the official options with sources.
1. Get a key
One request with your email returns a key with 100 free listings. It is shown once, so keep it in an environment variable.
curl -X POST https://listingrail.com/v1/signup \
-H "content-type: application/json" \
-d '{"email": "you@example.com"}'
export LISTINGRAIL_KEY=re_...2. Search and save to CSV
Install requests (pip install requests), then run:
import csv
import os
import requests
r = requests.post(
"https://listingrail.com/v1/listings/search",
headers={"Authorization": f"Bearer {os.environ['LISTINGRAIL_KEY']}"},
json={"source":"bayut","location":"dubai","type":"rent","limit":50},
timeout=300,
)
r.raise_for_status()
listings = r.json()["listings"]
fields = ["price", "currency", "beds", "baths", "area", "address", "url"]
with open("bayut-dubai.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerow(fields)
for home in listings:
writer.writerow([home[k] for k in fields])
print(len(listings), "listings saved to bayut-dubai.csv")The request body, on its own:
{
"source": "bayut",
"location": "dubai",
"type": "rent",
"limit": 50
}Each listing returned costs one credit. A search that finds nothing, or fails at Bayut, costs nothing. A request can take up to a minute or two, because Bayut is read at that moment.
3. What comes back
The first three rows of the run on 15 October 2026:
Every listing has the same keys on all 17 portals, so the code for Bayut reads the others too. Fields Bayut does not show come back as null, and the portal's own record sits in raw. With pandas:
import pandas as pd
df = pd.DataFrame(listings)
df["agent"] = df["agent"].str.get("company")
print(df[["price", "beds", "baths", "area", "address", "agent"]].head())4. Get new listings and price cuts every day
Running the script on a schedule works, but then you compare the files yourself. A monitor stores the search, checks it once a day, and sends only what changed: new listings and price cuts. The free key holds one monitor.
requests.post(
"https://listingrail.com/v1/monitors",
headers={"Authorization": f"Bearer {os.environ['LISTINGRAIL_KEY']}"},
json={
"source": "bayut",
"location": "dubai",
"filters": {"type":"rent"},
"webhook_url": "https://example.com/new-listings",
},
timeout=30,
)Changes can also be read with GET /v1/monitors/{id}/changes or downloaded as CSV. Plans and limits are on the monitors page.
Bayut quirks worth knowing
- Pass a UAE city ("dubai", "abu-dhabi"). For a community or filters, build the search on bayut.com and pass its link as location.
- Rents in the UAE are quoted per year: price_period is "year" and price is the annual rent in AED.
- area is in square metres (area_unit "sqm"); Bayut shows square feet on the site.
- Every listing names the agent, their mobile number and the brokerage, and listed_at is when the listing went live.
Questions
Does Bayut offer an API for developers?
No. Bayut's integrations are for agencies uploading their own listings by XML feed.
Why is the rent so high?
UAE rents are yearly. Divide price by 12 for a monthly figure; price_period says "year".
Does it cover Property Finder too?
Yes, as "source": "propertyfinder", in the same listing format.