Belgrade Rental Market Monitor
Pricing
from $0.0005 / actor start
Belgrade Rental Market Monitor
Collects long-term apartment rental listings in Belgrade from multiple real estate platforms (Halo Oglasi, 4zida, Nekretnine.rs, CityExpert), normalizes data into a unified structure for market analysis, price tracking, and rental monitoring.
Pricing
from $0.0005 / actor start
Rating
0.0
(0)
Developer
Victor
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
23 days ago
Last modified
Categories
Share
Collect structured long-term rental listings from Belgrade's top real estate portals in one unified dataset. Built for agencies, analysts, developers, and anyone who needs reliable, normalized rental market data.
What it does
This Actor scrapes publicly available apartment rental listings from multiple Serbian real estate websites, normalizes all data into a single consistent schema, and saves results to an Apify Dataset. Each run produces a clean, analysis-ready table with price, area, location, rooms, floor, furnishing status, and more.
Currently supported sources:
| Source | URL |
|---|---|
| Halo Oglasi | halooglasi.com |
Who it's for
- Real estate agencies — monitor competitor pricing, find new listings faster
- Relocation services — get fresh inventory for clients moving to Belgrade
- Market analysts & investors — track price trends by district, rooms, and area
- Telegram bot developers — power rental alert bots with fresh data
- Researchers & dashboards — feed BI tools, notebooks, and reporting pipelines
- Individuals — find apartments with exact criteria without clicking through multiple sites
Input
{"city": "Belgrade","districts": ["Novi Beograd", "Vračar"],"min_price": 400,"max_price": 1000,"min_area_m2": 40,"max_area_m2": 100,"rooms": ["2", "2.5", "3"],"max_results_per_source": 200,"scrape_details": true,"include_images": false,"proxy_enabled": true,"request_delay_ms": 1500}
Input fields
| Field | Type | Default | Description |
|---|---|---|---|
city | string | "Belgrade" | City to search (only Belgrade currently) |
districts | array | [] | Filter by districts — empty = all. E.g. ["Novi Beograd", "Vračar"] |
min_price | integer | null | Minimum rent in EUR |
max_price | integer | null | Maximum rent in EUR |
min_area_m2 | integer | null | Minimum apartment size in m² |
max_area_m2 | integer | null | Maximum apartment size in m² |
rooms | array | [] | Filter by rooms: studio, 1, 1.5, 2, 2.5, 3, 4+ |
max_results_per_source | integer | 500 | Cap on listings per source (1–5000) |
scrape_details | boolean | true | Visit each listing's page for full description, heating, furnishing, etc. |
include_images | boolean | false | Collect image URLs (requires scrape_details: true) |
proxy_enabled | boolean | true | Use Apify proxy for requests |
request_delay_ms | integer | 1000 | Milliseconds between requests |
Supported districts: Novi Beograd, Vračar, Stari Grad, Zemun, Savski Venac, Palilula, Voždovac, Zvezdara, Čukarica, Rakovica
Output
Each record in the dataset represents one rental listing.
Example output record
{"source": "halo_oglasi","external_id": "halo_oglasi_87654321","listing_url": "https://www.halooglasi.com/nekretnine/izdavanje-stanova/dvoiposobni-stan/87654321","title": "Dvoiposobni stan na Novom Beogradu, Blok 45","description": "Namešteni dvoiposobni stan od 65 kvadrata na 4. spratu. Centralno grejanje, lift, parking...","city": "Belgrade","district": "Novi Beograd","neighborhood": "Blok 45","address": null,"price": 650,"currency": "EUR","area_m2": 65.0,"rooms": "2.5","floor": 4,"total_floors": 8,"heating": "Centralno grejanje","furnished": true,"property_type": "apartment","rent_type": "long_term","advertiser_type": "agency","agency_name": "ABC Nekretnine","contact_name": null,"image_urls": [],"published_at": "2024-01-15","updated_at": null,"scraped_at": "2024-01-20T14:30:00+00:00","price_per_m2": 10.0,"normalized_title": "dvoiposobni stan na novom beogradu blok 45","duplicate_key": "a1b2c3d4e5f67890","possible_duplicate": false,"raw_data": null}
Output fields reference
| Field | Type | Description |
|---|---|---|
source | string | Data source: halo_oglasi / 4zida / nekretnine_rs / cityexpert |
external_id | string | Stable unique ID: {source}_{listing_id} |
listing_url | string | Full URL to the original listing |
title | string | Listing title |
description | string | Full description (if scrape_details: true) |
city | string | City (always Belgrade in V1) |
district | string | Belgrade district / municipality |
neighborhood | string | Sub-district / neighborhood (if available) |
address | string | Street address (if publicly shown) |
price | integer | Monthly rent, numeric |
currency | string | EUR (most Belgrade listings) or RSD |
area_m2 | float | Apartment area in m² |
rooms | string | Normalized rooms: studio / 1 / 1.5 / 2 / 2.5 / 3 / 4+ |
floor | integer | Floor number (0 = ground, -1 = basement) |
total_floors | integer | Total floors in building |
heating | string | Heating type |
furnished | boolean | true / false / null |
property_type | string | apartment / studio / room / house |
rent_type | string | Always long_term in V1 |
advertiser_type | string | agency / private / unknown |
agency_name | string | Real estate agency name |
contact_name | string | Contact person name (if publicly available) |
image_urls | array | Photo URLs (populated when include_images: true) |
published_at | string | Date listing was published (ISO 8601) |
updated_at | string | Date listing was last updated |
scraped_at | string | Timestamp when this record was collected |
price_per_m2 | float | price / area_m2, rounded to 2 decimals |
normalized_title | string | Lowercase title, stripped for deduplication |
duplicate_key | string | Hash used for cross-source fuzzy deduplication (V2) |
possible_duplicate | boolean | false in V1; V2 will flag cross-run duplicates |
raw_data | object | Original scraped fields for debugging (debug builds only) |
Use cases
Rental price monitoring
Run on a schedule (daily or weekly). Compare price and scraped_at across runs to track price changes by district and room count.
Relocation services
Filter by district, rooms, max_price, and furnished to build a curated shortlist for clients. Export to CSV or Google Sheets.
Real estate agency competitive analysis
Identify new listings before they go viral. Track how long listings stay on the market (coming in V2 with first_seen_at / days_on_market).
Telegram bot / email alerts
Trigger on new listings matching criteria. The external_id field makes it easy to track which listings you've already seen.
Research & dashboards
Feed directly into Jupyter notebooks, Metabase, Grafana, or any BI tool via Apify's dataset API. Calculate median rent by district, price per m² trends, etc.
Price analytics
Use price_per_m2 for comparable analysis across differently-sized apartments. Group by district + rooms for market benchmarks.
Limitations
- Data depends on source site availability and HTML structure. If a site changes its layout, the scraper may need an update.
- Some fields (
address,contact_name,heating,floor) may benull— not all listings show all details. - Listings may appear on multiple sources. Cross-source deduplication is planned for V2 (
possible_duplicatefield). - This scraper collects only publicly visible data — no paywalled content, no login-gated listings.
- Prices are as listed by the advertiser — not verified or adjusted for utilities.
- Images are only collected when
include_images: true. Large image counts increase run time.
Roadmap
V2 — Price Tracking
Fields: first_seen_at, last_seen_at, is_new_listing, is_removed, old_price, new_price, price_change_pct, days_on_market
Store listing history across runs. Enable alerts on price drops and new listings.
V3 — Multi-city
Novi Sad, Niš, Kragujevac, Subotica. Same schema, new city selector.
V4 — Sale listings
Track apartments for sale. Calculate rent vs. buy ratios. Price per m² by district for both categories.
V5 — Analytics summary
Push aggregate stats as a separate dataset: median_price_by_district, median_price_per_m2, listings_count_by_district, new_listings_count, price_drop_count.
Support
Found a bug or selector that stopped working? Open an issue on GitHub or contact via Apify.