ActorStack.dev
Real estateDeveloper toolsv0.1.10updated 19 August 2026

Zonaprop Argentina Real Estate & Agency Scraper

No login. No cookies. No CAPTCHA solving.

Extracts property listings, new developments and real estate agencies from Zonaprop, Argentina's largest property portal, with exact coordinates and every attribute the listing exposes. It runs one entity type per run so the table you download has a single clean shape, and it states its coverage ceiling instead of implying it scraped the whole country.

oswaldocarabano/zonaprop-scraper

input.json
{
  "propertyType": "departamentos",
  "operationType": "sale",
  "location": "palermo",
  "maxItems": 200,
  "scrapeDetails": true,
  "proxyCountry": "mx"
}
Version
v0.1.10
Memory
512 MB
Browser
none
Proxy
Residential, required — and it must not be Argentine

Short answer

The Zonaprop Argentina Real Estate & Agency Scraper extracts property listings, new developments and agency profiles from Zonaprop without a login: price in USD or ARS with expenses and price drops, total and covered area, rooms, age in years, exact latitude and longitude, and seller type taken from Zonaprop's own agency-versus-private labelling. Pricing is $0.001 per property or development and $0.002 per agency, and failed requests are never charged.

Key points

  • Runs signed-out with no cookies and no CAPTCHA solving. It gets through Cloudflare by making ordinary requests from residential IPs and keeping the sessions that work.
  • A residential proxy is required and it must not be Argentine: Argentine IPs are challenged by Zonaprop's protection. Mexico measured best, and it is the default.
  • One entity type per run — listings, developments or agencies — because their fields genuinely differ and mixing them produces a table half full of empty columns.
  • Exact latitude and longitude on the listing, plus an address-accuracy flag, rather than a neighbourhood centroid.
  • `seller_type` carries Zonaprop's own distinction between an agency and a private owner ("dueño directo"), so the two segments can be separated without inference.
  • The coverage ceiling is stated: Zonaprop serves a few hundred results per search URL no matter how many match, and robots.txt caps this Actor at 5 pages per URL, so large searches are split by location instead.
On this page11 sections

What it does

Extracts property listings, new developments and real estate agencies from Zonaprop, Argentina's largest property portal, with exact coordinates and every attribute the listing exposes. It runs one entity type per run so the table you download has a single clean shape, and it states its coverage ceiling instead of implying it scraped the whole country.

output — one row
{
  "posting_id": "54321098",
  "url": "https://www.zonaprop.com.ar/propiedades/...",
  "title": "Departamento 3 ambientes en Palermo Hollywood",
  "property_type": "Departamento",
  "operation_type": "sale",
  "price_amount": 245000,
  "price_currency": "USD",
  "price_formatted": "USD 245.000",
  "expenses_amount": 95000,
  "expenses_currency": "ARS",
  "total_area_m2": 78,
  "covered_area_m2": 71,
  "rooms": 3,
  "bedrooms": 2,
  "bathrooms": 2,
  "age_years": 12,
  "condition": "Muy bueno",
  "address": "Bonpland 1500",
  "address_visibility": "exact",
  "neighborhood": "Palermo Hollywood",
  "city": "Capital Federal",
  "province": "Capital Federal",
  "latitude": -34.5885,
  "longitude": -58.4372,
  "seller_type": "agency",
  "publisher_name": "Example Propiedades",
  "phone": "+541140000000",
  "partial_phone": "11400",
  "pictures_total_count": 24,
  "status": "active",
  "from_cache": false,
  "data_age_hours": 0
}

Why this one

It says what it cannot reach

One Zonaprop search can hold 74,000 properties and still only page through about 270 of them. That is the site's limit, not a scraper's. This Actor respects robots.txt — 5 pages, 150 results per URL — and then splits a large search into smaller ones by location to reach more of the inventory. Ask for a neighbourhood and an operation and coverage is near-complete; ask for every apartment in Argentina and no tool can deliver that, this one included.

The proxy requirement is a finding, not a setting

Zonaprop sits behind Cloudflare and challenges Argentine IPs. That is why a residential proxy is mandatory and why the country selector excludes Argentina — Mexico measured best. The concurrency default of 3 is part of the same finding: pushing harder gets sessions challenged, which costs more time than the parallelism saves.

Private sellers' phone numbers are off by default

Agency numbers are public business contacts and are always included. A private owner is an individual, so their number is withheld unless you turn it on, and the input says why. There is also a `partial_phone` field, which is not the number: it is the five-digit fragment Zonaprop itself renders to any visitor — area code plus three digits — so the five digits that identify the line are never in the output.

