# Vivanuncios Scraper — Mexico Property Listings (`reventadata/vivanuncios-scraper`) Actor

Scrape Vivanuncios (vivanuncios.com.mx) property listings for sale or rent by type and state, or from any listing page: price in MXN or USD, beds, baths, parking, areas, zone, coordinates, description and advertiser. Up to 150 listings per search.

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

## Pricing

from $2.50 / 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/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

## Vivanuncios Scraper: Mexico Property Listings

> **Unofficial.** This Actor is not affiliated with, authorised by, endorsed by, or in any way
> officially connected to Vivanuncios or its operator. "Vivanuncios" is a trademark of its respective
> owner and is used here only to describe what this tool reads. It reads the same public listing pages a
> browser does.

Get Mexican property listings from Vivanuncios (vivanuncios.com.mx) as clean rows: price in pesos or
dollars, bedrooms, bathrooms, parking, built and lot area, zone, municipality, state, coordinates, the full
description, the advertiser and the listing's contact numbers.

### What does it do?

It walks the public search result pages for the property types, operation (sale or rent) and states you
choose, or for any Vivanuncios listing page you paste, and saves one row per listing. Only listing data the
site shows to anyone is read: nothing from behind a login.

### Why use it?

- **Numbers, not text.** `price` and `currency` (MXN or USD), `bedrooms`, `bathrooms`, `halfBathrooms`,
  `parkingSpaces`, `builtAreaM2`, `landAreaM2`, `ageYears` and `maintenanceFee` are integers.
- **Where it is.** Zone (`neighborhood`), municipality (`city`), `state`, street and latitude / longitude
  when the advertiser gives them.
- **Who to call.** Advertiser name, type code and page, the advertiser phone when the site shows a real
  one, and the listing's WhatsApp number.
- **All property types.** Houses, apartments, land, commercial premises, offices, vacation houses (rent),
  or every type at once; new-build projects come as rows with `listingKind` `development`.
- **Filters that run before you pay.** Price band, minimum bedrooms, bathrooms, parking, built and lot area,
  words the listing must or must not contain. Rows they drop are not charged.

### How to use it

1. Pick **Operation** (sale or rent), **Property types** and, if you want, **States**. Or paste listing pages
   into **Start URLs** (one city or neighbourhood each) instead.
2. Set **Maximum items** and any filters.
3. Run the Actor and download the dataset as JSON, CSV or Excel.

#### How many listings one search gives

Vivanuncios' own robots.txt allows result pages 1 to 5 only, 30 listings each. The Actor stays inside that:
**one search returns at most 150 listings**, whatever the site says it holds. For more, search by state (32
states), or paste narrower Start URLs, one per city or neighbourhood. The site's own filters travel in
addresses robots.txt disallows (`?pr=`, `?fe=`, `?q=`), so every filter here runs on the rows after they are read.

#### Input

| Field | Type | Description |
|---|---|---|
| `operation` | string | `sale` (default) or `rent`. |
| `propertyTypes` | array | `houses` (default), `apartments`, `land` (sale only), `commercial`, `offices`, `vacation` (rent only), `all`. One search per type. |
| `states` | array | Any of the 32 states, for example `distrito-federal` (Mexico City), `jalisco`, `nuevo-leon`, `yucatan`. Empty: the whole country. One search per state and type. |
| `startUrls` | array | Vivanuncios listing pages, for example `https://www.vivanuncios.com.mx/s-casas-en-venta/guadalajara/v1c1293l14822p1`. Replaces the three fields above. Addresses with a query string, or under the paths robots.txt disallows, are refused. |
| `maxItems` | integer | Total listings to save across all searches, counted after the filters. Default 100. |
| `maxPages` | integer | Result pages per search, 1 to 5 (default 5). |
| `priceCurrency` | string | `MXN` (default) or `USD`: the currency the price limits are read in. Listings in the other currency are dropped when a limit is set. |
| `minPrice`, `maxPrice` | number | Price band. |
| `minBedrooms`, `minBathrooms`, `minParkingSpaces` | integer | Listings that state fewer, or none, are dropped (land, commercial and developments state none). |
| `minBuiltAreaM2`, `minLandAreaM2` | integer | Same rule for areas. |
| `includeKeywords`, `excludeKeywords` | array | `includeKeywords`: keep listings whose title, description or location contains at least one of these words; `excludeKeywords`: drop listings containing any of them. Case and accents ignored. |
| `proxyConfiguration` | object | Apify Unblocker (default). Vivanuncios sits behind Cloudflare, which refused plain and datacenter connections, and 24 of 25 residential ones, when this Actor was built. |

#### Sample input

```json
{
    "operation": "sale",
    "propertyTypes": ["houses"],
    "states": ["distrito-federal"],
    "minBedrooms": 3,
    "maxPrice": 25000000,
    "maxItems": 100
}
```

