# Halooglasi.com Property Scraper — Serbia Real Estate (`logiover/halooglasi-property-scraper-serbia-real-estate`) Actor

Scrape real estate listings from Halooglasi.com — Serbia's #1 property portal. Extract apartments, houses, land, commercial, garages and rooms (sale or rent) by location, EUR price, m², rooms and owner type. Returns price, area, GPS-ready address, advertiser and image gallery per ad.

- **URL**: https://apify.com/logiover/halooglasi-property-scraper-serbia-real-estate.md
- **Developed by:** [Logiover](https://apify.com/logiover) (community)
- **Categories:** Real estate, Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## Halooglasi.com Property Scraper

Scrape real estate listings from **[Halooglasi.com](https://www.halooglasi.com/nekretnine)** — Serbia's #1 property portal — into a clean, structured Apify dataset.

This actor extracts apartments, houses, land, commercial space, garages and rooms (sale or rent) by location, transaction type, EUR price, m², rooms and owner type. Each record includes price (EUR), surface area, full Serbian address (city → municipality → district → micro-location), advertiser, image gallery and listing labels.

---

### Features

- 🇷🇸 **Serbia-wide coverage** — every Halooglasi location slug is supported (Beograd municipalities, Novi Sad, Niš, Kragujevac, etc.).
- 💰 **Native EUR pricing** with auto-computed `pricePerSqm`.
- 🏘️ **Four-level location chain** — city, municipality (`opština`), district, and micro-location parsed separately.
- 🛏️ **Serbian room-count handling** in 0.5 increments (`garsonjera`, `jednosoban`, `dvosoban`, `troiposoban`, …) returned as both numeric value and Serbian label.
- 🏢 **Advertiser data** — agency name, profile URL, agency ID and owner type (`Agencija` / `Vlasnik` / `Investitor`).
- 🖼️ **Image gallery** per listing (logo banners auto-filtered).
- 🏷️ **Card tier labels** (`Premium`, `Top`, `VIP`, …).
- 🛡️ **Cloudflare-resilient** — direct HTTP fetch via residential proxy with automatic retry on 403/429/503.
- 🔁 **De-duplication & loop detection** across paginated pages.

---

### Architecture

Halooglasi is a **Sitecore + ASP.NET** site. Each listing page server-side embeds an inline JS variable carrying the full ad payload:

```js
window.QuidditaEnvironment.serverListData = {
  Ads: [...],          // up to 20 ads per page
  TotalCount: 9198,
  TotalPages: 460,
  ...
};
````

The actor:

1. **Regex-extracts** the `serverListData` JSON blob from the response HTML.
2. **Walks `Ads[]`** — each ad gives `Id`, `Title`, `RelativeUrl`, `AdvertiserId`, and `ListHTML`.
3. **HTML-entity-decodes `ListHTML`** (the visible product card markup) and parses with `cheerio` to extract price (from `<span data-value>`), area, rooms, floor, location chain, images and advertiser.
4. **De-duplicates by `adId`** across pages and detects pagination loops.

If the JSON envelope is missing (rare), a `cheerio`-based HTML fallback parses `.product-item` cards directly.

> **No browser, no GraphQL, no Cloudflare-bypass tricks** — just `got-scraping` + `cheerio` over residential IPs.

***

### Input

| Field | Type | Default | Notes |
|---|---|---|---|
| `locationSlugs` | `string[]` | `["beograd"]` | One slug per task. Examples: `beograd`, `novi-sad`, `nis`, `kragujevac`, `beograd-novi-beograd`, `beograd-vracar`, `beograd-savski-venac-beograd-na-vodi`, `beograd-zvezdara`, `beograd-vozdovac`, `beograd-cukarica`, `beograd-zemun`, `beograd-palilula`, `beograd-stari-grad`. Find more by browsing halooglasi.com and copying the path between `/nekretnine/{txn}/` and `?` from the URL. |
| `transaction` | `sale \| rent` | `sale` | Maps to `prodaja` / `izdavanje`. |
| `propertyType` | enum | `apartment` | `apartment` (stan) / `house` (kuća) / `land` (zemljište) / `commercial` (poslovni prostor) / `garage` (garaža) / `room` (soba). |
| `priceMin` / `priceMax` | int (EUR) | `0` | `0` = no bound. |
| `areaMin` / `areaMax` | int (m²) | `0` | `0` = no bound. |
| `roomsMin` / `roomsMax` | num | `0` | Halooglasi uses `0.5` increments (`garsonjera = 0.5`, `dvosoban = 2`, `5+ = 5`). `0` = no bound. |
| `ownerType` | enum | `all` | `all` / `agency` / `owner` / `investor`. |
| `sort` | enum | `latest` | `latest` / `price_asc` / `price_desc` / `area_asc` / `area_desc`. |
| `maxListings` | int | `200` | Total cap across all tasks. `0` = unlimited. |
| `maxPagesPerTask` | int | `10` | Pagination depth per location (≈ 20 listings per page). Narrow with price/area for deeper inventory. |
| `requestDelay` | int (ms) | `1000` | Inter-request delay. ≥ 800 ms recommended. |
| `maxRetries` | int | `3` | Per-request retries on `403` / `429` / `503` (rotates proxy IP). |
| `proxyConfiguration` | proxy | RESIDENTIAL + RS | **Residential proxy strongly recommended** — Halooglasi sits behind Cloudflare and datacenter IPs frequently get blocked. Country `RS` is prefilled. |

#### Example input

```json
{
  "locationSlugs": ["beograd-novi-beograd", "beograd-vracar"],
  "transaction": "sale",
  "propertyType": "apartment",
  "priceMin": 80000,
  "priceMax": 250000,
  "areaMin": 40,
  "areaMax": 80,
  "roomsMin": 1.5,
  "roomsMax": 3,
  "ownerType": "agency",
  "sort": "latest",
  "maxListings": 500,
  "maxPagesPerTask": 25,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"],
    "apifyProxyCountry": "RS"
  }
}
```

***

### URL pattern (decoded)

```
https://www.halooglasi.com/nekretnine/{prodaja|izdavanje}-{stanova|kuca|zemljista|...}/{location-slug}
  ?cena_d_from=<int>
  &cena_d_to=<int>
  &cena_d_unit=4                              ← EUR (RSD = different code)
  &kvadratura_d_from=<int>
  &kvadratura_d_to=<int>
  &kvadratura_d_unit=1                        ← m²
  &broj_soba_order_i_from=<num>
  &broj_soba_order_i_to=<num>
  &oglasivac_nekretnine_s=Agencija|Vlasnik|Investitor
  &order=1|3|4|5|6                            ← latest / price asc / price desc / area asc / area desc
  &page=<N>
```

***

### Output

One Apify dataset record per listing:

| Field | Type | Description |
|---|---|---|
| `adId` | string | Halooglasi 13-digit listing ID |
| `detailUrl` | string | Full listing URL |
| `title` | string | Listing title |
| `shortDescription` | string | Card-level description snippet |
| `transactionType` | string | `sale` / `rent` |
| `propertyType` | string | `apartment` / `house` / `land` / … |
| `advertType` | string | Raw `Agencija` / `Vlasnik` / `Investitor` |
| `price` | number | Total price in EUR |
| `priceCurrency` | string | `EUR` |
| `pricePerSqm` | number | Price per m² (read from card or computed `price / areaSqm`) |
| `areaSqm` | number | Usable surface area (`kvadratura`) |
| `terrainAreaSqm` | number | Plot/terrain area (houses, land) |
| `rooms` | number | `0.5`, `1`, `1.5`, `2`, `2.5`, `3`, `3.5`, `4`, `4.5`, `5` |
| `roomsLabel` | string | `garsonjera` / `jednosoban` / `dvosoban` / `troiposoban` / … |
| `floor` | string | Floor number/label (`III`, `PR`, `VPR`, …) |
| `totalFloors` | string | Total floors in building |
| `buildingType` | string | `Stara gradnja` / `Novogradnja` / … |
| `heatingType` | string | `CG` / `EG` / `TA` / `podno` / … |
| `yearBuilt` | int | Construction year |
| `country` | string | `Srbija` |
| `city` | string | City |
| `municipality` | string | Opština |
| `district` | string | District |
| `microLocation` | string | Mikrolokacija (neighborhood) |
| `street` | string | Ulica |
| `fullAddress` | string | Composed `street, microLocation, district, municipality, city, Srbija` |
| `latitude` / `longitude` | number | List endpoint does not expose GPS — always `null` (would need per-ad detail fetch). |
| `mainImageUrl` | string | Cover photo |
| `imageUrls` | string\[] | All listing photos (agency logos filtered) |
| `imageCount` | int | Number of listing images |
| `advertiserId` | string | Halooglasi advertiser ID |
| `advertiserName` | string | Advertiser display name |
| `advertiserUrl` | string | Advertiser profile page |
| `advertiserType` | string | `Agencija` / `Vlasnik` / `Investitor` |
| `isRegistered` `hasElevator` `hasParking` `hasGarage` `hasTerrace` `hasBalcony` `isFurnished` | boolean | Detail-only on Halooglasi list endpoint — typically `null` (would need per-ad detail fetch). |
| `isExclusive` | boolean | True when card carries the `Ekskluziva` tier tag |
| `datePosted` | string | Most recent post date (when available) |
| `dateValidFrom` | string | Listing valid-from date (when available) |
| `labels` | string\[] | Tier tags (`Premium`, `Top`, `VIP`, …) |
| `searchTransaction` `searchPropertyType` `searchLocation` `searchUrl` | string | Echoes of the input search parameters |
| `scrapedAt` | string | ISO-8601 scrape timestamp |

Two dataset views are pre-configured:

- **Overview** — compact card-style table (ID, type, price, area, rooms, location, advertiser).
- **Full Detail** — every field above.

#### Sample record

```json
{
  "adId": "5425647088741",
  "detailUrl": "https://www.halooglasi.com/nekretnine/prodaja-stanova/fontana-svetao-za-adaptaciju/5425647088741?kid=4",
  "title": "Fontana, svetao, za adaptaciju",
  "shortDescription": "Na prodaju izuzetno svetao stan na jednoj od najtraženijih lokacija – Fontana...",
  "transactionType": "sale",
  "propertyType": "apartment",
  "advertType": "Agencija",
  "price": 220000,
  "priceCurrency": "EUR",
  "pricePerSqm": 3548,
  "areaSqm": 62,
  "rooms": 2,
  "roomsLabel": "dvosoban",
  "floor": "IX",
  "totalFloors": "9",
  "country": "Srbija",
  "city": "Beograd",
  "municipality": "Opština Novi Beograd",
  "district": "Fontana",
  "microLocation": "Pariske komune",
  "fullAddress": "Pariske komune, Fontana, Opština Novi Beograd, Beograd, Srbija",
  "mainImageUrl": "https://img.halooglasi.com/slike/oglasi/Thumbs/260429/m/fontana-svetao-za-adaptaciju-...jpg",
  "imageCount": 1,
  "advertiserId": "5587725",
  "advertiserName": "BELIGRAD",
  "advertiserUrl": "https://www.halooglasi.com/oglasi/BELIGRAD",
  "advertiserType": "Agencija",
  "isExclusive": false,
  "labels": ["Premium"],
  "searchLocation": "beograd",
  "scrapedAt": "2026-05-05T14:22:17.392Z"
}
```

***

### Important notes

- **Cloudflare protection** — Halooglasi explicitly blocks several AI crawlers in `robots.txt` and serves `403` from datacenter IPs. **Use Apify Residential Proxy with country `RS`** for reliable runs (prefilled in input). The actor automatically retries `403` / `429` / `503` responses with a fresh proxy session.
- **Currency is always EUR** (`cena_d_unit=4`). Halooglasi does internally support RSD but its UI defaults to EUR.
- **Room counts** are returned both as numbers (`0.5`, `1`, `1.5`, `2`, `2.5`, `3`, `3.5`, `4`, `4.5`, `5`) and as Serbian labels (`garsonjera`, `jednosoban`, `dvosoban`, `troiposoban`, …) for convenience.
- **Coordinates and feature flags** (lift, parking, garage, terrace, balcony, furnished, registered) are populated by Halooglasi's *detail endpoint*, not the *list endpoint* this scraper uses. They are kept in the schema (always `null` here) so downstream consumers can merge in detail-page enrichment if needed.
- **Pagination cap** — Halooglasi displays up to ~9,000 results per location; if you need a deep historical sweep, narrow with `priceMin` / `priceMax` / `areaMin` / `areaMax` ranges and run multiple tasks.
- **Throughput** — ~200 listings / ~70 seconds with residential proxy, including Cloudflare retries.

***

### Common location slugs

**Beograd municipalities** — `beograd-novi-beograd`, `beograd-vracar`, `beograd-savski-venac-beograd-na-vodi`, `beograd-zvezdara`, `beograd-vozdovac`, `beograd-cukarica`, `beograd-zemun`, `beograd-palilula`, `beograd-stari-grad`, `beograd-rakovica`, `beograd-mladenovac`, `beograd-grocka`, `beograd-obrenovac`, `beograd-surcin`, `beograd-lazarevac`, `beograd-barajevo`, `beograd-sopot`, `beograd-zvezdara-mirijevo`

**Other major cities** — `novi-sad`, `nis`, `kragujevac`, `subotica`, `pancevo`, `cacak`, `kraljevo`, `leskovac`, `zrenjanin`, `smederevo`, `valjevo`, `vranje`, `uzice`, `sabac`, `sombor`, `pozarevac`, `zajecar`

To find more, browse a result page on halooglasi.com and copy the slug from the URL between `/nekretnine/{txn-type}/` and `?`.

***

### Troubleshooting

| Symptom | Likely cause | Fix |
|---|---|---|
| Repeated `403` warnings, 0 results | Datacenter proxy or no proxy | Switch to **Residential** with country `RS` |
| `Two empty pages — stopping` early | Filters too narrow for that location | Loosen price/area/rooms or split into multiple tasks |
| `Pagination loop detected` | Halooglasi caps result set ~9k per query | Narrow with price/area ranges to slice the inventory |
| `floor` / `totalFloors` null on some rows | Listing didn't include a floor feature | Expected — not every Halooglasi ad provides this field |
| `latitude` / `longitude` always null | List endpoint doesn't expose coordinates | Expected — would require per-ad detail fetch |

***

### License

Apache-2.0

# Actor input Schema

## `locationSlugs` (type: `array`):

URL location slugs from Halooglasi. Each slug becomes its own scraping task. Leave empty for nationwide. Common values: `beograd`, `novi-sad`, `nis`, `kragujevac`, `beograd-novi-beograd`, `beograd-vracar`, `beograd-savski-venac-beograd-na-vodi`, `beograd-zvezdara`, `beograd-vozdovac`, `beograd-cukarica`, `beograd-zemun`, `beograd-palilula`, `beograd-stari-grad`. Find more by browsing halooglasi.com and copying the path between `/nekretnine/{txn}/` and `?` from the URL.

## `transaction` (type: `string`):

Sale (`prodaja`) or rent (`izdavanje`).

## `propertyType` (type: `string`):

Halooglasi URL category slug.

## `priceMin` (type: `integer`):

Minimum price in EUR. 0 = no minimum.

## `priceMax` (type: `integer`):

Maximum price in EUR. 0 = no maximum.

## `areaMin` (type: `integer`):

Minimum surface area. 0 = no minimum.

## `areaMax` (type: `integer`):

Maximum surface area. 0 = no maximum.

## `roomsMin` (type: `number`):

Minimum room count. Halooglasi uses 0.5 increments (garsonjera=0.5, jednosoban=1, jednoiposoban=1.5, dvosoban=2, dvoiposoban=2.5, trosoban=3, troiposoban=3.5, cetvorosoban=4, 5+). 0 = no minimum.

## `roomsMax` (type: `number`):

Maximum room count. 0 = no maximum.

## `ownerType` (type: `string`):

Filter by who's listing the property.

## `sort` (type: `string`):

Result ordering.

## `maxListings` (type: `integer`):

Total cap across all location tasks (0 = unlimited).

## `maxPagesPerTask` (type: `integer`):

Pagination depth per location. Halooglasi typically returns ~20 listings per page. Narrow with price/area for deeper inventory.

## `requestDelay` (type: `integer`):

Delay between sequential page requests. Halooglasi is Cloudflare-protected — keep ≥ 800ms.

## `maxRetries` (type: `integer`):

Retries per request on HTTP errors (rotates proxy IP).

## `proxyConfiguration` (type: `object`):

Apify Proxy is strongly recommended. Halooglasi sits behind Cloudflare — RESIDENTIAL with country=RS is recommended; datacenter often gets 403.

## Actor input object example

```json
{
  "locationSlugs": [
    "beograd"
  ],
  "transaction": "sale",
  "propertyType": "apartment",
  "priceMin": 0,
  "priceMax": 0,
  "areaMin": 0,
  "areaMax": 0,
  "roomsMin": 0,
  "roomsMax": 0,
  "ownerType": "all",
  "sort": "latest",
  "maxListings": 200,
  "maxPagesPerTask": 10,
  "requestDelay": 1000,
  "maxRetries": 3,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "RS"
  }
}
```

# Actor output Schema

## `adId` (type: `string`):

Halooglasi listing numeric ID

## `detailUrl` (type: `string`):

Full URL to the listing page

## `title` (type: `string`):

Listing title

## `shortDescription` (type: `string`):

Card-level description snippet

## `transactionType` (type: `string`):

sale / rent

## `propertyType` (type: `string`):

apartment / house / land / commercial / garage / room

## `advertType` (type: `string`):

Agencija / Vlasnik / Investitor (raw)

## `price` (type: `string`):

Total price in EUR

## `priceCurrency` (type: `string`):

Currency (EUR)

## `pricePerSqm` (type: `string`):

Price per square meter

## `areaSqm` (type: `string`):

Usable surface area (kvadratura)

## `terrainAreaSqm` (type: `string`):

Plot/terrain area (houses, land)

## `rooms` (type: `string`):

Room count (0.5, 1, 1.5, 2, 2.5, ..., 5+)

## `roomsLabel` (type: `string`):

Serbian room label (garsonjera, dvosoban, etc.)

## `floor` (type: `string`):

Floor number/label

## `totalFloors` (type: `string`):

Total floors in the building

## `buildingType` (type: `string`):

Stara gradnja / Novogradnja

## `heatingType` (type: `string`):

CG / EG / TA / podno / etc.

## `yearBuilt` (type: `string`):

Construction year

## `country` (type: `string`):

Country (Srbija default)

## `city` (type: `string`):

City

## `municipality` (type: `string`):

Opština

## `district` (type: `string`):

District

## `microLocation` (type: `string`):

Mikrolokacija (neighborhood)

## `street` (type: `string`):

Street name (ulica)

## `fullAddress` (type: `string`):

Composed address string

## `latitude` (type: `string`):

GPS latitude

## `longitude` (type: `string`):

GPS longitude

## `mainImageUrl` (type: `string`):

Cover photo

## `imageUrls` (type: `string`):

All listing images

## `imageCount` (type: `string`):

Total images

## `advertiserId` (type: `string`):

Advertiser ID

## `advertiserName` (type: `string`):

Advertiser display name

## `advertiserUrl` (type: `string`):

Advertiser profile page

## `advertiserType` (type: `string`):

Agencija / Vlasnik / Investitor

## `isRegistered` (type: `string`):

Property registered with the cadastre

## `hasElevator` (type: `string`):

Building has elevator

## `hasParking` (type: `string`):

Has parking spot

## `hasGarage` (type: `string`):

Has garage

## `hasTerrace` (type: `string`):

Has terrace

## `hasBalcony` (type: `string`):

Has balcony

## `isFurnished` (type: `string`):

Furnished property

## `isExclusive` (type: `string`):

Exclusive listing flag

## `datePosted` (type: `string`):

Most recent post date

## `dateValidFrom` (type: `string`):

Listing valid-from date

## `labels` (type: `string`):

Listing labels/badges

## `searchTransaction` (type: `string`):

Transaction used in search

## `searchPropertyType` (type: `string`):

Property type used in search

## `searchLocation` (type: `string`):

Location slug used in search

## `searchUrl` (type: `string`):

Full search URL used

## `scrapedAt` (type: `string`):

ISO timestamp

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "locationSlugs": [
        "beograd"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "RS"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("logiover/halooglasi-property-scraper-serbia-real-estate").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "locationSlugs": ["beograd"],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "RS",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("logiover/halooglasi-property-scraper-serbia-real-estate").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "locationSlugs": [
    "beograd"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "RS"
  }
}' |
apify call logiover/halooglasi-property-scraper-serbia-real-estate --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=logiover/halooglasi-property-scraper-serbia-real-estate",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Halooglasi.com Property Scraper — Serbia Real Estate",
        "description": "Scrape real estate listings from Halooglasi.com — Serbia's #1 property portal. Extract apartments, houses, land, commercial, garages and rooms (sale or rent) by location, EUR price, m², rooms and owner type. Returns price, area, GPS-ready address, advertiser and image gallery per ad.",
        "version": "0.0",
        "x-build-id": "ylsu3htEyk3tMIMrl"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/logiover~halooglasi-property-scraper-serbia-real-estate/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-logiover-halooglasi-property-scraper-serbia-real-estate",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/logiover~halooglasi-property-scraper-serbia-real-estate/runs": {
            "post": {
                "operationId": "runs-sync-logiover-halooglasi-property-scraper-serbia-real-estate",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/logiover~halooglasi-property-scraper-serbia-real-estate/run-sync": {
            "post": {
                "operationId": "run-sync-logiover-halooglasi-property-scraper-serbia-real-estate",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "locationSlugs"
                ],
                "properties": {
                    "locationSlugs": {
                        "title": "Location Slugs",
                        "type": "array",
                        "description": "URL location slugs from Halooglasi. Each slug becomes its own scraping task. Leave empty for nationwide. Common values: `beograd`, `novi-sad`, `nis`, `kragujevac`, `beograd-novi-beograd`, `beograd-vracar`, `beograd-savski-venac-beograd-na-vodi`, `beograd-zvezdara`, `beograd-vozdovac`, `beograd-cukarica`, `beograd-zemun`, `beograd-palilula`, `beograd-stari-grad`. Find more by browsing halooglasi.com and copying the path between `/nekretnine/{txn}/` and `?` from the URL.",
                        "default": [
                            "beograd"
                        ],
                        "items": {
                            "type": "string"
                        }
                    },
                    "transaction": {
                        "title": "Transaction Type",
                        "enum": [
                            "sale",
                            "rent"
                        ],
                        "type": "string",
                        "description": "Sale (`prodaja`) or rent (`izdavanje`).",
                        "default": "sale"
                    },
                    "propertyType": {
                        "title": "Property Type",
                        "enum": [
                            "apartment",
                            "house",
                            "land",
                            "commercial",
                            "garage",
                            "room"
                        ],
                        "type": "string",
                        "description": "Halooglasi URL category slug.",
                        "default": "apartment"
                    },
                    "priceMin": {
                        "title": "Min Price (EUR)",
                        "minimum": 0,
                        "maximum": 100000000,
                        "type": "integer",
                        "description": "Minimum price in EUR. 0 = no minimum.",
                        "default": 0
                    },
                    "priceMax": {
                        "title": "Max Price (EUR)",
                        "minimum": 0,
                        "maximum": 100000000,
                        "type": "integer",
                        "description": "Maximum price in EUR. 0 = no maximum.",
                        "default": 0
                    },
                    "areaMin": {
                        "title": "Min Area (m²)",
                        "minimum": 0,
                        "maximum": 1000000,
                        "type": "integer",
                        "description": "Minimum surface area. 0 = no minimum.",
                        "default": 0
                    },
                    "areaMax": {
                        "title": "Max Area (m²)",
                        "minimum": 0,
                        "maximum": 1000000,
                        "type": "integer",
                        "description": "Maximum surface area. 0 = no maximum.",
                        "default": 0
                    },
                    "roomsMin": {
                        "title": "Min Rooms",
                        "minimum": 0,
                        "maximum": 10,
                        "type": "number",
                        "description": "Minimum room count. Halooglasi uses 0.5 increments (garsonjera=0.5, jednosoban=1, jednoiposoban=1.5, dvosoban=2, dvoiposoban=2.5, trosoban=3, troiposoban=3.5, cetvorosoban=4, 5+). 0 = no minimum.",
                        "default": 0
                    },
                    "roomsMax": {
                        "title": "Max Rooms",
                        "minimum": 0,
                        "maximum": 10,
                        "type": "number",
                        "description": "Maximum room count. 0 = no maximum.",
                        "default": 0
                    },
                    "ownerType": {
                        "title": "Owner Type",
                        "enum": [
                            "all",
                            "agency",
                            "owner",
                            "investor"
                        ],
                        "type": "string",
                        "description": "Filter by who's listing the property.",
                        "default": "all"
                    },
                    "sort": {
                        "title": "Sort Order",
                        "enum": [
                            "latest",
                            "price_asc",
                            "price_desc",
                            "area_asc",
                            "area_desc"
                        ],
                        "type": "string",
                        "description": "Result ordering.",
                        "default": "latest"
                    },
                    "maxListings": {
                        "title": "Max Listings",
                        "minimum": 0,
                        "maximum": 1000000,
                        "type": "integer",
                        "description": "Total cap across all location tasks (0 = unlimited).",
                        "default": 200
                    },
                    "maxPagesPerTask": {
                        "title": "Max Pages per Task",
                        "minimum": 1,
                        "maximum": 200,
                        "type": "integer",
                        "description": "Pagination depth per location. Halooglasi typically returns ~20 listings per page. Narrow with price/area for deeper inventory.",
                        "default": 10
                    },
                    "requestDelay": {
                        "title": "Request Delay (ms)",
                        "minimum": 0,
                        "maximum": 30000,
                        "type": "integer",
                        "description": "Delay between sequential page requests. Halooglasi is Cloudflare-protected — keep ≥ 800ms.",
                        "default": 1000
                    },
                    "maxRetries": {
                        "title": "Max Retries",
                        "minimum": 0,
                        "maximum": 10,
                        "type": "integer",
                        "description": "Retries per request on HTTP errors (rotates proxy IP).",
                        "default": 3
                    },
                    "proxyConfiguration": {
                        "title": "Proxy Configuration",
                        "type": "object",
                        "description": "Apify Proxy is strongly recommended. Halooglasi sits behind Cloudflare — RESIDENTIAL with country=RS is recommended; datacenter often gets 403."
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
