# Inmuebles24 Scraper — Mexico Property Listings (+ZonaProp) (`tortuga/inmuebles24-scraper`) Actor

Scrape Inmuebles24, ZonaProp, Imovelweb, Urbania and Plusvalía listings for sale or rent: price, fees, area, rooms, address, coordinates, photos, agency.

- **URL**: https://apify.com/tortuga/inmuebles24-scraper.md
- **Developed by:** [Trevor Ortega](https://apify.com/tortuga) (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.80 / 1,000 listing scrapeds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## Inmuebles24 Scraper — Mexico Property Listings (+ZonaProp)

Scrape property listings from **Inmuebles24**, Mexico's largest real estate portal, for sale (venta) or for rent (renta). The same actor also works on the sister portals that run on the same platform: **ZonaProp** (Argentina), **Imovelweb** (Brazil), **Urbania** (Peru) and **Plusvalía** (Ecuador). For each listing you get the price and currency (MXN, USD, ARS, BRL or PEN), the maintenance fee (mantenimiento / expensas / condomínio), the total and covered area, rooms, bedrooms, bathrooms, half bathrooms, parking spaces and age. You also get the property type, the address as the advertiser publishes it, neighbourhood, city, state and coordinates. On top of that come the features, the full description, photos, the advertiser (agency name, logo and profile, or "private owner"), the premium / featured flag and the dates.

Start from any search URL copied from one of the five sites, or type a city or neighbourhood (colonia) and pick filters. Turn on **Include listing page details** to also get every photo, the grouped amenities, video links, the publication age ("Publicado hace 12 días" turned into a date) and the view count.

The actor reads the same JSON the websites load (30 listings per request), not the visible HTML. That keeps the output complete and stable and runs fast: 1,136 listings in 34 seconds in our test. You pay only for the listings you get.

### What data does Inmuebles24 Scraper extract?

| Field | Description |
|---|---|
| `id`, `code`, `url`, `site` | Listing id, the advertiser's posting code, listing URL, and `Inmuebles24`, `ZonaProp`, `Imovelweb`, `Urbania` or `Plusvalía` |
| `title`, `headline` | The advertiser's title and the site's summary line (`"Departamento · 240m² · 3 Recámaras · 2 Estacionamientos"`) |
| `operation`, `price`, `currency` | `sale`, `rent`, `temporary rent` or `transfer`; price and ISO currency (`MXN`, `USD`, `ARS`, `BRL`, `PEN`). `priceOnRequest` is `true` when the price is hidden |
| `prices` | Every price of the listing (some are offered for sale and for rent, or in two currencies) |
| `maintenanceFee`, `maintenanceFeeCurrency` | Monthly maintenance / expensas / condomínio, when given |
| `propertyType`, `postingType` | e.g. `Departamentos`, `Casas`, `Terrenos`; `property`, or `development` for new projects |
| `totalArea`, `coveredArea`, `areaUnit` | Total (terreno) and covered / built (construida) area, usually m² |
| `rooms`, `bedrooms`, `bathrooms`, `halfBathrooms`, `suites`, `parkingSpaces`, `ageYears` | Ambientes (ZonaProp), recámaras / dormitorios / quartos, baños, medios baños, suítes (Imovelweb), estacionamientos / cocheras / vagas, antigüedad |
| `otherFeatures`, `features`, `developmentInfo` | Extra main features (e.g. orientation), highlighted amenities (`"Alberca"`, `"Gimnasio"`), and delivery date / units / stage for developments |
| `address`, `neighborhood`, `subNeighborhood`, `city`, `state`, `country` | Address as published (see the privacy FAQ); colonia / barrio / bairro, municipality, state |
| `latitude`, `longitude` | Map point when the listing shows one |
| `description` | The full listing description |
| `photos` | Photo URLs (up to 8 from search results; all of them with details) |
| `hasVideo`, `hasVirtualTour`, `hasFloorPlans` | Media flags |
| `publisherName`, `publisherType`, `publisherId`, `publisherUrl`, `publisherLogo`, `isPrivateOwner` | Agency, developer, broker or private owner (`real estate agency`, `developer`, `broker`, `private owner`), profile page and logo |
| `premium`, `listingPlan` | Paid highlight flag and the plan (`simple`, `featured`, `super featured`, `free`, `exclusive`) |
| `reserved`, `status` | Reserved flag and listing status |
| `modifiedDate`, `firstOnlineDate` | Last modification date; first online date (developments) |
| `search`, `scrapedAt`, `detailsFetched` | The search the listing came from, the run time, and whether the listing page was opened |

With **Include listing page details** you also get:

| Field | Description |
|---|---|
| `photos` | All photos in 1200 px |
| `amenities` | Amenities grouped as on the page, e.g. `{"Servicios": ["Seguridad privada"], "Amenidades": ["Estudio", "Bodega(s): 1"]}` |
| `videoUrls` | YouTube links of the listing videos |
| `publishedAgo`, `publishedDaysAgo`, `publishedDate` | `"Publicado hace 40 días"`, `40`, and the date computed from it |
| `views` | View count the page shows (Inmuebles24, Imovelweb) |
| `description` | Description with its line breaks |

### How to scrape Inmuebles24 listings

1. Open [inmuebles24.com](https://www.inmuebles24.com/) (or zonaprop.com.ar, imovelweb.com.br, urbania.pe, plusvalia.com), search for a city or colonia, set any filters (type, price, recámaras, baños, superficie, amenities, sort, ...) and copy the address from your browser. Or skip this step and type the place in **Locations** and pick the filters in the input.
2. Paste the URL into **Start URLs**. You can add several searches, from different sites too, and single listing URLs.
3. Set **Max listings** and start the run. Download the results as JSON, CSV or Excel, or read them through the API.

The Locations search covers the filters most people use: sale or rent, property type, price (local currency or USD), bedrooms, bathrooms, advertiser type (agencies or private owners / dueño directo) and publication date. Any other filter on the websites works through a search URL.

### Input example

```json
{
  "site": "inmuebles24",
  "locations": ["Polanco", "Condesa", "Guadalajara"],
  "operation": "rent",
  "propertyType": "apartment",
  "maxPrice": 40000,
  "minBedrooms": 2,
  "sort": "newest",
  "maxItems": 500
}
```

Or with URLs from several sites:

```json
{
  "startUrls": [
    { "url": "https://www.inmuebles24.com/casas-en-venta-en-monterrey.html" },
    { "url": "https://www.zonaprop.com.ar/departamentos-venta-capital-federal.html" },
    { "url": "https://www.inmuebles24.com/propiedades/clasificado/veclapin-departamento-en-venta-en-solon-polanco-ii-seccion-150472613.html" }
  ],
  "includeDetails": true,
  "maxItems": 1000
}
```

Locations accept a state (`Jalisco`), a city or municipality (`Guadalajara`, `Miguel Hidalgo`), a colonia (`Polanco`) or a colonia with its city (`Polanco, Guadalajara`). The actor looks each one up with the site's own autocomplete. The SUMMARY record in the key-value store shows which place was used.

### Output example

```json
{
  "id": "150950146",
  "code": "66AMBG",
  "url": "https://www.inmuebles24.com/propiedades/clasificado/veclcain-casa-nueva-en-venta-jardines-de-valle-alto-150950146.html",
  "site": "Inmuebles24",
  "title": "Casa Nueva en Venta Jardines de Valle Alto",
  "headline": "Casa · 593m² · 4 Recámaras · 3 Estacionamientos",
  "operation": "sale",
  "price": 17800000,
  "currency": "MXN",
  "priceOnRequest": false,
  "prices": [{ "operation": "sale", "price": 17800000, "currency": "MXN" }],
  "maintenanceFee": null,
  "propertyType": "Casas",
  "postingType": "property",
  "totalArea": 422,
  "coveredArea": 593,
  "areaUnit": "m²",
  "bedrooms": 4,
  "bathrooms": 4,
  "halfBathrooms": 1,
  "parkingSpaces": 3,
  "address": "Jardines de Valle Alto",
  "city": "Monterrey",
  "state": "Nuevo León",
  "country": "Mexico",
  "latitude": 25.5755224,
  "longitude": -100.2853143,
  "description": "Diseño, amplitud y espacios pensados para disfrutar cada nivel de tu nuevo hogar.\n\nUbicada en Jardines de Valle Alto, ...",
  "photos": ["https://img10.naventcdn.com/avisos/18/01/50/95/01/46/1200x1200/1628752510.jpg"],
  "publisherName": "Montenbruck Real Estate",
  "publisherType": "real estate agency",
  "publisherUrl": "https://www.inmuebles24.com/inmobiliarias/montenbruck-real-estate_103035327-inmuebles.html",
  "publisherLogo": "https://img10.naventcdn.com/empresas/18/01/03/03/53/27/130x70/logo_montenbruck-real-estate_1772750982413.jpg",
  "isPrivateOwner": false,
  "premium": true,
  "listingPlan": "super featured",
  "reserved": false,
  "modifiedDate": "2026-08-31",
  "amenities": { "Características generales": ["Cuartos de servicio", "Cocina integral"] },
  "publishedAgo": "Publicado hace 40 días",
  "publishedDaysAgo": 40,
  "publishedDate": "2026-08-31",
  "views": 299,
  "detailsFetched": true,
  "search": "https://www.inmuebles24.com/casas-en-venta-en-monterrey.html",
  "scrapedAt": "2026-10-10T06:47:04Z"
}
```

(Shortened: real items carry every field from the tables above. Detail fields are absent when **Include listing page details** is off.)

### Does it work for ZonaProp, Imovelweb, Urbania and Plusvalía?

Yes. The five portals run the same listing software, so the same fields come out of all of them, in the local language: ZonaProp gives `rooms` (ambientes) and expensas in ARS, Imovelweb gives `suites` and prices in BRL, Urbania prices in PEN or USD, Plusvalía in USD. Paste search URLs from any of them (several sites in one run is fine), or pick the site in **Site for location searches**. Each site only answers visitors from its own country, so the actor routes every site through residential IPs in Mexico, Argentina, Brazil, Peru or Ecuador automatically.

### How many listings can I get per search?

Up to **30,000 listings per search**: the sites serve 1,000 pages of 30, and deeper pages repeat page 1, which the actor detects. That is enough for most cities (CDMX apartments for sale: 18,500; Polanco rentals: 1,136). For bigger searches (all of São Paulo has over a million listings) split by colonia, property type or price range. When a run asks for the whole search (**Max listings** at least the number of results), it is read cheapest-first. The sites' relevance and newest orders reshuffle listings with equal keys between pages: a 1,000-listing relevance run met 197 repeats and so missed about 20 % of that slice, while price order gave all 1,136 Polanco rentals with no repeat. Repeats are always skipped and never charged.

### Does it work without login? Does it collect phone numbers or addresses?

No login and no account are needed: the actor reads only what anyone sees on the websites. It does **not** export phone or WhatsApp numbers, which the sites show only after a click (they are dropped even where the page source carries them). Addresses are exported only as far as the advertiser publishes them. For private owners (`publisherType` = `private owner`, "dueño directo"), the actor never exports the street and rounds the coordinates to about 1 km. Agencies' and developers' names, logos and profile pages are business data and are included.

### Do I need a proxy?

Yes, and the default works: Apify **Residential** proxy. Cloudflare in front of all five sites refuses datacenter IPs and anything from outside the site's country. The actor therefore pins residential IPs to Mexico, Argentina, Brazil, Peru or Ecuador per site; you only keep the RESIDENTIAL group selected. In our tests every search and API request succeeded: about 9 in 10 on the first try, the rest on an automatic retry from a fresh IP. Listing pages (details) on Imovelweb and Urbania are refused more often in some hours; the actor retries them on fresh IPs, so detail runs there are slower. Residential traffic is billed by Apify per GB, and the actor uses little: about 30 KB per 30 listings, about 150 KB per start URL (the search page is opened once to read its filters), and about 100 KB per listing page with details.

### Monitor changes on a schedule

Turn on **Only new or changed items** to watch a search. Each run remembers what earlier runs returned and outputs only new listings and listings whose price, currency, maintenance fee or reserved flag changed. Unchanged listings are dropped before any listing page is opened, so they are not charged. **Max listings** then sets how many of the newest listings are checked per run, e.g. 100-300 for a colonia. Start URLs are read newest-first in this mode. Save the input as a task in Apify and add a Schedule (for example daily). Give each watch its own **Monitoring key** if several schedules use the same search. Every output item gets `changeType` (`new` or `changed`), and changed items get `previousValues` with the old values, e.g. `{"price": 25000}`. Sold or removed listings simply stop appearing.

### Pricing

Pay per result: you are charged for each listing saved to the dataset. With **Include listing page details** on (and for single listing URLs), each listing page opened adds a small extra charge. See the Pricing tab for the current prices. There is no start fee. Platform usage is small: at the default 512 MB memory our test runs used about $0.02 per 1,000 listings without details (residential traffic, compute and dataset writes) and about $0.90 per 1,000 with details (one ~100 KB listing page each, almost all of it residential traffic).

### Integrations and API

Run it from the Apify API or a schedule, and send the results to Google Sheets, Slack, Make, Zapier, n8n or a webhook. Use `maxItems` to cap the cost of each run. Typical uses are price per m² studies by colonia, rent vs. sale yield analysis, agency inventory tracking, new-listing alerts, private-owner (dueño directo) lead lists and market reports across Mexico, Argentina, Brazil, Peru and Ecuador.

### Is it legal to scrape Inmuebles24?

This actor collects publicly visible listing data that anyone can see on the websites without logging in. It does not log in, it does not collect phone numbers or anything else behind a click, and it does not export private owners' street addresses. Names of private owners and individual brokers are personal data under Mexico's LFPDPPP, Argentina's Ley 25.326, Brazil's LGPD and similar laws. You are responsible for having a legitimate purpose and a legal basis for processing them, and for respecting the portals' terms of use. If in doubt, ask a lawyer.

### Support

Found a bug or need a field that is not there? Open an issue on the Issues tab with the input you used and the run link.

# Actor input Schema

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

Search URLs from Inmuebles24, ZonaProp, Imovelweb, Urbania or Plusvalía with any filters set in the browser (open the search on the site and copy the address bar, e.g. https://www.inmuebles24.com/departamentos-en-renta-en-polanco.html), or single listing URLs (.../propiedades/...-150472613.html), which return that listing with full details. Leave empty if you use Locations below.

## `site` (type: `string`):

Which portal the Locations searches run on. With no Start URLs and no Locations, the whole country of this site is searched with the filters below.

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

States, cities, neighbourhoods (colonias / barrios / bairros), one per line, e.g. 'Polanco', 'Guadalajara', 'Polanco, Guadalajara', 'Palermo', 'Miraflores'. Each is looked up with the site's own location autocomplete and searched separately.

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

Listings for sale (venta), for rent (renta / alquiler / aluguel) or temporary / vacation rent. Applies to Locations searches.

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

Only this property type (Locations searches). For other sub-types (PH, dúplex, bodega, ...) set the filter on the site and use the URL as a Start URL.

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

Minimum sale price, or minimum monthly rent for rentals, in the currency chosen below (Locations searches).

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

Maximum sale price, or maximum monthly rent for rentals, in the currency chosen below (Locations searches).

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

Currency of Min / Max price: the site's local currency (MXN on Inmuebles24, ARS on ZonaProp, BRL on Imovelweb, PEN on Urbania, USD on Plusvalía) or US dollars (not on Imovelweb).

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

At least this many bedrooms (recámaras / dormitorios / quartos).

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

At least this many bathrooms.

## `publisherType` (type: `string`):

All listings, only agencies, or only private owners (dueño directo / trato directo).

## `postedWithin` (type: `string`):

Only listings published recently (the site's own 'Fecha de publicación' filter).

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

Order of Locations searches (Start URLs keep the order chosen on the site). 'Newest' is best for monitoring. When a run asks for a whole search (Max listings at least the number of results), it is paged cheapest-first instead: the site's relevance and newest orders reshuffle listings between pages.

## `includeDetails` (type: `boolean`):

Open each listing page for all photos (search results show up to 8), grouped amenities, video links, publication age ('Publicado hace 12 días' -> publishedDate) and view count. One extra request and one extra 'detail' event per listing; slower.

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

Stop after this many listings in total (all searches together). You pay per listing. One search returns at most 30,000 listings (the sites' own limit). With monitoring on, this is the number of newest listings checked each run.

## `onlyNewOrChanged` (type: `boolean`):

Remember what earlier runs of this search returned and output only new items or items whose price/status changed. Use with a Schedule; unchanged items are not charged.

## `monitoringKey` (type: `string`):

Name for this watch, so several schedules on the same search stay separate; defaults to a key derived from the search input.

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

The sites only answer residential IPs from their own country; the actor sets the country per site automatically (MX, AR, BR, PE, EC). Keep the RESIDENTIAL group: datacenter IPs are blocked. Residential traffic is about 30 KB per 30 listings (~$0.01 per 1,000 listings) plus ~150 KB per start URL and ~100 KB per listing page with details.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.inmuebles24.com/departamentos-en-renta-en-polanco.html"
    }
  ],
  "site": "inmuebles24",
  "locations": [],
  "operation": "sale",
  "propertyType": "any",
  "priceCurrency": "local",
  "publisherType": "any",
  "postedWithin": "any",
  "sort": "newest",
  "includeDetails": false,
  "maxItems": 100,
  "onlyNewOrChanged": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `results` (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.inmuebles24.com/departamentos-en-renta-en-polanco.html"
        }
    ],
    "locations": [],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("tortuga/inmuebles24-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": [{ "url": "https://www.inmuebles24.com/departamentos-en-renta-en-polanco.html" }],
    "locations": [],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("tortuga/inmuebles24-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": [
    {
      "url": "https://www.inmuebles24.com/departamentos-en-renta-en-polanco.html"
    }
  ],
  "locations": [],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call tortuga/inmuebles24-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,tortuga/inmuebles24-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/hFpg5htlKV1ayVAmk/builds/gh3qVOkXs9K3cxkHW/openapi.json
