Skip to main content

Complete Guide: How to Scrape Vivanuncios Mexico Listings Using Python

Automate property extraction from Vivanuncios Mexico using Python and Apify to collect asking prices, property specs, coordinates, and advertiser contacts.

Updated 11 min readMarkdown
Complete Guide: How to Scrape Vivanuncios Mexico Listings Using Python

This complete guide shows how to extract structured Mexican property listings from Vivanuncios using Python and the Apify API. By integrating cloud scraping into your data stack, you will capture standardized, typed records: asking prices in Mexican pesos (MXN) or US dollars (USD), built surface areas, lot dimensions, bedroom and bathroom counts, parking spaces, full advertiser descriptions, municipal locations, coordinates, and WhatsApp agent contact numbers.

Vivanuncios (vivanuncios.com.mx) is a property classifieds portal in Mexico, listing residential and commercial properties across all 32 Mexican states. Harvesting property listings at scale presents technical challenges: the website is protected by Cloudflare bot mitigations that challenge automated HTTP clients, while its robots.txt enforces strict boundaries on search pagination and disallows query-string filtering parameters.

In this tutorial, you will learn how to configure and execute the Vivanuncios Scraper Apify Actor (reventadata/vivanuncios-scraper) using Python. We cover setup, parameterization, cloud execution through Apify Unblocker, schema interpretation, and webhook automation. Estimated reading time: 15 minutes.


TL;DR

In this tutorial, you will learn how to configure and run the Vivanuncios Scraper Apify Actor from Python, inspect run execution states, parse structured property records, and filter listings by price, dimensions, and location.

Key steps: install apify-client, export your APIFY_API_TOKEN, define search parameters in run_input, call reventadata/vivanuncios-scraper, and iterate through dataset items in run.default_dataset_id.

Expected outcome: a structured JSON dataset of Mexican real estate listings ready for database insertion, market analysis, or lead generation.

The Actor is available on the Apify Store: apify.com/reventadata/vivanuncios-scraper.


Prerequisites and setup

Before writing extraction scripts, verify that your local development environment satisfies these basic requirements:

  1. Python 3.11 or newer installed locally on your machine (apify-client 3.x requires Python 3.11 or higher to run).
  2. The official Apify Python client library installed in your active virtual environment:
pip install -U "apify-client~=3.0"
  1. An active Apify account. You can register for free using email or your GitHub profile. Apify Console is the cloud dashboard where you manage runs, storage datasets, and integration credentials; your secret API token is located under the API & Integrations tab in Apify Console. Official platform documentation and guides are available at docs.apify.com.

Export your secret token in your shell environment before executing commands:

export APIFY_API_TOKEN="your_apify_token_here"

Understanding Vivanuncios Scraper

The Vivanuncios Scraper collects clean property listings across Mexican real estate markets while handling infrastructure complexities behind the scenes:

  1. Category Routing & Pagination Ceilings: Vivanuncios allows browsing across operations (sale or rent) and property types (houses, apartments, land, commercial, offices, vacation, or all). Each search queries nationwide listings or focuses on any of Mexico's 32 states. The site's robots.txt allows result pages 1 through 5 only (with 30 listings per page), establishing a ceiling of 150 listings per search URL.
  2. Apify Unblocker Transport: Vivanuncios sits behind Cloudflare managed challenges. In benchmark testing on 2026-10-21, direct requests, datacenter proxies, and 24 of 25 residential proxy requests were blocked by Cloudflare challenges. The Actor uses Apify Unblocker proxies by default, which achieved 24 of 25 successful page fetches.
  3. Data Extraction & Dual Body Parsing: Pages serve preloaded JSON state records inside script tags. When the state block is present, the Actor extracts complete records including geocoordinates and agent contacts. If target pages arrive without the state script, the Actor makes up to three attempts and falls back to parsing HTML listing cards (source: "card"), preserving core property attributes.

Step-by-step walkthrough

Step 1: Initialize the client and define inputs

In your Python script, import ApifyClient, load your credentials from the environment, and define the search parameters in run_input:

import os
from apify_client import ApifyClient

# 1. Initialize ApifyClient with token from environment
client = ApifyClient(os.environ["APIFY_API_TOKEN"])

# 2. Define the extraction parameters
run_input = {
    "operation": "rent",
    "propertyTypes": ["apartments"],
    "states": ["jalisco"],
    "minBedrooms": 1,
    "maxPrice": 25000,
    "maxItems": 20,
}

