# Zonaprop Scraper — Avisos Inmobiliarios de Argentina (`juanoox/zonaprop-ar`) Actor

Extrae avisos inmobiliarios de Zonaprop (Argentina) con precio normalizado, superficie, ambientes, ubicacion y datos de contacto. Filtra por barrio, operacion y rango de precio.

- **URL**: https://apify.com/juanoox/zonaprop-ar.md
- **Developed by:** [Juan ignacio Veltri](https://apify.com/juanoox) (community)
- **Categories:** Real estate, Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.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.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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

## Zonaprop Scraper — Avisos Inmobiliarios de Argentina

Extrae avisos inmobiliarios de Zonaprop (Argentina) con precio normalizado, superficie, ambientes, ubicacion y datos de contacto. Filtra por barrio, operacion y rango de precio.

Devuelve datos limpios y estructurados, sin captchas, sin sesiones y sin mantener proxies.

**En cada aviso:** precio con moneda ya normalizada, expensas, superficie en m², ambientes, dormitorios, baños, cocheras, barrio y foto de portada.

**Activando "Entrar a cada aviso":** además el contacto de la inmobiliaria (nombre, teléfono y perfil), la dirección exacta y todas las fotos. Cuesta un request extra por aviso y tiene un recargo por resultado.

***

### Qué hace

- **Busca por filtros o por URL.** Filtrás en el sitio, pegás la URL y el Actor devuelve exactamente ese resultado. O cargás ubicación, operación y rango de precio y arma la búsqueda solo.
- **Precios normalizados de verdad.** `USD 185.000`, `R$ 1.250.000` y `$ 89.500` salen como número + código de moneda ISO. Los avisos "a consultar" se marcan con `onRequest: true` en vez de inventar un `0`.
- **Formato unificado.** Todos los Actors de esta familia devuelven el mismo schema, así que podés cruzar varios portales y países sin escribir un mapeo por cada uno.
- **Sin resultados basura.** Un aviso sin título ni precio no se guarda ni se cobra.
- **Modo monitoreo.** Con "Incluir avisos ya vistos" apagado, cada run devuelve sólo lo que se publicó desde el anterior.
- **Deduplicado.** El mismo aviso, aunque aparezca en varias páginas o con parámetros de tracking distintos, sale una sola vez.

### Ejemplo de salida

```json
{
  "id": "zonaprop_a1b2c3d4e5f6a7b8",
  "url": "https://www.zonaprop.com.ar/propiedades/clasificado/ejemplo-123456.html",
  "source": "zonaprop",
  "country": "AR",
  "scrapedAt": "2026-08-19T14:32:10.512Z",
  "title": "Departamento 2 ambientes con balcón",
  "operation": "sale",
  "propertyType": "apartment",
  "price": { "amount": 185000, "currency": "USD", "raw": "USD 185.000", "onRequest": false },
  "totalAreaM2": 59,
  "rooms": 2,
  "bedrooms": 1,
  "bathrooms": 1,
  "parkingSpaces": 1,
  "images": ["https://..."],
  "location": { "neighborhood": "Palermo", "city": "Capital Federal", "country": "AR", "latitude": null, "longitude": null },
  "contact": { "agencyName": null, "phones": [], "emails": [], "isAgency": null },
  "listingId": "59105482"
}
```

### Cómo se usa

#### 1. Por URL de listado (más preciso)

Filtrá en Zonaprop Scraper — Avisos Inmobiliarios de Argentina como lo harías a mano, copiá la URL de resultados y pegala en **URLs de listado**.

```json
{
  "startUrls": [{ "url": "https://www.zonaprop.com.ar/departamentos-venta-palermo.html" }],
  "maxItems": 500
}
```

#### 2. Por filtros

```json
{
  "locations": ["Palermo", "Belgrano"],
  "operation": "sale",
  "priceMin": 100000,
  "priceMax": 300000,
  "sortBy": "newest",
  "maxItems": 1000
}
```

#### 3. Monitoreo diario de avisos nuevos

Programalo con un Schedule y activá `includeSeen: false`: cada run devuelve sólo lo que apareció desde el anterior.

```json
{
  "startUrls": [{ "url": "https://www.zonaprop.com.ar/departamentos-venta-palermo.html" }],
  "sortBy": "newest",
  "includeSeen": false,
  "maxPagesPerUrl": 3
}
```

### Parámetros

| Campo | Tipo | Default | Para qué sirve |
|---|---|---|---|
| `startUrls` | array | — | URLs de listado ya filtradas. Si las cargás, se ignoran los filtros. |
| `searchQuery` | string | — | Texto libre de búsqueda. |
| `locations` | array | `[]` | Barrio, ciudad o provincia. Genera una búsqueda por cada una. |
| `operation` | enum | `any` | `sale`, `rent`, `temporary_rent`, `any`. |
| `propertyTypes` | array | `[]` | Vacío = todos los tipos. |
| `priceMin` / `priceMax` | integer | — | En la moneda del portal. |
| `sortBy` | enum | `relevance` | `newest` es el mejor para monitoreo. |
| `maxItems` | integer | `200` | Corta el run al llegar. `0` = sin tope. **Es tu control de gasto.** |
| `maxPagesPerUrl` | integer | `20` | Páginas de listado por URL de arranque. |
| `scrapeDetails` | boolean | `false` | Entra a cada aviso: más datos, un request por aviso. |
| `includeSeen` | boolean | `true` | `false` devuelve sólo avisos nuevos respecto de runs anteriores. |
| `proxyTier` | enum | `datacenter` | Nivel inicial de proxy. |
| `maxProxyTier` | enum | `residential` | Poné `datacenter` para nunca gastar ancho de banda residencial. |
| `maxConcurrency` | integer | `10` | Bajalo si ves bloqueos. |
| `maxRequestRetries` | integer | `3` | Reintentos por request. |

### Costo

El Actor cobra **por resultado guardado**. Los resultados descartados por incompletos o duplicados **no se cobran**.

Para acotar el gasto de un run:

- `maxItems` es el tope duro: al llegar, el run corta.
- `maxProxyTier: "datacenter"` garantiza que nunca se consuma proxy residencial (lo más caro de un scraper).
- El Actor arranca con proxy datacenter y sólo escala a residencial si detecta bloqueos reales.

### Integraciones

- **API / SDK** — corré el Actor y traé el dataset desde JavaScript, Python o HTTP.
- **MCP** — usable como herramienta desde un agente de IA vía el MCP server de Apify.
- **Google Sheets, Slack, webhooks** — con las integraciones nativas de Apify.
- **Schedules** — para monitoreo periódico sin escribir código.

### Preguntas frecuentes

**¿Es legal?** Se extraen únicamente datos públicos, visibles sin iniciar sesión. No se accede a áreas privadas ni se evaden muros de autenticación. Si vas a tratar datos personales (teléfonos, emails), la responsabilidad de cumplir la normativa aplicable de protección de datos es de quien los usa.

**¿Por qué algunos avisos vienen sin precio?** Porque el portal los publica como "a consultar". Salen con `price.onRequest: true` y `price.amount: null`, para no ensuciar tus promedios con ceros falsos.

**¿Por qué me devolvió menos avisos de los que dice el portal?** Casi siempre es `maxItems` o `maxPagesPerUrl`. Subilos. Si persiste, revisá el `RUN_SUMMARY` del key-value store: ahí figura cuántos se descartaron y por qué.

**¿Anda con proxy propio?** Sí, configurable desde los parámetros de red.

### Soporte

Si un campo deja de venir o cambia el sitio, abrí un issue en la pestaña Issues del Actor con la URL que falló. Los reportes con URL se arreglan mucho más rápido.

# Actor input Schema

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

Pegá URLs de resultados ya filtradas en Zonaprop Scraper — Avisos Inmobiliarios de Argentina. Si cargás esto, se ignoran los filtros de abajo. Es la opción más precisa: filtrás en el sitio y el Actor copia exactamente ese resultado. Viene precargada una búsqueda de ejemplo: reemplazala por la tuya.

## `searchQuery` (type: `string`):

Texto libre, ej. "monoambiente con balcón". Se combina con el resto de los filtros.

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

Barrio, ciudad o provincia. Se genera una búsqueda por cada una.

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

Tipo de operación a buscar.

## `propertyTypes` (type: `array`):

Dejalo vacío para incluir todos.

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

En la moneda que muestra el portal. Vacío = sin mínimo.

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

En la moneda que muestra el portal. Vacío = sin máximo.

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

Moneda en la que se interpretan el precio mínimo y máximo. Zonaprop publica ventas en dólares y alquileres en pesos.

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

Filtra por cantidad mínima de ambientes. Vacío = sin filtro.

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

Ordenar por "Más nuevos" es lo mejor para monitoreo diario: los avisos nuevos quedan primero.

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

Corta el run al llegar a este número. 0 = sin tope. Es el control directo de cuánto gastás.

## `maxPagesPerUrl` (type: `integer`):

Cuántas páginas de listado seguir por cada URL de arranque.

## `scrapeDetails` (type: `boolean`):

Visita la página de cada aviso para traer el contacto de la inmobiliaria (nombre, teléfono y perfil), la dirección exacta y todas las fotos. Cuesta un request extra por aviso y se cobra un recargo por resultado.

## `includeSeen` (type: `boolean`):

Desactivalo para monitoreo: el Actor recuerda los avisos de runs anteriores y sólo devuelve los nuevos. Requiere reusar el mismo almacenamiento entre runs (usá un Schedule).

## `proxyTier` (type: `string`):

Arrancá en datacenter. El Actor escala solo a residencial si detecta bloqueos, así no pagás ancho de banda residencial de más.

## `maxProxyTier` (type: `string`):

Poné "Datacenter" para garantizar que el run nunca consuma ancho de banda residencial.

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

Requests en paralelo. Bajalo si el portal te bloquea.

## `maxRequestRetries` (type: `integer`):

Cuántas veces reintentar una petición fallida antes de darla por perdida. Subilo si el portal es inestable.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.zonaprop.com.ar/departamentos-venta-capital-federal.html"
    }
  ],
  "locations": [],
  "operation": "any",
  "propertyTypes": [],
  "priceCurrency": "usd",
  "sortBy": "relevance",
  "maxItems": 100,
  "maxPagesPerUrl": 20,
  "scrapeDetails": false,
  "includeSeen": true,
  "proxyTier": "datacenter",
  "maxProxyTier": "residential",
  "maxConcurrency": 10,
  "maxRequestRetries": 3
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `runSummary` (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 = {
    "startUrls": [
        {
            "url": "https://www.zonaprop.com.ar/departamentos-venta-capital-federal.html"
        }
    ],
    "locations": [],
    "propertyTypes": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("juanoox/zonaprop-ar").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": [{ "url": "https://www.zonaprop.com.ar/departamentos-venta-capital-federal.html" }],
    "locations": [],
    "propertyTypes": [],
}

# Run the Actor and wait for it to finish
run = client.actor("juanoox/zonaprop-ar").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": [
    {
      "url": "https://www.zonaprop.com.ar/departamentos-venta-capital-federal.html"
    }
  ],
  "locations": [],
  "propertyTypes": []
}' |
apify call juanoox/zonaprop-ar --silent --output-dataset

```

## MCP server setup

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

```

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/YqAuUkUcuiZ684a5r/builds/Kui8mAZEDl1CHcdsp/openapi.json
