# Zonaprop Argentina - Properties, Prices & Agencies (`abotapi/zonaprop-scraper`) Actor

Scrape Zonaprop.com.ar property listings across Argentina. Extract 140+ fields including USD/ARS prices, price per m², expenses, area, rooms, bedrooms, bathrooms, GPS, descriptions, photos, agency contacts, phone and WhatsApp. Supports buy, rent, temporary listings, filters, sorting and URLs.

- **URL**: https://apify.com/abotapi/zonaprop-scraper.md
- **Developed by:** [Abot API](https://apify.com/abotapi) (community)
- **Categories:** Real estate, Automation, Lead generation
- **Features:** Limited permissions
- **Stats:** 8 total users, 0 monthly users, 93.2% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 property 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/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Zonaprop Scraper: Property Listings, Prices & Agency Contacts Across Argentina

Zonaprop Scraper turns zonaprop.com.ar into a clean, structured properties feed. Search any city or neighborhood in Argentina with buy, rent or temporary rent filters, or paste any number of zonaprop search URLs, and get back one flat record per property with price in both USD and ARS, expenses, area, rooms, bedrooms, bathrooms, GPS coordinates, the full description, every photo, and the agency or owner contact including phone and WhatsApp. Results are collected page by page up to a single hard cap you control, then exported to JSON, CSV or Excel, or pulled straight into your app through the API.

### Why This Scraper?

- **150+ named fields per property**, including USD and ARS prices, price per square metre, expenses, areas, rooms, garages, age, GPS, the full description and the photo set.
- **Agency and owner contacts**: name, type, profile URL, phone and WhatsApp number.
- **Two input modes**: build searches from location names plus filters, or paste zonaprop URLs of any supported shape (search, agency and single property pages).
- **Filters that follow you into URL mode**: price, currency, area, room, bedroom, bathroom and agency filters narrow both a location search and a pasted URL.
- **Incremental monitoring**: scheduled runs return only new, changed and reappeared listings, and three dataset views (Overview, Agency & Contacts, Detail) organise the output.
- **Fails loudly, bills fairly**: if the site refuses every request the run stops with a clear error, and an empty search finishes with an empty dataset and no placeholder row.

### Use Cases

- **Real estate portals and PropTech teams:** build a comparison site or search index of Argentina listings with price, area and location data.
- **Investors and analysts:** track price per square metre, expenses and inventory mix across neighborhoods and cities.
- **Lead generation and CRM tools:** pull agency and owner phone and WhatsApp contacts for outreach lists.
- **Market researchers:** monitor buy versus rent inventory and pricing trends over time.
- **Mapping and listing apps:** feed GPS coordinates, photos and descriptions into your own map or UI.

### Data You Get

> Sample shape: values are illustrative placeholders, not from a live listing.

| Field | Example |
| --- | --- |
| `postingId` | `"00000000"` |
| `title` | `"Bright 2-bedroom apartment in Palermo"` |
| `description` | `"Sunny apartment, fully equipped, close to transport and shops."` |
| `operationType` | `"Venta"` |
| `propertyType` | `"Departamentos"` |
| `price` | `185000` |
| `currency` | `"USD"` |
| `priceUsd` / `priceArs` | `185000` / `null` |
| `expenses` | `80000` |
| `totalArea` / `coveredArea` | `72` / `65` |
| `rooms` | `3` |
| `bedrooms` | `2` |
| `bathrooms` | `1` |
| `garages` | `1` |
| `neighborhood` | `"Palermo"` |
| `city` / `province` | `"Capital Federal"` / `"Capital Federal"` |
| `latitude` / `longitude` | `-34.588` / `-58.43` |
| `publisherName` | `"Jane Doe Propiedades"` |
| `publisherType` | `"agency"` |
| `publisherPhone` / `publisherWhatsapp` | `"5491100000000"` / `"5491100000000"` |
| `mainImage` / `photoCount` | `"https://example.com/photo-1.jpg"` / `2` (equal to the length of `images`) |
| `url` | `"https://www.zonaprop.com.ar/propiedades/clasificado/example-00000000.html"` |

Every record also carries `featuresDetail` (each feature with its category, label, value and unit) and `publicationPlanTypes`. Property pages (single-property URLs and **Fetch full description**) add `publicationDate` (when the ad went online), `publishedAgo`, `viewCount`, `floorPlanUrls` and the property's own feature groups: `amenities`, `featuresDetailGroups` and one `featuresDetail` row per feature with its group name as `categoryName` (search cards alone leave these groups empty). It also carries the property age, amenities, the full photo array, the modified and scraped timestamps, and a set of alias fields that mirror the field names used by other property-scraper outputs (for example `id`, `name`, `location`, `amount`, `geolocation` and `whatsapp`), so a downstream pipeline built for a competitor's field names keeps working without changes.

### How to Use

1. Pick a **mode**: `search` (build a search from locations and filters) or `url` (paste one or more zonaprop search URLs).
2. Fill in the fields for that mode: locations, operation and property type for search mode, or the URLs to paste for URL mode. Price, currency, area, room and bedroom filters apply in both modes.
3. Set **Max listings** to control run size and cost, then click **Start**.
4. Download the dataset as JSON, CSV or Excel, or read it through the API.

**Search by location and filters:**

```json
{
  "mode": "search",
  "locations": ["Palermo", "Belgrano"],
  "operationType": "sale",
  "propertyType": "apartment",
  "minPrice": 100000,
  "maxPrice": 300000,
  "currency": "USD",
  "sortBy": "price-asc",
  "maxListings": 100
}
```

**Paste one or more search URLs:**

```json
{
  "mode": "url",
  "urls": [
    "https://www.zonaprop.com.ar/casas-venta-cordoba.html",
    "https://www.zonaprop.com.ar/departamentos-alquiler-palermo.html"
  ],
  "maxPages": 5,
  "maxListings": 200
}
```

**Search with the full, untruncated description fetched per property:**

```json
{
  "mode": "search",
  "locations": ["Capital Federal"],
  "operationType": "rent",
  "fetchDetails": true,
  "maxListings": 50
}
```

**Search with a bounded connection budget:**

```json
{
  "mode": "search",
  "locations": ["Mendoza"],
  "operationType": "sale",
  "maxListings": 300,
  "residentialCap": 150,
  "trafficBudgetMb": 200
}
```

#### Run it from your code

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/zonaprop-scraper").call(run_input={
    "mode": "search",
    "locations": ["Palermo"],
    "operationType": "sale",
    "maxListings": 50,
})
for listing in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(listing["title"], listing["price"], listing["currency"])
```

JavaScript:

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

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/zonaprop-scraper').call({
  mode: 'search',
  locations: ['Palermo'],
  operationType: 'sale',
  maxListings: 50,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the **Integrations** tab.

#### URL mode: supported shapes

| Shape | Example | What you get |
| --- | --- | --- |
| Search page | `https://www.zonaprop.com.ar/departamentos-venta-palermo.html` | All listings of the search, page by page |
| Search page, later page | `.../departamentos-venta-palermo-pagina-2.html` | Reading starts at that page |
| Rooms slug | `.../departamentos-alquiler-palermo-2-ambientes.html` | Listings for that room count |
| Sort slug | `.../departamentos-venta-capital-federal-orden-precio-ascendente.html` | Listings in the order the URL carries |
| Province or city search | `.../inmuebles-venta-cordoba.html` | All property types in that location |
| Temporary rent | `.../casas-alquiler-temporal-mar-del-plata.html` | Temporary rental listings |
| Single property page | `.../propiedades/clasificado/<slug>-<id>.html` | One row for that property |
| Agency page | `.../inmobiliarias/<agency>_<id>-inmuebles.html` | The agency's listings |
| Agency page, later page | `.../inmobiliarias/<agency>_<id>-inmuebles-pagina-2.html` | Reading starts at that page |

