Bayut KSA Property Scraper
Pricing
from $2.20 / 1,000 property listings
Bayut KSA Property Scraper
Extract property listings from Bayut.sa with optional full listing details and agent information.
Pricing
from $2.20 / 1,000 property listings
Rating
0.0
(0)
Developer
Data Scrapers
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
4 days ago
Last modified
Categories
Share
Bayut KSA Property Scraper creates a structured dataset of property listings collected from Bayut Saudi Arabia. Each dataset item is one listing and can include the listing id, purpose, price in SAR, rooms, baths, area, location path, cover image, and public URL. Query by purpose, city or neighbourhood, category, and property type, optionally add the listing page and the agent profile, limit results with maxItems, and retrieve records through the Apify Dataset API or export them as JSON, CSV, Excel, XML, or another supported format.
Dataset at a glance
| Property | Value |
|---|---|
| Source | bayut.sa |
| Record unit | One property listing |
| Input methods | purpose, location, category, subCategory, and the other filters |
| Main identifiers | externalID and id |
| Delivery | Apify Dataset and API |
| Export formats | JSON, CSV, Excel, XML, and other Apify dataset exports |
| Update model | Fresh records per Actor run |
| Pricing | $2.50 per 1,000 listings, $2.00 per 1,000 detail fetches, $1.50 per 1,000 agent profiles on the free plan |
Coverage and available records
The Actor searches Bayut Saudi Arabia. purpose is for-sale or for-rent. location is a city, neighbourhood, or path. Set parentLocation when location is a neighbourhood and needs a parent city. Category is residential or commercial. subCategory is a property-type slug such as apartments or villas.
Other filters: completion status (all, ready, off-plan), rent frequency, furnishing, bedroom and bathroom bounds, area in square feet, and price in SAR. superHot limits the search to superhot for-sale listings.
maxPages defaults to 1. An empty value means all pages. maxItems defaults to 0, which means no item cap. The prefill is 100.
The search card includes title, Arabic title, price, rooms, baths, area, geography, location hierarchy, category, cover image, photo and video counts, agency, verification, and the public propertyUrl. The Actor also writes priceFormatted, propertyType, fullAddress, coverImageUrl, agencyName, and agencyUrl.
scrapePropertyDetails adds propertyDetails and amenities. scrapeAgentInformation adds agentInformation. Both are off by default. The saved Riyadh sample had both on. Phone numbers and an agent email were present on that listing. They are not copied into the example below.
Not currently collected: a sold-price history, or listings outside the filters you set.
Data dictionary
The table uses a saved for-sale apartment in Al Rimal, Riyadh. Area on that card is 86. Price is 550,000 SAR.
| Field | Type | Nullable | Description | Example |
|---|---|---|---|---|
id | integer | No | Internal listing id. Also stored as objectID. | 1358011 |
externalID | string | No | Public listing number. Best field for deduplication. | 88006942 |
propertyUrl | string | No | English listing URL built by the Actor. | https://www.bayut.sa/en/property/details-88006942.html |
purpose | string | No | for-sale or for-rent. | for-sale |
price | number | Yes | Price in SAR. | 550000.0 |
priceFormatted | string | Yes | Display price. | SAR 550,000 |
rentFrequency | string or null | Yes | Rent period. Null on the saved sale. | null |
title | string | Yes | English title. | Apartment for sale in Al Rimal |
title_l1 | string | Yes | Arabic title. | Arabic title string |
rooms | integer or null | Yes | Bedrooms. | 2 |
baths | integer or null | Yes | Bathrooms. | 2 |
area | number or null | Yes | Area. The saved card is 86. The input filter unit is square feet. | 86.0 |
propertyType | string | Yes | Type label added by the Actor. | Apartment |
fullAddress | string | Yes | City, area, and district joined by the Actor. | Riyadh, East Riyadh, Al Rimal |
geography | object | Yes | lat and lng. | 24.90263, 46.83518 |
location | array | No | Hierarchy from country to district, each with id, name, name_l1, and slug. | KSA, Riyadh, East Riyadh, Al Rimal |
category | array | No | Category path, residential then apartment on this card. | Residential |
furnishingStatus | string or null | Yes | Furnishing label. | unfurnished |
completionStatus | string or null | Yes | Completion label. | completed |
state | string | Yes | Listing state. | active |
coverImageUrl | string or null | Yes | Cover image URL. | https://images.bayut.sa/thumbnails/... |
photoCount | integer | Yes | Photo count. | 14 |
videoCount | integer | Yes | Video count. | 1 |
hasVideo | boolean | Yes | True when a video is present. | true |
agencyName | string or null | Yes | Agency name. | Agency name string |
agencyUrl | string or null | Yes | Agency page URL. | https://www.bayut.sa/en/companies/... |
isVerified | boolean | Yes | Verification flag from the card. | true |
hidePrice | boolean | Yes | True when the source hides the price. | false |
permitNumber | string or null | Yes | Permit number when present. Null on the saved card. | null |
referenceNumber | string or null | Yes | Reference number. Null on the saved card. | null |
createdAt | number | Yes | Source timestamp as a Unix number. | 1790760790.0 |
updatedAt | number | Yes | Source update timestamp. | 1790760790.0 |
propertyDetails is the listing-page object when scrapePropertyDetails is true. amenities is then an array of amenity names. agentInformation is the agent profile when scrapeAgentInformation is true. phoneNumber can contain mobile, phone, and WhatsApp values. agentEmail is a string when the listing exposes one. Those contact fields are omitted from the example.
Example dataset record
Saved from purpose for-sale, location Riyadh, category residential, subCategory apartments, with details and agent information enabled. Contact names, phone numbers, and email are on the stored record and are not repeated here. location keeps the district level only.
{"id": 1358011,"externalID": "88006942","objectID": "1358011","purpose": "for-sale","price": 550000.0,"priceFormatted": "SAR 550,000","rentFrequency": null,"title": "**Apartment for Sale | Al Sadaf 27 Project | Al Rimal District**","rooms": 2,"baths": 2,"area": 86.0,"propertyType": "Apartment","fullAddress": "Riyadh, East Riyadh, Al Rimal","geography": { "lat": 24.902634636864, "lng": 46.835184996003 },"furnishingStatus": "unfurnished","completionStatus": "completed","state": "active","propertyUrl": "https://www.bayut.sa/en/property/details-88006942.html","coverImageUrl": "https://images.bayut.sa/thumbnails/9551980-800x600.webp","photoCount": 14,"videoCount": 1,"hasVideo": true,"isVerified": true,"hidePrice": false,"permitNumber": null,"referenceNumber": null}
Query and input reference
| Input | Type | Required | Default | Accepted values | Description |
|---|---|---|---|---|---|
purpose | string | No | for-sale | for-sale, for-rent | Listing purpose. |
location | string | No | Riyadh | City, neighbourhood, or path | Search place. |
parentLocation | string | No | empty | Parent city dropdown, or empty | Required in the UI sense only for sub-areas. |
category | string | No | residential | residential, commercial | Category. |
subCategory | string | No | apartments | Property-type slugs in the input schema | Example: apartments, villas, offices. |
status | string | No | all | all, ready, off-plan | Completion filter. |
rentFrequency | string | No | None | yearly, monthly, weekly, daily | Rent listings only. |
furnishingStatus | string | No | None | all, furnished, unfurnished | Furnishing filter. |
roomsMin | integer | No | None | Integer | Minimum bedrooms. |
roomsMax | integer | No | None | Integer | Maximum bedrooms. |
bathsMin | integer | No | None | Integer | Minimum bathrooms. |
bathsMax | integer | No | None | Integer | Maximum bathrooms. |
areaMin | integer | No | None | Square feet | Minimum area. |
areaMax | integer | No | None | Square feet | Maximum area. |
priceMin | integer | No | None | SAR | Minimum price. |
priceMax | integer | No | None | SAR | Maximum price. |
superHot | boolean | No | false | true or false | Superhot for-sale listings only. |
scrapePropertyDetails | boolean | No | false | true or false | Charge property-details. |
scrapeAgentInformation | boolean | No | false | true or false | Charge agent-information. |
detailsConcurrency | integer | No | 5 | Integer | Parallel detail and agent requests. |
maxPages | integer | No | 1 | Positive integer, or empty for all pages | Page cap. |
maxItems | integer | No | 0 | 0 or a positive integer | Listing cap. 0 means no cap. Prefill 100. |
proxyConfiguration | object | No | Apify residential proxy, country SA | Apify proxy editor | Proxy for search, detail, and agent requests. |
Minimal request:
{"purpose": "for-sale","location": "Riyadh","category": "residential","subCategory": "apartments","maxPages": 1,"maxItems": 5}
With details and agent profiles:
{"purpose": "for-sale","location": "Riyadh","subCategory": "apartments","maxItems": 5,"scrapePropertyDetails": true,"scrapeAgentInformation": true}
Retrieve the data through the API
- Start
datascrapers/bayut-sa-scraperwith the JSON input. - Wait until the run finishes, or call the synchronous dataset endpoint.
- Read items from the run's default dataset.
- Paginate with dataset
offsetandlimit, or export from the Apify console.
from apify_client import ApifyClientclient = ApifyClient("<YOUR_API_TOKEN>")run = client.actor("datascrapers/bayut-sa-scraper").call(run_input={"purpose": "for-sale","location": "Riyadh","category": "residential","subCategory": "apartments","maxItems": 5,})for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(item["externalID"], item["fullAddress"], item["price"])
Other languages are listed on the Actor's API tab. This is the Apify Actor API, not a Bayut API.
Data quality and record handling
- One dataset item is one listing. The
propertyevent is charged for that listing. - Deduplicate on
externalID.idandobjectIDare the same internal number on the saved card. propertyUrlis built fromexternalID.fullAddressis built from the location names.createdAtandupdatedAtare Unix timestamps from the source, not ISO strings.areaon the saved card is 86. The input area filters are documented as square feet. Do not assume the card unit without checking the listing.propertyDetailsandamenitiesare absent unless detail scraping succeeds.agentInformationis absent unless the agent request succeeds.- A failed detail or agent request does not remove the search card.
- Phone numbers and email are present only when the source listing includes them.
Pricing and cost examples
The price file charges three events. Amounts are per 1,000 events. The free-plan rates are $2.50 for property, $2.00 for property-details, and $1.50 for agent-information.
| Event | Free | Bronze | Silver | Gold | Platinum and Diamond |
|---|---|---|---|---|---|
property | $2.50 | $2.40 | $2.30 | $2.20 | $2.20 |
property-details | $2.00 | $1.90 | $1.80 | $1.70 | $1.70 |
agent-information | $1.50 | $1.40 | $1.30 | $1.20 | $1.20 |
Platinum and Diamond are not listed in the file. They use the Gold rate. The file sets platform usage as not charged to the user. Figures below use the free-plan rates and assume every selected listing is enriched.
| Listings | Cards only | Cards and details | Cards, details, and agent profiles |
|---|---|---|---|
| 1,000 | $2.50 | $4.50 | $6.00 |
| 10,000 | $25.00 | $45.00 | $60.00 |
Limitations and responsible data use
- Results follow the public Bayut search you configure.
maxPagesdefaults to 1. - Neighbourhood searches need
parentLocationwhen the location is not a city. - Prices, photos, and verification flags change on the source. This is not a historical archive.
- Phone numbers, email, and agent names are contact data. Use them in line with the privacy rules that apply to your project.
- You are responsible for complying with Bayut's terms and applicable law.
Dataset questions
What does one dataset item represent?
One Bayut Saudi Arabia listing. Detail and agent fields are added only when those options succeed.
Which field should I use as a unique identifier?
Use externalID. It is the number in propertyUrl.
Are fields nullable or conditional?
Yes. Rent frequency, permit number, and reference number were null on the saved sale. propertyDetails, amenities, and agentInformation depend on the two scrape options.
Can I retrieve the records as CSV or JSON?
Yes. Export the default dataset as JSON, CSV, Excel, XML, or another Apify format.
How do I paginate large datasets?
Set maxItems and maxPages. Read the dataset with limit and offset. maxItems of 0 removes the item cap.
Does the Actor return historical data?
No. createdAt is the source timestamp on the current listing, not a history of price changes.
What counts as a billable result?
Each listing charges property at $0.0025 on the free plan. Each successful detail fetch charges property-details at $0.002. Each successful agent profile charges agent-information at $0.0015.
Related datasets from Data Scrapers
- Aqar.fm Scraper collects Saudi listing cards you can compare on city, price, and area.
- Apartments Scraper collects apartment listings with price and location fields.
- 99acres Scraper is another national listings dataset with price and area.
- Aengevelt Scraper collects commercial property records.
- Asunnot Oikotie.fi collects Finnish listing cards with price, size, and address.
Data Scrapers support
Need an additional field, record type, or export workflow? Contact Data Scrapers at stardustspotlight@gmail.com. Include a sample source URL, required fields, expected record volume, and preferred delivery format.