(Note: This demonstration snippet uses maxItems: 20 for a fast initial test. The sample row cited below was captured from page 1 of this search on 2026-10-21.)

Step 2: Trigger execution on Apify

Invoke the Actor using client.actor("reventadata/vivanuncios-scraper").call(run_input=run_input). The client dispatches the container run to Apify's infrastructure and blocks until the run finishes:

# 3. Start the Actor run and wait for it to complete
print("Starting Vivanuncios Mexico extraction...")
run = client.actor("reventadata/vivanuncios-scraper").call(run_input=run_input)
if run is None or run.status != "SUCCEEDED":
    status = run.status if run else "unknown"
    raise SystemExit(f"Run did not succeed (status: {status}).")

# 4. Fetch the resulting dataset items
dataset = client.dataset(run.default_dataset_id).list_items().items

print(f"Extraction complete! Retrieved {len(dataset)} listings.\n")

Step 3: Inspect and export dataset records

Iterate over the resulting items to format, log, or store listing attributes:

for item in dataset:
    title = item.get("title") or item.get("generatedTitle")
    price = item.get("price")
    currency = item.get("currency") or "MXN"
    city = item.get("city")
    state = item.get("state")
    bedrooms = item.get("bedrooms")
    built_m2 = item.get("builtAreaM2")

    print(f"Listing: {title}")
    if price is None:
        print("  Price: unpriced")
    else:
        print(f"  Price: {price:,} {currency}")
    print(f"  Location: {city}, {state}")
    specs = []
    if bedrooms is not None:
        specs.append(f"{bedrooms} rec.")
    if built_m2 is not None:
        specs.append(f"{built_m2} m²")
    if specs:
        print(f"  Specs: {' · '.join(specs)}")
    print("-" * 50)

Here is a verbatim sample row from a capture dated 2026-10-21 (from search path /s-departamentos-en-renta/jalisco/v1c1300l1013p1, scrapedAt omitted):

{
  "id": "151221071",
  "url": "https://www.vivanuncios.com.mx/a-renta-departamento/moderna/departamento-en-renta-en-colonia-moderna-coordenada-lafayette/151221071",
  "title": "Departamento en Renta en Colonia Moderna, Coordenada Lafayette",
  "generatedTitle": "Departamento · 43m² · 1 Recámara · 1 Estacionamiento",
  "listingKind": "property",
  "operation": "Renta",
  "propertyType": "Departamentos",
  "price": 18000,
  "currency": "MXN",
  "maintenanceFee": null,
  "landAreaM2": 43,
  "builtAreaM2": 43,
  "bedrooms": 1,
  "bathrooms": 1,
  "halfBathrooms": null,
  "ageYears": 2,
  "parkingSpaces": 1,
  "description": "Departamento totalmente amueblado tipo loft en Coordenada Lafayette. Es ideal para quienes disfrutan de un estilo de vida dinámico, con fácil acceso a la cultura, el entretenimiento y los servicios. Es un lugar con carácter y mucha vida. Explorar las calles aledañas a la avenida Chapultepec que ofrecen un equilibrio entre la cercanía a la acción y un ambiente más bohemio y tranquilo. Características: Construcción: 43. 5 M2. 1 habitación. 1 baño completo. Cocina equipada. 1 lugar de estacionamiento. Amenidades: Lobby. Co-working. Sky Bar. bbq Zone. Ciclopuertos. Terraza de usos múltiples. * Se permiten Mascota Pequeña* *Mantenimiento Incluido* Cambios de información o precios sin previo aviso. Eb-th8015. pqGqjpm",
  "neighborhood": "Moderna",
  "city": "Guadalajara",
  "state": "Jalisco",
  "street": "Calle Juan Ruiz de Alarcón 519",
  "latitude": 20.6661433,
  "longitude": -103.3760042,
  "publisherId": "102342120",
  "publisherName": "FINCA INMUEBLES",
  "publisherTypeId": "2",
  "publisherUrl": "https://www.vivanuncios.com.mx/u-anuncios-del-vendedor/finca-inmuebles/v1u102342120p1",
  "publisherPhone": null,
  "contactWhatsapp": "523312564414",
  "premier": true,
  "imageCount": 8,
  "imageUrls": [
    "https://img10.naventcdn.com/avisos/18/01/51/22/06/81/720x532/1634354544.jpg?rapc=bXZhX2ltYWdl?isFirstImage=true",
    "https://img10.naventcdn.com/avisos/18/01/51/22/06/81/720x532/1634354545.jpg?rapc=bXZhX2ltYWdl",
    "https://img10.naventcdn.com/avisos/18/01/51/22/06/81/720x532/1634354548.jpg?rapc=bXZhX2ltYWdl",
    "https://img10.naventcdn.com/avisos/18/01/51/22/06/81/720x532/1634354541.jpg?rapc=bXZhX2ltYWdl",
    "https://img10.naventcdn.com/avisos/18/01/51/22/06/81/720x532/1634354552.jpg?rapc=bXZhX2ltYWdl",
    "https://img10.naventcdn.com/avisos/18/01/51/22/06/81/720x532/1634354556.jpg?rapc=bXZhX2ltYWdl",
    "https://img10.naventcdn.com/avisos/18/01/51/22/06/81/720x532/1634354551.jpg?rapc=bXZhX2ltYWdl",
    "https://img10.naventcdn.com/avisos/18/01/51/22/06/81/720x532/1634354547.jpg?rapc=bXZhX2ltYWdl"
  ],
  "hasVideo": false,
  "hasTour360": false,
  "hasPlans": false,
  "modifiedAt": "2026-10-21T17:28:50-0400",
  "source": "state",
  "searchPath": "/s-departamentos-en-renta/jalisco/v1c1300l1013p1",
  "searchPage": 1
}

