# Zonaprop + Argenprop Scraper: Argentina Real Estate (`roomy_tweet/zonaprop-argenprop-scraper`) Actor

Scrape Zonaprop and Argenprop property listings (propiedades, inmuebles) from Buenos Aires and all of Argentina in one run and one format: price, expensas, m², ambientes, price per m², agency, photos, coordinates. Big searches split automatically.

- **URL**: https://apify.com/roomy_tweet/zonaprop-argenprop-scraper.md
- **Developed by:** [roomy_tweet](https://apify.com/roomy_tweet) (community)
- **Categories:** Real estate
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.60 / 1,000 listings

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

## Argentina Real Estate Scraper: Zonaprop + Argenprop

Get Argentine real estate listings from its two biggest portals in **one run and one table**: Capital Federal (CABA), Gran Buenos Aires and any city the portals cover, such as Córdoba, Rosario or Mar del Plata. Paste a Zonaprop or Argenprop search, or just pick *venta / alquiler*, a property type and a barrio, and receive clean rows ready for a spreadsheet: price, expensas, address, barrio, m², ambientes, price per m², agency, photos, and map coordinates for Zonaprop.

#### Why this Actor

- **Two portals, one format.** Zonaprop and Argenprop rows share the same fields, so you can sort, filter and compare them together instead of running and merging two scrapers.
- **The whole search, not the first pages.** Zonaprop shows only ~270 listings per search to automated clients and Argenprop ~1,980, even when the site says it has 12,000. This Actor splits big searches into price bands until each fits. In our tests that took Argenprop *PH for sale in Capital Federal* from 1,980 to 6,853 of 6,855 listings.
- **Ready for analysis.** Numeric prices with currency, expensas, covered and total m², price per m² with the area it was computed on, and a flag when the same property shows up on both portals.
- **One price per listing.** Coordinates, price per m², splitting and the duplicate flag are included; there is no detail-page surcharge, and the start fee is the platform minimum.

#### Who uses this

- **Investors and buyers** comparing price per m² across barrios or tracking a neighbourhood.
- **Real estate agencies** watching the competition's inventory and prices on both portals.
- **Analysts and proptech teams** feeding dashboards, valuation models or market reports.

#### Quick start

1. Pick a search: paste URLs, or fill **Operation**, **Property type** and **Locations** (e.g. `palermo`).
2. Set **Maximum listings**.
3. Run, then export the dataset to Excel, CSV or JSON.

> ### En español: scraper de propiedades e inmuebles de Zonaprop y Argenprop
>
> Extraé avisos de departamentos, casas, PH y terrenos, en venta o alquiler, de **Zonaprop y Argenprop en una sola corrida y con el mismo formato**. Funciona en CABA, Gran Buenos Aires y cualquier ciudad que tengan los portales (Córdoba, Rosario, Mar del Plata…). Cada aviso trae: precio y moneda, expensas, dirección, barrio, m² cubiertos y totales, ambientes, dormitorios, baños, antigüedad, precio por m², inmobiliaria y fotos (en Zonaprop, también coordenadas).
>
> - **Búsqueda completa:** Zonaprop muestra unas 270 propiedades por búsqueda y Argenprop unas 1.980. El Actor divide las búsquedas grandes por rangos de precio (USD para venta, ARS para alquiler) para traer todo.
> - **Fácil de usar:** pegá URLs de búsqueda de cualquiera de los dos portales, o elegí operación, tipo de propiedad y barrio.
> - **Avisos repetidos:** si la misma propiedad está en los dos portales, se marca con `possibleDuplicateOf`.
> - **Se cobra por aviso entregado.** Sin costo extra por coordenadas, precio por m² ni división de búsquedas.
>
> Ideal para inversores, inmobiliarias que siguen el mercado y analistas que arman reportes o tasaciones.

### What you get

| Field | Zonaprop | Argenprop |
|---|:-:|:-:|
| `price`, `currency` (USD or ARS, as published) | ✓ | ✓ |
| `expenses` (expensas) | ✓ | ✓ |
| `address`, `neighborhood` | ✓ | ✓ |
| `city` | ✓ | — |
| `latitude`, `longitude` | ✓ | — (only on the listing page) |
| `coveredAreaM2`, `totalAreaM2` | ✓ | covered ✓, total when shown |
| `rooms`, `bedrooms`, `bathrooms`, `garages`, `ageYears` | ✓ | ✓ when shown |
| `pricePerM2` + `pricePerM2Basis` (covered or total) | ✓ | ✓ |
| `publisherName` (agency or advertiser) | ✓ | ✓ |
| `photoUrls`, `description`, `title`, `url` | ✓ | ✓ |
| `operation` (sale / rent), `propertyType` (apartment, house, ph, land…) | ✓ | ✓ |
| `possibleDuplicateOf` | the same property found on the other portal in this run | |

Coverage measured on a real run (Palermo, apartments for sale, 300 listings): price, address, neighbourhood and photos on 100% of rows from both portals; coordinates on 100% of Zonaprop rows; covered area on 96% (Zonaprop) and 93% (Argenprop); expenses on 71–75%, since many listings don't publish them.

### How to use

**Option 1 — paste search URLs.** Run a search on [zonaprop.com.ar](https://www.zonaprop.com.ar) or [argenprop.com](https://www.argenprop.com) with the filters you want, copy the URL from the browser, and paste it. You can mix both portals and add up to 50 URLs.

```json
{
  "startUrls": [
    "https://www.zonaprop.com.ar/departamentos-venta-palermo-2-ambientes.html",
    "https://www.argenprop.com/departamentos/venta/palermo/2-ambientes"
  ],
  "maxItems": 1000
}
```

**Option 2 — let the Actor build the search on both portals.** Pick operation, property type and one or more locations, written as the portals write them in their URLs (`palermo`, `belgrano`, `nunez`, `capital-federal`…).

```json
{
  "operation": "venta",
  "propertyType": "departamentos",
  "locations": ["palermo", "belgrano"],
  "maxItems": 5000
}
```

Supported: `venta` or `alquiler`; `departamentos`, `casas`, `ph`, `terrenos`. For anything else (offices, temporary rentals, extra filters), use Option 1.

**Set `maxItems`** to the number of listings you want in total. The Actor requests only the pages it needs for that number.

### Large searches and the page limit

| | Zonaprop | Argenprop |
|---|---|---|
| Listings per page | ~25–30 | 20 |
| Last page an automated client can open | 9 | 99 |
| Most listings from one search | ~270 | ~1,980 |

When a search is bigger than that and you asked for more than it can deliver, the Actor splits it by price: USD bands for sales, ARS bands for rentals. A band that is still too big is halved, and so on. Each band is a normal search on the portal, so nothing is guessed. Listings that sit exactly on a band edge can appear in two bands; the output is deduplicated by listing ID.

Results from test runs on 22 October 2026:

| Search | Listings the site advertised | Without splitting | With splitting |
|---|---:|---:|---:|
| Argenprop — PH for sale, Capital Federal | 6,855 | 1,980 | **6,853** |
| Zonaprop — apartments for sale, Palermo Soho | 1,044 | 270 | **886** |

The Zonaprop gap came from 3 pages that stayed blocked after 5 retries, from developments (see below) and from listings without a published price, which fall in no price band. The `REPORT` record lists every failed page so you can run those URLs again.

Turn splitting off with `"splitLargeSearches": false` if you only want the first pages of each search, for example to follow the newest listings.

### Output example

Values below are illustrative, not a real listing.

```json
{
  "portal": "zonaprop",
  "id": "61234567",
  "url": "https://www.zonaprop.com.ar/propiedades/clasificado/veclapin-ejemplo-61234567.html",
  "title": "Departamento 3 ambientes con balcón",
  "operation": "sale",
  "propertyType": "apartment",
  "price": 189000,
  "currency": "USD",
  "expenses": 250000,
  "expensesCurrency": "ARS",
  "address": "Calle Ejemplo 1234",
  "neighborhood": "Palermo",
  "city": "Capital Federal",
  "latitude": -34.588,
  "longitude": -58.43,
  "totalAreaM2": 78,
  "coveredAreaM2": 70,
  "rooms": 3,
  "bedrooms": 2,
  "bathrooms": 1,
  "garages": null,
  "ageYears": 15,
  "pricePerM2": 2700,
  "pricePerM2Basis": "covered",
  "publisherName": "Inmobiliaria Ejemplo",
  "photoUrls": ["https://imgar.zonapropcdn.com/avisos/…/720x532/….jpg"],
  "possibleDuplicateOf": { "portal": "argenprop", "id": "20123456", "url": "https://www.argenprop.com/…--20123456" },
  "priceBand": { "min": 150000, "max": 200000, "currency": "USD" },
  "searchUrl": "https://www.zonaprop.com.ar/departamentos-venta-palermo.html",
  "scrapedAt": "2026-10-22T21:00:00.000Z"
}
```

Export as JSON, CSV or Excel from the dataset. The **Overview** view shows the main columns side by side.

### Run report

Each run saves a `REPORT` record in its key-value store. Per search it shows the total the portal advertised, how many listings were saved, `coverageOfAdvertised`, whether the search was split and into how many bands, and any page that failed. The run's status message gives the totals at a glance.

### Pricing

You pay per listing delivered; the current price is on the **Pricing** tab. Coordinates, price per m², search splitting and the duplicate flag cost nothing extra, and there is no separate charge for detail pages or per search. The start fee is the platform minimum (US$0.00005).

Duplicates inside a run are not delivered twice, so they are not charged twice. A listing found on both portals is two listings, one per portal, and the second one is flagged with `possibleDuplicateOf`. Set Apify's maximum cost per run and the Actor stops before going over it.

### Good to know

- **Developments (emprendimientos)** on Zonaprop are skipped for now. Zonaprop's advertised total includes them, so coverage of individual properties is higher than `coverageOfAdvertised` suggests.
- **Prices are as published.** No currency conversion; sale prices are usually USD, rents usually ARS. `pricePerM2` uses the same currency as the price.
- **Argenprop coordinates and city** are only on each listing's own page, which this version doesn't open.
- **Contact details** (phone, WhatsApp, e-mail) are not extracted.
- **Duplicates across portals** are matched by street address, price and currency. The match is a hint, not a guarantee. Listings without a street number are never matched.
- Zonaprop pages are fetched through Argentine residential IPs and Argenprop pages directly; both are included in the price.

### FAQ

**Can I get every apartment in Capital Federal?** That is over 70,000 listings per portal. It works with splitting, but it takes many requests and a long run; start with one or a few neighbourhoods.

**Why did I get fewer listings than the site shows?** Check `REPORT`: a failed page, developments, or listings without a price. If `truncatedBySiteCap` is true, splitting was off or not needed for your `maxItems`.

**Does it log in or use my account?** No. It reads public search pages only.

# Actor input Schema

## `startUrls` (type: `array`):

Paste search result pages from zonaprop.com.ar or argenprop.com, with any filters you need. You can mix both portals.

## `operation` (type: `string`):

Optional: build the search for you on both portals instead of pasting URLs.

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

Used with Operation and Locations.

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

Neighbourhood or city names as the portals use them, e.g. "palermo", "belgrano", "capital-federal", "cordoba".

## `portals` (type: `array`):

Which portals the built search runs on.

## `maxItems` (type: `integer`):

Total listings across all searches. Only the pages needed for this are requested.

## `splitLargeSearches` (type: `boolean`):

Zonaprop shows only ~270 listings and Argenprop ~1,980 per search. When you ask for more, the search is split into price bands (USD for sale, ARS for rent) until each band fits. Listings without a published price are in no band.

## `maxPagesPerSearch` (type: `integer`):

Per search or price band. The sites also cap this: Zonaprop 9 pages, Argenprop 99.

## `maxConcurrency` (type: `integer`):

Pages requested at the same time.

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

A blocked or failed page is retried from a new IP address.

## `maxDurationSecs` (type: `integer`):

No new pages are started after this time.

## Actor input object example

```json
{
  "startUrls": [
    "https://www.zonaprop.com.ar/departamentos-venta-palermo.html",
    "https://www.argenprop.com/departamentos/venta/palermo"
  ],
  "portals": [
    "zonaprop",
    "argenprop"
  ],
  "maxItems": 200,
  "splitLargeSearches": true,
  "maxPagesPerSearch": 99,
  "maxConcurrency": 3,
  "maxRetries": 4,
  "maxDurationSecs": 1200
}
```

# Actor output Schema

## `listings` (type: `string`):

Property prices, addresses, areas, agencies, photos and other published listing data.

## `report` (type: `string`):

Listing counts, search coverage, price splitting, failed pages and the reason the run stopped.

# 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 = {
    "startUrls": [
        "https://www.zonaprop.com.ar/departamentos-venta-palermo.html",
        "https://www.argenprop.com/departamentos/venta/palermo"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("roomy_tweet/zonaprop-argenprop-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 = { "startUrls": [
        "https://www.zonaprop.com.ar/departamentos-venta-palermo.html",
        "https://www.argenprop.com/departamentos/venta/palermo",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("roomy_tweet/zonaprop-argenprop-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 '{
  "startUrls": [
    "https://www.zonaprop.com.ar/departamentos-venta-palermo.html",
    "https://www.argenprop.com/departamentos/venta/palermo"
  ]
}' |
apify call roomy_tweet/zonaprop-argenprop-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,roomy_tweet/zonaprop-argenprop-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/jYqMQf08Ob21M03wq/builds/VbFGqO3umo0K4B8ob/openapi.json