Restricted permissions, on purpose

The Actor runs with restricted permissions and touches only its own default dataset and key-value store, never the rest of your account's storages. That is also why everything lands in one dataset rather than several named ones, and why entity types are separated by run instead of by dataset.

Use cases

  • Build a priced, geolocated dataset of a neighbourhood's for-sale or rental inventory.
  • Track asking prices in USD and ARS over time in a market where both currencies are quoted.
  • Separate agency inventory from private-owner listings using Zonaprop's own labelling.
  • Map new-build developments against existing stock in the same zone.
  • Build an agency directory with listing counts, profile URLs and public business phones.
  • Feed a valuation or yield model with area, rooms, age, condition and exact coordinates.

Input

Every field has a default, and the defaults are deliberately small so a first run is cheap enough to inspect before you commit to a sweep. This table mirrors the Actor's own input schema field for field.

FieldDefaultWhat it does
startUrlsstring[][]Start URLsZonaprop search URLs to scrape. Leave empty to build the search from the filters below.
entityTypeselect"listings"What to scrapeOne entity type per run: `listings`, `developments` or `agencies`. Their fields genuinely differ, so mixing them would give you one table with half the columns empty.
propertyTypeselect"departamentos"Property typeZonaprop's own property-type slug, used when no start URL is given.
operationTypeselect"sale"OperationSale, rent or temporary rent.
locationstring"capital-federal"LocationLocation slug — `capital-federal`, `palermo`, `cordoba`, `gba-norte`. Empty searches the whole country, which the coverage ceiling makes a poor idea.
maxItemsinteger100Maximum resultsHard cap on delivered results. You are charged only for results actually delivered.
maxPagesPerUrlinteger5Pages per search URLCapped at 5, which is what Zonaprop's robots.txt allows. Each page holds 30 listings, so more results come from splitting the search, not from paging deeper.
scrapeDetailsbooleanfalseScrape listing detail pagesAdds the publication date, every photo, floor plans, videos, virtual tours and the full description. A detail page costs about ten times a search result.
includePrivateSellerPhonebooleanfalseInclude private seller phone numberspersonal dataAgency numbers are always included. A private seller is an individual, so their number is opt-in and the choice is yours to justify.
maxConcurrencyinteger3Maximum concurrencyKeep it low. Zonaprop is behind Cloudflare and aggressive crawling gets IPs challenged, which costs more time than the parallelism saves.
proxyCountryselect"mx"Proxy countryCountry for the residential proxy. Argentine IPs are challenged, so a non-Argentine country is required. Mexico measured best.

Output and fill rates

A field being in the schema is not the same as it having a value. The percentages below were counted on real runs; the sample sizes are in Measurements. Anything not listed here is not promised.

FieldFilledMeaning
posting_idstringnot measuredZonaprop's listing identifier. The join key across runs.
urlstringnot measuredCanonical listing URL.
titlestringnot measuredListing title as published, in Spanish.
property_typestringnot measuredProperty type as Zonaprop classifies it.
operation_typestringnot measuredSale, rent or temporary rent. A property listed for both carries every operation.
price_amountnumbernot measuredAsking price. An offer, never a transaction price.
price_currencystringnot measured`USD` or `ARS`. Both are quoted in this market, so the currency is not decoration.
expenses_amountnumbernot measuredMonthly building expenses, with `expenses_currency` and `expenses_reported` alongside.
total_area_m2numbernot measuredTotal area in square metres.
covered_area_m2numbernot measuredCovered area in square metres.
roomsintegernot measuredRoom count, with `bedrooms`, `bathrooms`, `toilets` and `parking_spaces` separately.
age_yearsintegernot measuredAge of the property in years, as published.
layoutstringnot measuredLayout, with `orientation`, `brightness` and `condition` alongside.
addressstringnot measuredStreet address, with `address_visibility` recording how precise Zonaprop was willing to be.
latitudenumbernot measuredExact latitude, not a neighbourhood centroid.
longitudenumbernot measuredExact longitude.
neighborhoodstringnot measuredNeighbourhood, with `city`, `province`, `zone`, `subzone` and the full `location_path`.
seller_typestringnot measuredAgency or private owner, carried through from Zonaprop's own labelling.
publisher_namestringnot measuredSeller name, with `publisher_url`, `publisher_since` and a logo.
phonestringnot measuredAgency phone. Withheld for private sellers unless explicitly enabled.
partial_phonestringnot measuredThe five-digit fragment Zonaprop shows publicly. Not the phone number.
pictures_total_countintegernot measuredPhoto count, with `main_image_url` and flags for video, plans and virtual tour.
statusstringnot measuredListing status, with `is_reserved`, `is_premier` and `modified_at`.
from_cachebooleannot measuredWhether the row was served from the shared cache, with `data_age_hours`.