The agency directory (`/inmobiliarias.bum`) is not supported and is skipped with a warning. Non-www and mobile hosts are normalised to www.

**Default list.** If you switch to URL mode and leave the URLs field unedited, the run scrapes the nine example URLs above (one of each shape) instead of failing with no URLs. Clear the field and add your own URLs to scrape only those.

#### Incremental mode

Turn on `incrementalMode` for scheduled monitoring. The first run returns every listing as `NEW`; later runs return only `NEW`, `UPDATED` and `REAPPEARED` listings. Each row carries `changeType`, `changedFields`, `firstSeenAt` and `lastSeenAt`. `emitUnchanged` also returns unchanged rows (marked `UNCHANGED`, billed as normal listings), `emitExpired` marks listings that disappeared (only after a complete scan), `stateKey` names the campaign and `ignoreFieldsForChanges` lists fields that must not trigger `UPDATED`. Single-property pages you paste are tracked too (separately from search rows), so an unchanged property page is neither returned nor billed on later runs. The saved state is updated while the run is going, so a stopped or timed-out run does not make the next one return everything again.

#### Billing

The **Pricing** tab shows the current rates; this is what the actor charges:

- **Actor start**: once per run.
- **Property result**: once per row saved to the dataset (listings, single-property rows, and `UNCHANGED` / `EXPIRED` rows when you ask for them).
- **Detail enrichment**: once per property page successfully fetched when `fetchDetails` is on, charged right after that page of results is saved. It is never charged for unchanged rows, and not at all when `fetchDetails` is off.