#### Output

One row per listing:

| Field | Type | Description |
|---|---|---|
| `id`, `url` | string | Vivanuncios posting id and page URL. |
| `title`, `generatedTitle` | string / null | The advertiser's title and the site's summary title. |
| `listingKind` | string | `property`, or `development` for a new-build project. |
| `operation`, `propertyType` | string / null | `Venta` or `Renta`; the site's type (Casas, Departamentos, Terrenos, ...). A listing offered for both sale and rent appears in both searches and carries the price of the operation you searched. |
| `price`, `currency` | number / string | Asking price (monthly rent for rentals) and its currency: `MXN` or `USD`, the only two seen. |
| `maintenanceFee` | number / null | Monthly maintenance fee as the listing states it (0 when it states none); the site gives no currency for it. |
| `landAreaM2`, `builtAreaM2`, `bedrooms`, `bathrooms`, `halfBathrooms`, `ageYears`, `parkingSpaces` | integer / null | The listing's main features; null when it states none. |
| `description` | string / null | The full description as written. |
| `neighborhood`, `city`, `state`, `street` | string / null | Zone, municipality, state and street. |
| `latitude`, `longitude` | number / null | Coordinates when given. |
| `publisherId`, `publisherName`, `publisherTypeId`, `publisherUrl` | string / null | The advertiser. `publisherTypeId` is the site's code: 2 on agencies; 3 and 4 also occur and the site does not say what they mean. |
| `publisherPhone`, `contactWhatsapp` | string / null | Advertiser phone when the site gives a real one; the contact's WhatsApp number with country code. |
| `premier` | boolean / null | Paid-highlight listing. |
| `imageCount`, `imageUrls` | integer, array | The pictures the search page carries (up to 8 per listing), from the site's `720x532` image path. |
| `hasVideo`, `hasTour360`, `hasPlans` | boolean / null | Video, 360 tour and floor plans attached. |
| `modifiedAt` | string / null | Last modification the site reports. |
| `source` | string | `state` (the page's data block) or `card`, see below. |
| `searchPath`, `searchPage` | string, integer | The search that returned the row and its result page. |
| `scrapedAt` | string | ISO 8601 timestamp. |

**Cards.** Through the proxy, a small share of pages arrives without its data block. The Actor asks again, up to
three times in all, and if every answer lacks it, reads the listing cards instead. Those `source: "card"` rows keep
id, URL, price, currency, operation, lot area, bedrooms, bathrooms, parking, maintenance fee, zone, municipality,
street and description. `listingKind`, `source`, `searchPath`, `searchPage` and `scrapedAt` are always set; every other field is null.

#### Sample output

A real row from run `IBUyjuuVjmcHJbMOc` on 2026-10-21 (`description` and `imageUrls` shortened):

```json
{
    "id": "149863929",
    "url": "https://www.vivanuncios.com.mx/a-venta-casa/bosques-de-las-lomas/casa-bosques-de-las-lomas/149863929",
    "title": "Casa - Bosques de Las Lomas",
    "generatedTitle": "Casa · 545m² · 3 Estacionamientos",
    "listingKind": "property",
    "operation": "Venta",
    "propertyType": "Casas",
    "price": 23630000,
    "currency": "MXN",
    "maintenanceFee": 0,
    "landAreaM2": 611,
    "builtAreaM2": 545,
    "bedrooms": null,
    "bathrooms": 3,
    "halfBathrooms": 1,
    "ageYears": null,
    "parkingSpaces": 3,
    "description": "Hermosa casa en Bosques de las Lomas con terreno plano y gran frente. Destaca por su excelente distribución y su conexión con el jardín, lleno de…",
    "neighborhood": "Bosques de las Lomas",
    "city": "Cuajimalpa de Morelos",
    "state": "Ciudad de México",
    "street": "Bosque de las Lomas",
    "latitude": 19.3871074,
    "longitude": -99.2520096,
    "publisherId": "327398",
    "publisherName": "JBR MÉXICO",
    "publisherTypeId": "2",
    "publisherUrl": "https://www.vivanuncios.com.mx/u-anuncios-del-vendedor/jbr-mexico/v1u327398p1",
    "publisherPhone": null,
    "contactWhatsapp": "525525081269",
    "premier": true,
    "imageCount": 8,
    "imageUrls": [
        "https://img10.naventcdn.com/avisos/18/01/49/85/56/92/720x532/1606258847.jpg?rapc=bXZhX2ltYWdl?isFirstImage=true",
        "https://img10.naventcdn.com/avisos/18/01/49/85/56/92/720x532/1606258820.jpg?rapc=bXZhX2ltYWdl"
    ],
    "hasVideo": false,
    "hasTour360": false,
    "hasPlans": false,
    "modifiedAt": "2026-10-21T14:28:06-0400",
    "source": "state",
    "searchPath": "/s-casas-en-venta/distrito-federal/v1c1293l1008p1",
    "searchPage": 1,
    "scrapedAt": "2026-10-21T19:50:25+00:00"
}
```

### How much does it cost to scrape Vivanuncios?

Pay-per-event: **$0.0025 per result** saved to the dataset (**$2.50 per 1,000 results**), plus
**$0.00005** charged once when the run starts. No subscription. The price band, minimum bedrooms,
bathrooms, parking and area filters, the keyword filters and duplicate removal run before a row is
saved, so listings they drop are not charged.

### Privacy & Compliance

This Actor reads only publicly accessible listing pages and returns the public data they show, including the
advertiser names and contact numbers the site displays. It sends no login. Check your own obligations (Mexico's
data-protection law, the site's terms, your marketing rules) before contacting advertisers.

# Actor input Schema

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

Buy or rent. Together with Property types and States it builds the Vivanuncios searches; ignored when Start URLs are given.

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

One search per type: houses, apartments, land (sale only), commercial premises, offices, vacation houses (rent only) or all property types. Ignored when Start URLs are given.

## `states` (type: `array`):

Limit each search to these Mexican states, one search per state and type. Leave empty for the whole country. For one city or neighbourhood, paste its Vivanuncios listing page into Start URLs.

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

Vivanuncios listing pages to read instead of the selectors above, for example https://www.vivanuncios.com.mx/s-casas-en-venta/guadalajara/v1c1293l14822p1. Addresses with a query string (?pr=, ?q=, ?sort= ...) are refused: the site's robots.txt disallows them, so filters run after the fetch. A page number in the address is ignored; the Actor walks pages itself.

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

Total number of listings to save across all searches. Each result page holds 30.

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

Result pages to read per search, 30 listings each. The site's robots.txt allows pages 1 to 5 only, so 5 is the ceiling: one search yields at most 150 listings. For more, add states or paste narrower Start URLs (one city or neighbourhood each).

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

Currency the minimum and maximum price are read in. Listings priced in the other currency are dropped when a price limit is set.

## `minPrice` (type: `number`):

Drop listings priced below this amount, in the Price currency. Applied after the fetch.

## `maxPrice` (type: `number`):

Drop listings priced above this amount, in the Price currency. Applied after the fetch.

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

Drop listings with fewer bedrooms, and listings that state none (land, commercial, developments). Applied after the fetch.

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

Drop listings with fewer full bathrooms than this, and listings that state none. Half bathrooms are not counted. Applied after the fetch.

## `minParkingSpaces` (type: `integer`):

Drop listings with fewer parking spaces, and listings that state none. Applied after the fetch.

## `minBuiltAreaM2` (type: `integer`):

Drop listings with less built area, and listings that state none. Pages the site occasionally serves without its data block (2 of 24 probe pages, none of 40 in the test run) carry the lot size only, so those listings are dropped by this filter.

## `minLandAreaM2` (type: `integer`):

Drop listings with a smaller lot, and listings that state none. Applied after the fetch.

## `includeKeywords` (type: `array`):

Keep a listing only when its title, description or location contains at least one of these words. Accents and capitals are ignored (alberca matches Alberca).

## `excludeKeywords` (type: `array`):

Drop a listing when its title, description or location contains any of these words. Accents and capitals are ignored.

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

Vivanuncios sits behind Cloudflare, which refused plain and datacenter connections, and 24 of 25 residential ones, when this Actor was built. The default is Apify Unblocker; change it only if you know another group passes.

## Actor input object example

```json
{
  "operation": "sale",
  "propertyTypes": [
    "houses"
  ],
  "states": [
    "distrito-federal"
  ],
  "startUrls": [],
  "maxItems": 30,
  "maxPages": 1,
  "priceCurrency": "MXN",
  "includeKeywords": [],
  "excludeKeywords": [],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "UNBLOCKER"
    ]
  }
}
```

# Actor output Schema

## `dataset` (type: `string`):

Property listings scraped from vivanuncios.com.mx.

# 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 = {
    "propertyTypes": [
        "houses"
    ],
    "states": [
        "distrito-federal"
    ],
    "maxItems": 30,
    "maxPages": 1,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "UNBLOCKER"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("reventadata/vivanuncios-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 = {
    "propertyTypes": ["houses"],
    "states": ["distrito-federal"],
    "maxItems": 30,
    "maxPages": 1,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["UNBLOCKER"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("reventadata/vivanuncios-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 '{
  "propertyTypes": [
    "houses"
  ],
  "states": [
    "distrito-federal"
  ],
  "maxItems": 30,
  "maxPages": 1,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "UNBLOCKER"
    ]
  }
}' |
apify call reventadata/vivanuncios-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,reventadata/vivanuncios-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/tkviI2JHwRN9nLPHX/builds/5IMLexIRMNftiXuJB/openapi.json