Every key is always present. A field that exists but is empty comes back as explicit null, so a parser never has to guess.

Datasets

Different record types go to different datasets, so the main table never carries columns that are blank on most rows.

  • defaultOne row per entity of the type you selected: listing, development or agency.billed
  • ERRORS (key-value store)Anything that failed, with the reason.never billed

Pricing

Pay per delivered result. Charges are applied as each row is produced rather than in a lump at the end, so an aborted run bills only for what it actually gave you.

EventPriceNotes
actor-startActor start$0.00001Charged once when the run starts. The platform minimum.
propertyProperty listing$0.001One property listing delivered. Failed requests are never charged.
developmentNew development$0.001One new-development listing delivered.
agencyReal estate agency$0.002One agency profile delivered, including how many listings it holds.

Measurements

Each figure is shown with the method that produced it. A benchmark without a method is a marketing claim wearing a number's clothes.

Per-search ceiling

~270 results per search URL

One search can match 74,000 properties and still only page through a few hundred. It is a limit of the site, so a large search is split by location instead.

Compliant pagination depth

5 pages, 150 listings per URL

What Zonaprop's robots.txt allows, at 30 listings per page. The Actor does not go beyond it.

Proxy country

Mexico best; Argentina challenged

Argentine residential IPs are challenged by Zonaprop's Cloudflare protection, so the selector excludes them.

Concurrency

3 by default

Higher concurrency gets sessions challenged, which costs more wall-clock time than the parallelism saves.

Detail page cost

~10x a search result

Which is why `scrapeDetails` is off by default rather than on.

What it will not do

Stated plainly so you can judge fit before spending anything.

  • A few hundred results per search URL is the site's ceiling — about 270 — regardless of how many listings match. Large searches must be split by location.
  • robots.txt caps pagination at 5 pages per URL, which is 150 listings, and this Actor does not go beyond it.
  • One entity type per run. Listings, developments and agencies each need their own run.
  • A residential proxy is required, and an Argentine one will be challenged.
  • Detail pages cost roughly ten times a search result, so `scrapeDetails` is off by default.
  • No CAPTCHA solving and no fingerprint spoofing. If the public data becomes unreachable without them, the run reports the failure.

Privacy

  • Agency phone numbers are always returned: they are public business contact details.
  • Private sellers are individuals, so their phone number is withheld unless `includePrivateSellerPhone` is enabled — and enabling it is your decision, with your lawful basis.
  • `partial_phone` is not a phone number. It is the five-digit fragment Zonaprop publishes to every visitor, covering the area code and three digits; the five digits that identify the line are never included.
  • Removal requests: privacy@actorstack.dev

See also the data removal process.

Frequently asked questions

Do I need a proxy to scrape Zonaprop?
Yes, a residential one, and it must not be Argentine. Zonaprop sits behind Cloudflare and challenges Argentine IPs. Mexico measured best and is the default; the Actor makes ordinary requests and keeps the sessions that work rather than hammering the site.
How many listings can one run return?
As many as you cap it at, but a single search URL only yields a few hundred no matter how many properties match — about 270 — and robots.txt limits this Actor to 5 pages, or 150 listings, per URL. Larger runs come from splitting the search by location, which the Actor does automatically.
Are private sellers' phone numbers included?
Not by default. Agency numbers are public business contacts and are always returned. A private owner — Zonaprop's "dueño directo" — is an individual, so their number is opt-in and the responsibility for having a lawful basis is yours. `partial_phone` is a different field and is not the number: it is the five-digit fragment Zonaprop itself shows every visitor.
Can I get listings, developments and agencies in one run?
No, and that is deliberate. The three have genuinely different fields, so one dataset holding all three would be a table with most columns empty on most rows. Run the Actor once per type and each download has a single clean shape.
Are the coordinates exact or approximate?
Exact latitude and longitude as the listing publishes them, not a neighbourhood centroid, and `address_visibility` records how precise Zonaprop was willing to be about the street address.
Does it include prices in both USD and ARS?
It returns the currency the listing is quoted in — Argentine listings appear in both — as `price_amount` plus `price_currency`, with the formatted original alongside. No conversion is applied, because a converted figure would embed an exchange rate the Actor cannot vouch for.

Guides for this Actor