A run that is refused by the site, or an empty search, writes no rows, so no Property result is charged; only the Actor start event applies.

#### How Max listings and Max pages shape a run

**Max listings** is the run's single hard cap: the total number of properties returned across every location or URL, split evenly between them. Set it to `0` for no cap. **Max pages** is an optional extra safety stop on how many result pages (about 30 listings each) are read per location or URL; leave it empty for no page cap, in which case the run is bounded solely by Max listings. Turning on **Fetch full description** adds one extra request per property to pull the untruncated description text; the search results already include a description, location, GPS, contacts, prices and photos, so most runs never need it.

### Send results into your apps (MCP connectors)

Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step **after** the scrape: the Apify dataset is never changed.

**What gets written to the connector:** a condensed, human-readable **summary** of each record, not the full JSON. Each item becomes one entry with a **title** and its key fields flattened to plain text. The **complete record always stays in the Apify dataset**.

1. Authorize a connector once under **Apify → Settings → Integrations** (Notion, Linear, Airtable, or Apify).
2. Select it in the **"Pipe results into your apps"** input field. (If the picker is empty, you haven't authorized a connector yet.)
3. For **Notion**, also set `notionParentPageUrl` to the page where items should be created.

The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.

### Input Parameters

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `mode` | string | `search` | `search` (build from locations and filters) or `url` (paste search URLs). |
| `locations` | array | none (prefill: `["Capital Federal"]`) | Location names to search, e.g. Capital Federal, Palermo, Cordoba. Search mode only. |
| `operationType` | string | `sale` | Buy (sale), rent, or temporary rent. Search mode only. |
| `propertyType` | string | `all` | Property category: all, apartment, house, ph, land, office, store, warehouse, country_house, farm, office_practice, building or garage. Search mode only. |
| `minPrice` | integer | none | Minimum price in the listing currency. Applies in both modes, including a pasted URL. |
| `maxPrice` | integer | none | Maximum price in the listing currency. Applies in both modes, including a pasted URL. |
| `currency` | string | `any` | Keep only listings in this currency: any, USD or ARS. Applies in both modes, including a pasted URL. |
| `minArea` | integer | none | Minimum total area in square metres. Applies in both modes, including a pasted URL. |
| `maxArea` | integer | none | Maximum total area in square metres. Applies in both modes, including a pasted URL. |
| `minRooms` | integer | none | Minimum number of rooms (ambientes). Applies in both modes, including a pasted URL. |
| `maxRooms` | integer | none | Maximum number of rooms (ambientes). Applies in both modes, including a pasted URL. |
| `minBathrooms` | integer | none | Minimum number of bathrooms. Applies in both modes, including a pasted URL. Listings with no stated bathroom count are excluded. |
| `agenciesOnly` | boolean | `false` | Keep only listings published by an agency (drops private owners). Applies in both modes, including a pasted URL. |
| `minBedrooms` | integer | none | Minimum number of bedrooms (dormitorios). Applies in both modes, including a pasted URL. There is no maximum-bedrooms filter. |
| `sortBy` | string | `relevance` | relevance, price-asc, price-desc or newest. Search mode only; a pasted URL carries its own order. |
| `urls` | array | one example of each supported shape | Zonaprop URLs for URL mode: search pages (any type, operation, location, rooms or sort slug, temporary rent, `-pagina-N` to start from a page), agency pages and single property pages. The agency directory is not supported. Non-www and mobile hosts are normalised to www. Location, operation, property type and sort order above are ignored in this mode; the filters above still apply to search pages. |
| `fetchDetails` | boolean | `false` | Fetch each property page to add the full untruncated description. Off by default. When on, the Detail enrichment event is charged per property page successfully fetched, right after that page of results is saved, so a run that stops early is still billed correctly for what it delivered. The listing already carries a description, location, GPS, contacts, prices and photos. |
| `maxPages` | integer | none (leave empty = unlimited) | Optional safety stop on how many result pages to read per location or URL (about 30 listings per page). Does not cap the run; Max listings does that. |
| `maxListings` | integer | `20` | The run's single hard cap: maximum total listings across all searches. Set `0` for unlimited. |
| `proxy` | object | none (prefill: residential, country Argentina) | Connection settings. When left empty, the actor applies this same residential Argentina configuration automatically, since the site only serves results to an Argentine residential connection. |
| `allowProxyDowngrade` | boolean | `true` | When on, the run may fall back to a backup connection when the primary connection is refused for the account or keeps failing on a page, and stays on it while it serves results. When off, the run uses only the configured proxy and never escalates to another connection. The residential cap and traffic budget, when set, move the run to the cheaper backup connection once reached whatever this setting says. |
| `residentialCap` | integer | none (empty or `0` = no cap) | Optional ceiling on how many requests may use the primary residential connection in one run. Once reached, the run switches to the cheaper backup connection. |
| `trafficBudgetMb` | integer | none (empty or `0` = no budget) | Optional cap on total downloaded data per run, in megabytes. Once reached, the run switches to the cheaper backup connection. |
| `resumeFromRunId` | string | empty | Paste a previous run ID or dataset ID to continue an interrupted pull: listings already collected there are skipped and not returned or billed again. |
| `incrementalMode` | boolean | `false` | For scheduled runs: the first run returns every listing as NEW; later runs return only NEW, UPDATED and REAPPEARED listings. Each row gets `changeType`, `changedFields`, `firstSeenAt` and `lastSeenAt`. |
| `stateKey` | string | none | Optional name for the monitoring campaign. Empty = derived automatically from the mode, locations or URLs, operation, property type and filters. |
| `emitUnchanged` | boolean | `false` | Also return unchanged listings, marked UNCHANGED. These rows are returned and billed as normal listings; detail enrichment is not run for them. |
| `emitExpired` | boolean | `false` | Also return listings that are no longer found, marked EXPIRED. Only when the run read every result page of every search to the end (no Max listings cap hit, no Max pages limit, no URL starting past page 1). |
| `ignoreFieldsForChanges` | array | none | Extra field names (dotted paths for nested fields) that must not make a listing count as UPDATED. They are still returned in the output. |
| `mcpConnectors` | array | none | Optional: send a condensed summary of each record to apps you authorized under Integrations (Notion, Linear, Airtable or Apify). |
| `notionParentPageUrl` | string | none | Notion connector only: page (URL or id) under which item pages are created. |
| `maxNotifyListings` | integer | `50` | Cap on items written to each connector per run. Does not affect the dataset. |

### Output Example

> Sample shape: values are illustrative placeholders, not from a live listing.

```json
{
  "postingId": "00000000",
  "postingCode": "AAAAAA",
  "url": "https://www.zonaprop.com.ar/propiedades/clasificado/example-00000000.html",
  "title": "Bright 2-bedroom apartment in Palermo",
  "description": "Sunny apartment, fully equipped, close to transport and shops.",
  "propertyType": "Departamentos",
  "operationType": "Venta",
  "status": "ONLINE",
  "price": 185000,
  "currency": "USD",
  "priceUsd": 185000,
  "priceArs": null,
  "expenses": 80000,
  "expensesCurrency": "$",
  "totalArea": 72,
  "coveredArea": 65,
  "rooms": 3,
  "bedrooms": 2,
  "bathrooms": 1,
  "garages": 1,
  "age": 8,
  "address": "Example St 100",
  "neighborhood": "Palermo",
  "city": "Capital Federal",
  "province": "Capital Federal",
  "country": "Argentina",
  "latitude": -34.588,
  "longitude": -58.43,
  "mainImage": "https://example.com/photo-1.jpg",
  "images": ["https://example.com/photo-1.jpg", "https://example.com/photo-2.jpg"],
  "photoCount": 2,
  "amenities": ["Pool", "Gym"],
  "publisherName": "Jane Doe Propiedades",
  "publisherType": "agency",
  "publisherPhone": "5491100000000",
  "publisherWhatsapp": "5491100000000",
  "hasWhatsapp": true,
  "modifiedDate": "2026-01-01T00:00:00-0300",
  "scrapedAt": "2026-01-01T00:00:00+00:00"
}
```

### Plan Requirement

zonaprop.com.ar sits behind a bot challenge that a datacenter connection fails most of the time (it is occasionally let through, so results there are unreliable). An Argentine residential connection is required for dependable results, so keep the default connection configuration (residential, country Argentina). If a residential connection is not available on your plan, the actor logs a clear warning and tries a backup connection, which may still return nothing. When no connection can load any page, the run fails with a clear message rather than returning an empty dataset: either "The proxy connection was refused for this account, so no page could be read. Your Apify plan does not include proxy access; a paid plan is required", "No results: residential proxies are unavailable on this run (Apify free plans do not include them), and the backup connection could not load the requested Zonaprop pages", or "Could not load any results page (the requests failed), so nothing was collected. This is a connection problem, not an empty search."

#### Cost controls

The actor automatically retries with a different connection when one is refused. To bound connection spend you can also:

- set `residentialCap` to limit how many requests use the primary residential connection per run;
- set `trafficBudgetMb` to cap total downloaded data per run;
- leave `allowProxyDowngrade` on (the default) so the run falls back to a cheaper backup connection after the primary connection keeps failing, and stays on it for the rest of the run; turn it off to use only the configured proxy (the cap and budget above still apply).

When either the residential cap or the traffic budget is reached, the run continues on the cheaper backup connection instead of stopping.

### FAQ

#### How much does it cost?

You pay a small fee per run start, per property returned, and per property page fetched when you turn on the full-description fetch (see Billing above). The **Pricing** tab shows the current rates. Use **Max listings** to cap the cost of any run.

#### Is it legal to scrape Zonaprop?

This actor collects only publicly available property listing data. You are responsible for how you use it: follow zonaprop's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Listing facts such as price and area are generally not protected, but photos and agency data may be subject to third-party rights.

#### Can I schedule it, or only get new listings?

You can schedule the actor from the **Schedules** tab like any other actor. Turn on **Incremental changes for scheduled runs** and the actor remembers each listing between runs (state is kept per search, or per **State key** you choose). The first run returns everything as NEW; after that you get only NEW, UPDATED and REAPPEARED listings, and listings that did not change are neither returned nor billed. `changedFields` names exactly what moved. Photo URLs, the antiquity counter (`age`, `yearBuilt`, `condition`), the per-visit `viewCount`, the daily `publishedAgo` text and `scrapedAt` never count as changes, though they are still returned; add more in **Ignore fields when detecting changes**. In incremental mode, detail enrichment (`fetchDetails`) and its charge apply only to NEW, UPDATED and REAPPEARED rows, never to unchanged ones, and an incremental run where nothing changed returns an empty dataset. Without incremental mode every run reads the live site from scratch.

#### What changed in URL mode?

URL mode now accepts search pages, agency pages and single property pages (a property page returns one row with its title, description and main image). The agency directory (`/inmobiliarias.bum`) is not supported and is skipped with a warning. The URLs field now has a default: if you switch to URL mode and leave it unedited, the run scrapes one example of each shape instead of failing with no URLs. Clear the field and add your own URLs to avoid this.

#### Why do my price, area and room filters still apply when I paste a URL?

By design. Location, operation type, property type and sort order are only meaningful in search mode, since a pasted URL already encodes them, so they're ignored in URL mode. But price, currency, area, room, bedroom, bathroom and agency filters narrow the results regardless of mode, so they still apply on top of a pasted URL.

#### Why did my run fail instead of returning an empty dataset?

If URL mode has no search URLs, the run fails immediately with an input error before any request is made, and nothing is charged for results; add at least one zonaprop search URL. If the site refuses every single request, the run stops with a clear error instead of billing you for a result that looks empty but was actually never read. A genuinely empty search, where the site answered but had nothing to show, succeeds with an empty dataset (earlier versions wrote a single placeholder row, which was billed as a result; it no longer does). If you see the connection-failure error, retry with an Argentina residential connection.

#### Can I use it with AI agents or MCP?

Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.

### 🔗 Want more real estate data?

Pair this actor with these related scrapers from the same team:

<table>
<tr><td>🚗 <a href="https://apify.com/abotapi/dubizzle-com-scraper"><b>Dubizzle.com Scraper</b></a><br>Scrape dubizzle.com across the UAE for property, motors, and agent listings. Search by...</td><td>🏠 <a href="https://apify.com/abotapi/immoscout24-scraper"><b>ImmobilienScout24.de Scraper</b></a><br>Extract property listings from immobilienscout24.de, Germany's #1 real estate platform...</td></tr>
<tr><td>🏠 <a href="https://apify.com/abotapi/fotocasa-es-scraper"><b>Fotocasa.es</b></a><br>Scrape Spain property listings from fotocasa.es. Get price, surface, rooms, baths...</td><td>🏠 <a href="https://apify.com/abotapi/iproperty-com-my-scraper"><b>iProperty MY Scraper</b></a><br>Scrape property listings from iProperty.com.my for sale or rent: price, PSF, bedrooms...</td></tr>
<tr><td>🏠 <a href="https://apify.com/abotapi/domclick-scraper"><b>Domclick RU Property Scraper</b></a><br>Extract property listings from domclick.ru, one of Russia’s largest real estate portals...</td><td>🏠 <a href="https://apify.com/abotapi/quintoandar-scraper"><b>QuintoAndar Scraper</b></a><br>Scrape QuintoAndar property listings across Brazil with 80+ fields, including rent, sale...</td></tr>
</table>

👉 [Browse all abotapi scrapers](https://apify.com/abotapi)

### 💬 Support

- 🐞 **Found a bug or a missing field?** Open a ticket on the [Issues tab](https://apify.com/abotapi/zonaprop-scraper/issues/open). We usually reply within hours.
- 🛠️ **Need another site, extra fields or a private build?** Email <contact@abotapi.com>.
- ⭐ **Enjoying it?** A quick review on the actor page helps other users find it.

# Actor input Schema

## `mode` (type: `string`):

search = build searches from location names + filters. url = paste one or more zonaprop search URLs.

## `locations` (type: `array`):

Location names to search, e.g. Capital Federal, Palermo, Cordoba, Mendoza. Accents and spaces are handled automatically. Only applies when mode = search.

## `operationType` (type: `string`):

Buy, rent or temporary rent. Only applies when mode = search.

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

Property category to search. 'All' covers every type. Only applies when mode = search.

## `minPrice` (type: `integer`):

Minimum price in the listing currency. Applies in Search mode and URL mode, including a pasted URL.

## `maxPrice` (type: `integer`):

Maximum price in the listing currency. Applies in Search mode and URL mode, including a pasted URL.

## `currency` (type: `string`):

Keep only listings priced in this currency. Argentine listings are quoted in USD or ARS. Applies in Search mode and URL mode, including a pasted URL.

## `minArea` (type: `integer`):

Minimum total area in square metres. Applies in Search mode and URL mode, including a pasted URL.

## `maxArea` (type: `integer`):

Maximum total area in square metres. Applies in Search mode and URL mode, including a pasted URL.

## `minRooms` (type: `integer`):

Minimum number of rooms (ambientes). Applies in Search mode and URL mode, including a pasted URL.

## `maxRooms` (type: `integer`):

Maximum number of rooms (ambientes). Applies in Search mode and URL mode, including a pasted URL.

## `minBedrooms` (type: `integer`):

Minimum number of bedrooms (dormitorios). Applies in Search mode and URL mode, including a pasted URL.

## `minBathrooms` (type: `integer`):

Minimum number of bathrooms (banos). Applies in Search mode and URL mode, including a pasted URL. Listings that do not state a bathroom count are excluded.

## `agenciesOnly` (type: `boolean`):

Keep only listings published by a real-estate agency (drops listings from private owners). Applies in Search mode and URL mode, including a pasted URL.

## `sortBy` (type: `string`):

Result ordering. Only applies when mode = search. A pasted URL carries its own order.

## `urls` (type: `array`):

Paste one or more zonaprop URLs: a search page (any type, operation, location, rooms or sort slug, temporary rent, or a '-pagina-N' page to start from), an agency page (/inmobiliarias/<name>\_<id>-inmuebles.html), or a single property page (/propiedades/clasificado/...). The agency directory (/inmobiliarias.bum) is not supported. Non-www and mobile hosts are normalised to www. Location, operation, property type and sort order above are ignored in this mode (a pasted URL carries its own); price, currency, area, room, bedroom, bathroom and agency filters above still apply to search and agency pages (not to single property pages). Results are collected starting from the page in the URL.

## `fetchDetails` (type: `boolean`):

Fetch each property page to add the full untruncated description. The search results already include a description, location, GPS, agency contact, prices and all photos, so leave this off for the fastest, cheapest run. Adds one request per property.

## `maxPages` (type: `integer`):

Optional safety stop on how many result pages to read per location/URL (about 30 listings per page). This does NOT cap the run: leave it empty (or 0) for unlimited pages and the run is bounded solely by Max listings. Set a value only if you also want a per-search page ceiling.

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

The run's single hard cap: maximum total listings across all searches. Defaults to 20. Set 0 for unlimited. This is the only default limit; Max pages is unlimited by default and defers to this.

## `proxy` (type: `object`):

An Argentina residential proxy is required: zonaprop serves results only to Argentine residential connections. The actor defaults the country to Argentina.

## `allowProxyDowngrade` (type: `boolean`):

When on, the run may fall back to a cheaper backup connection if the primary connection keeps failing, and will stay on the cheaper connection if the site serves results from it. This saves residential proxy quota. Turn off to always use the configured proxy only: a refused or failing connection is never escalated to another one. The residential cap and traffic budget below, when set, still move the run to the cheaper backup connection once reached, whatever this setting says.

## `residentialCap` (type: `integer`):

Optional ceiling on how many requests may use the residential proxy in one run. Once reached, the run switches to the cheaper backup connection. Leave empty or 0 for no cap. Use this to bound residential proxy spend.

## `trafficBudgetMb` (type: `integer`):

Optional cap on total downloaded data per run, in megabytes. Once reached, the run switches to the cheaper backup connection. Leave empty or 0 for no budget.

## `resumeFromRunId` (type: `string`):

Paste a previous run ID or dataset ID to continue a large pull without returning or charging for listings already collected there. Use this after an interrupted run. For recurring monitoring of the same search, use Incremental mode below instead.

## `incrementalMode` (type: `boolean`):

Turn this on for daily or recurring monitoring. The first run returns all matching listings as NEW. Later runs return only NEW, UPDATED and REAPPEARED listings. A listing counts as UPDATED when a real listing field changes (price, expenses, title, description, address, publisher, features, photo count and similar). Photo URLs (images, photos, mainImage, publisher logo), the antiquity counter (age, yearBuilt, condition) and the scrape timestamp (scrapedAt) never count as changes, though they are still returned. Listings that did not change are not returned and not billed unless "Emit unchanged" is on. Listings that were not scanned in a run keep their previous state.

## `stateKey` (type: `string`):

Optional. Name this monitoring campaign to keep its state stable, or to deliberately share state across differently-configured runs. Leave empty to let the actor derive a key automatically from the mode, locations/URLs, operation, property type and filters, so different searches never mix state.

## `emitUnchanged` (type: `boolean`):

Off by default. Turn on to also return listings that have not changed since the last run, marked UNCHANGED. This returns, and bills, extra rows you already have. Detail enrichment is not run for unchanged rows.

## `emitExpired` (type: `boolean`):

Off by default. Turn on to also return listings that were in your previous scans but are no longer found, marked EXPIRED. Only emitted when the run walked every result page of every search to the end (no Max listings cap hit, no Max pages limit, no URL starting past page 1); otherwise nothing is marked expired.

## `ignoreFieldsForChanges` (type: `array`):

Output field names that should NOT make a listing count as UPDATED. Always ignored: images, photos, media, pictures, mainImage, list_first_image_url, publisherLogo, url_logo, publisher.logo (rotating photo URLs; photoCount still catches added or removed photos), age, yearBuilt, condition (antiquity counter), viewCount (per-visit counter on a property page), publishedAgo (daily "hace N días" text) and scrapedAt. Add fields such as description or labels here if changes to them are not relevant to you. Use a dotted path (for example publisher.name) for a field inside a nested object. Ignored fields are still returned in the output.

## `mcpConnectors` (type: `array`):

Optionally send the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize a connector once under Apify, Settings, Integrations, then select it here. The connector receives a condensed, human-readable summary per item (title + key fields), not the full JSON; the complete record stays in the dataset. Leave empty to skip. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com).

## `notionParentPageUrl` (type: `string`):

URL (or id) of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors.

## `maxNotifyListings` (type: `integer`):

Cap on items written to each connector per run. Does not affect the dataset.

## Actor input object example

```json
{
  "mode": "search",
  "locations": [
    "Capital Federal"
  ],
  "operationType": "sale",
  "propertyType": "all",
  "currency": "any",
  "agenciesOnly": false,
  "sortBy": "relevance",
  "urls": [
    "https://www.zonaprop.com.ar/departamentos-venta-palermo.html",
    "https://www.zonaprop.com.ar/departamentos-venta-palermo-pagina-2.html",
    "https://www.zonaprop.com.ar/inmuebles-venta-capital-federal.html",
    "https://www.zonaprop.com.ar/casas-venta-cordoba.html",
    "https://www.zonaprop.com.ar/departamentos-venta-palermo-orden-precio-ascendente.html",
    "https://www.zonaprop.com.ar/departamentos-alquiler-capital-federal-2-ambientes.html",
    "https://www.zonaprop.com.ar/departamentos-venta-palermo-2-habitaciones.html",
    "https://www.zonaprop.com.ar/departamentos-venta-palermo-mas-de-2-banos.html",
    "https://www.zonaprop.com.ar/departamentos-venta-palermo-100000-200000-dolar.html",
    "https://www.zonaprop.com.ar/departamentos-venta-palermo-menos-200000-dolar.html",
    "https://www.zonaprop.com.ar/departamentos-venta-palermo-con-pileta.html",
    "https://www.zonaprop.com.ar/departamentos-alquiler-temporal-palermo.html",
    "https://www.zonaprop.com.ar/propiedades/clasificado/veclapin-venta-duplex-2-ambientes-con-cochera-en-palermo-60051784.html",
    "https://www.zonaprop.com.ar/inmobiliarias/aguilar-bugeau-valor-inmobiliario_30351457-inmuebles.html"
  ],
  "fetchDetails": false,
  "maxListings": 20,
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "AR"
  },
  "allowProxyDowngrade": true,
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "maxNotifyListings": 50
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

# 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 = {
    "mode": "search",
    "locations": [
        "Capital Federal"
    ],
    "urls": [
        "https://www.zonaprop.com.ar/departamentos-venta-palermo.html",
        "https://www.zonaprop.com.ar/departamentos-venta-palermo-pagina-2.html",
        "https://www.zonaprop.com.ar/inmuebles-venta-capital-federal.html",
        "https://www.zonaprop.com.ar/casas-venta-cordoba.html",
        "https://www.zonaprop.com.ar/departamentos-venta-palermo-orden-precio-ascendente.html",
        "https://www.zonaprop.com.ar/departamentos-alquiler-capital-federal-2-ambientes.html",
        "https://www.zonaprop.com.ar/departamentos-venta-palermo-2-habitaciones.html",
        "https://www.zonaprop.com.ar/departamentos-venta-palermo-mas-de-2-banos.html",
        "https://www.zonaprop.com.ar/departamentos-venta-palermo-100000-200000-dolar.html",
        "https://www.zonaprop.com.ar/departamentos-venta-palermo-menos-200000-dolar.html",
        "https://www.zonaprop.com.ar/departamentos-venta-palermo-con-pileta.html",
        "https://www.zonaprop.com.ar/departamentos-alquiler-temporal-palermo.html",
        "https://www.zonaprop.com.ar/propiedades/clasificado/veclapin-venta-duplex-2-ambientes-con-cochera-en-palermo-60051784.html",
        "https://www.zonaprop.com.ar/inmobiliarias/aguilar-bugeau-valor-inmobiliario_30351457-inmuebles.html"
    ],
    "proxy": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "AR"
    },
    "incrementalMode": false,
    "emitUnchanged": false,
    "emitExpired": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/zonaprop-scraper").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 = {
    "mode": "search",
    "locations": ["Capital Federal"],
    "urls": [
        "https://www.zonaprop.com.ar/departamentos-venta-palermo.html",
        "https://www.zonaprop.com.ar/departamentos-venta-palermo-pagina-2.html",
        "https://www.zonaprop.com.ar/inmuebles-venta-capital-federal.html",
        "https://www.zonaprop.com.ar/casas-venta-cordoba.html",
        "https://www.zonaprop.com.ar/departamentos-venta-palermo-orden-precio-ascendente.html",
        "https://www.zonaprop.com.ar/departamentos-alquiler-capital-federal-2-ambientes.html",
        "https://www.zonaprop.com.ar/departamentos-venta-palermo-2-habitaciones.html",
        "https://www.zonaprop.com.ar/departamentos-venta-palermo-mas-de-2-banos.html",
        "https://www.zonaprop.com.ar/departamentos-venta-palermo-100000-200000-dolar.html",
        "https://www.zonaprop.com.ar/departamentos-venta-palermo-menos-200000-dolar.html",
        "https://www.zonaprop.com.ar/departamentos-venta-palermo-con-pileta.html",
        "https://www.zonaprop.com.ar/departamentos-alquiler-temporal-palermo.html",
        "https://www.zonaprop.com.ar/propiedades/clasificado/veclapin-venta-duplex-2-ambientes-con-cochera-en-palermo-60051784.html",
        "https://www.zonaprop.com.ar/inmobiliarias/aguilar-bugeau-valor-inmobiliario_30351457-inmuebles.html",
    ],
    "proxy": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "AR",
    },
    "incrementalMode": False,
    "emitUnchanged": False,
    "emitExpired": False,
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/zonaprop-scraper").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "mode": "search",
  "locations": [
    "Capital Federal"
  ],
  "urls": [
    "https://www.zonaprop.com.ar/departamentos-venta-palermo.html",
    "https://www.zonaprop.com.ar/departamentos-venta-palermo-pagina-2.html",
    "https://www.zonaprop.com.ar/inmuebles-venta-capital-federal.html",
    "https://www.zonaprop.com.ar/casas-venta-cordoba.html",
    "https://www.zonaprop.com.ar/departamentos-venta-palermo-orden-precio-ascendente.html",
    "https://www.zonaprop.com.ar/departamentos-alquiler-capital-federal-2-ambientes.html",
    "https://www.zonaprop.com.ar/departamentos-venta-palermo-2-habitaciones.html",
    "https://www.zonaprop.com.ar/departamentos-venta-palermo-mas-de-2-banos.html",
    "https://www.zonaprop.com.ar/departamentos-venta-palermo-100000-200000-dolar.html",
    "https://www.zonaprop.com.ar/departamentos-venta-palermo-menos-200000-dolar.html",
    "https://www.zonaprop.com.ar/departamentos-venta-palermo-con-pileta.html",
    "https://www.zonaprop.com.ar/departamentos-alquiler-temporal-palermo.html",
    "https://www.zonaprop.com.ar/propiedades/clasificado/veclapin-venta-duplex-2-ambientes-con-cochera-en-palermo-60051784.html",
    "https://www.zonaprop.com.ar/inmobiliarias/aguilar-bugeau-valor-inmobiliario_30351457-inmuebles.html"
  ],
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "AR"
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false
}' |
apify call abotapi/zonaprop-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,abotapi/zonaprop-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/eZODDboS4t5UxN0ZM/builds/l27Ab5aTDhlEGMh8x/openapi.json