Working with the API

The Apify Python SDK provides comprehensive programmatic control over run configuration, cloud execution lifecycle, and dataset retrieval.

To start an asynchronous Actor execution without blocking local execution, invoke client.actor("reventadata/vivanuncios-scraper").start(run_input=run_input). This initiates the container on Apify infrastructure and immediately returns a run object containing the run ID and execution status.

You can inspect execution progress, monitor container status changes, or stream logs directly from Python using client.log(run_id).get(). When the run finishes, the run object transitions to a final status such as SUCCEEDED, FAILED, or TIMED-OUT.

When integrating with external automation workflows, Apify webhooks notify external endpoints upon run completion. In Apify Console, create an HTTP webhook triggered by the ACTOR.RUN.SUCCEEDED event. The webhook delivers a payload whose resource object contains the full Get Actor run API response, including defaultDatasetId, run duration, and push statistics.

For regular extraction cadences, attach an Apify Schedule using standard 5-field cron syntax:

  • 0 8 * * *: Runs daily at 08:00 UTC.
  • 0 0 * * 1: Runs weekly every Monday at midnight UTC.

Result datasets can be exported programmatically in JSON, CSV, Excel, XML, HTML, RSS, or JSONL formats via API endpoints or downloaded directly through the Console. This enables seamless ingestion into analytics dashboards, SQL databases, or data warehouse pipelines.


Advanced Filtering and Query Patterns

Because Vivanuncios' robots.txt disallows query parameters like ?pr= (price bounds), ?fe= (features), and ?sort= (sorting), all filtering is performed inside the Actor after reading allowed search result pages:

  1. Multi-State Sweep: To scrape multiple regional property markets in a single execution, pass an array of state slugs such as run_input["states"] = ["distrito-federal", "jalisco", "nuevo-leon"]. The Actor executes sequential sweeps across each specified state directory without crossing query boundaries, maximizing geographic coverage across Mexico.
  2. City and Neighbourhood Start URLs: For municipal, alcaldía, or colonia-level targeting, supply direct Vivanuncios directory URLs via startUrls, for example run_input["startUrls"] = ["https://www.vivanuncios.com.mx/s-casas-en-venta/guadalajara/v1c1293l14822p1"]. Query strings in startUrls are refused during input validation to maintain robots.txt compliance. The Actor automatically strips existing pagination parameters and traverses pages 1 through 5.
  3. Attribute and Feature Thresholds: Refine your dataset by defining minimum standards: minBedrooms, minBathrooms, minParkingSpaces, minBuiltAreaM2, and minLandAreaM2. Rows that omit these fields (such as land parcels or commercial developments) are excluded before dataset ingestion.
  4. Keyword Matching and Exclusions: Use includeKeywords to keep listings containing specific features (such as ["alberca", "terraza", "jardin"]) and excludeKeywords to drop unwanted terms. The matching engine normalizes accents and case automatically, ensuring robust substring comparison across listing descriptions and addresses.

Understanding Your Data

Each extracted dataset record contains standardized, typed real estate attributes:

  • Identifiers: id (the portal's posting ID) and url (canonical listing page on vivanuncios.com.mx without tracking parameters).
  • Titles: title (headline written by the advertiser) and generatedTitle (the portal's summary string).
  • Listing Classification: listingKind ('property' for individual homes or 'development' for projects), operation ('Venta' or 'Renta'), and propertyType (e.g. 'Casas', 'Departamentos', 'Terrenos').
  • Financials: price (numerical asking price or monthly rental rate), currency ('MXN' or 'USD'), and maintenanceFee (monthly condominium HOA fee).
  • Dimensions & Layout: landAreaM2 (lot size), builtAreaM2 (constructed surface in square metres), bedrooms, bathrooms, halfBathrooms, parkingSpaces, and ageYears.
  • Location Hierarchy: neighborhood (colonia), city (alcaldía or municipality), state, street address, and latitude/longitude geographic coordinates.
  • Merchant Details: publisherName, publisherId, publisherTypeId (code 2 was seen on agencies; codes 3 and 4 also occur and the site does not publish their meaning), and contactWhatsapp with country code.
  • Media & Features: imageCount, imageUrls (720x532 resolution images), hasVideo, hasTour360, and hasPlans.
  • Extraction Source: source indicates 'state' when extracted from the embedded JSON state script, or 'card' when parsed from HTML fallback cards.

Troubleshooting Guide

When deploying the scraper in automated pipelines, keep these potential failure modes in mind:

  • RuntimeError on Zero Rows: The Actor raises a RuntimeError if zero listings are pushed to the dataset. This fail-safe alerts monitoring pipelines to misconfigured filters or empty search terms. Check whether price limits or keywords are overly restrictive.
  • Input Schema Enum Rejection: The Apify platform validates operation, propertyTypes, states, and priceCurrency against schema enums. Supplying an unknown state slug or invalid operation type is rejected before execution begins.
  • Incompatible Types: Land cannot be rented ('rent' + 'land'), and vacation properties cannot be sold ('sale' + 'vacation'). These combinations raise an error during option parsing.
  • Missing Built Area on Fallback Cards: When target pages arrive without the JSON state block and fallback to HTML listing cards (source: "card"), builtAreaM2, coordinates, and publisher details are null. Lot area (landAreaM2) and bedrooms remain available.
  • Query Strings in Start URLs: Search URLs containing query strings (?pr=, ?q=) are rejected because robots.txt disallows them. Supply clean path URLs.

Best Practices

Follow these guidelines for stable and efficient property extraction:

  1. Set Realistic Item Limits: Always set maxItems to cap the total listings stored. The Actor halts immediately once your quota is reached.
  2. Respect Site Ceilings: Vivanuncios limits search result pagination to 5 pages per query (up to 150 listings). For broader coverage, break your extraction into distinct state or city queries.
  3. Use Start URLs for Granular Markets: When targeting high-value neighbourhoods, use directory URLs in startUrls rather than nationwide state sweeps.
  4. Monitor Source Types: If your downstream application requires geocoordinates and agent phone numbers, assert item['source'] == 'state'.
  5. Automate with Schedules: Run recurring sweeps off-peak using cron expressions to capture newly listed inventory.

Conclusion and Next Steps

In this guide, you learned how to extract Mexican property listings from Vivanuncios into structured JSON using Python and Apify Unblocker proxies.

For current pricing and details, see the Store page.

Try Vivanuncios Scraper yourself and let me know what you build!

About the author: reventadata builds and publishes marketplace scrapers on the Apify Store.

About the author

  • Hi, I’m the engineer behind ReventaData. I build automated web scrapers, reverse-engineer undocumented APIs, and design data pipelines on Apify that turn complex, unstructured websites into clean, reliable feeds. Here on Hashnode, I share practical tutorials on modern web scraping with Python, bypassing aggressive anti-bot protections (Cloudflare, Akamai, PerimeterX), and data pipeline automation, reverse-engineering hidden endpoints, and automating data extraction. Explore our turnkey scrapers: https://apify.com/reventadata

No comments yet. Be the first to comment.

More from this blog