Fotocasa.es $1๐Ÿ’ฐ Buy, Rent & Property Details avatar

Fotocasa.es $1๐Ÿ’ฐ Buy, Rent & Property Details

Pricing

from $1.00 / 1,000 listing scrapeds

Go to Apify Store
Fotocasa.es $1๐Ÿ’ฐ Buy, Rent & Property Details

Fotocasa.es $1๐Ÿ’ฐ Buy, Rent & Property Details

From $1/1K. Scrape Spain property listings from fotocasa.es. Get price, surface, rooms, baths, address, GPS, agency, phone, energy rating, photos and 140+ fields. Buy and rent, all regions, all property types.

Pricing

from $1.00 / 1,000 listing scrapeds

Rating

0.0

(0)

Developer

Abot API

Abot API

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

0

Monthly active users

9 days ago

Last modified

Share

Fotocasa.es Scraper

Extract property listings from fotocasa.es, Spain's leading property portal, at scale. Search by location and filters or paste direct search URLs, and get clean, structured records with price, surface, rooms, bathrooms, full address, GPS coordinates, agency and contact details, energy rating, photos and 140+ fields per listing. Forward-walking pagination, optional per-listing detail enrichment, and ready-to-use exports to your apps.

Why This Scraper?

  • 140+ fields per listing - far more than typical alternatives, including both camelCase and snake_case field names so the output drops into any existing pipeline.
  • Buy and rent, every region, every property type - flats, houses, duplexes, penthouses, studios, lofts, new construction, garages, offices, land and more.
  • Rich location data - city, neighborhood, full address and precise latitude/longitude for every listing.
  • Agency and contact details - agency name, alias, type, phone, and (with detail enrichment) agent name, email and listing reference.
  • Two input modes - search by location with filters, or feed direct fotocasa.es search URLs.
  • Powerful filters - price, rooms, bathrooms and surface ranges, plus operation, property type and sort order.
  • Export anywhere - pipe results into Notion, Airtable, Linear or other apps via MCP connectors, with the full record always kept in the dataset.

Data You Get

Sample shape - values are illustrative placeholders, not from a live listing.

FieldExample
id1_000000000
propertyId000000000
titleC/ de Ejemplo, Centro
rawPrice295000
currencyEUR
pricePerSqm4538.46
surface65
rooms3
baths2
floor4
propertyType2
propertySubtype1
operationsale
cityMadrid
neighborhoodCentro
latitude40.4168
longitude-3.7038
agencyNameExample Agency SL
phone+34000000000
referenceREF-00000
energyCertificate{"energyEfficiencyRatingType": "C"}
images["https://static.fotocasa.es/images/ads/0000?rule=original"]
urlhttps://www.fotocasa.es/es/comprar/vivienda/madrid-capital/centro/000000000/d

How to Use

Search a city for homes to buy:

{
"mode": "search",
"locations": ["madrid-capital"],
"operation": "comprar",
"propertyType": "viviendas",
"maxListings": 50
}

Search with filters and sorting:

{
"mode": "search",
"locations": ["barcelona-capital"],
"operation": "alquiler",
"minPrice": 800,
"maxPrice": 1500,
"minRooms": 2,
"sortBy": "price_asc",
"maxListings": 100
}

Scrape direct URLs with full detail enrichment:

{
"mode": "url",
"urls": ["https://www.fotocasa.es/es/comprar/viviendas/valencia-capital/todas-las-zonas/l"],
"fetchDetails": true,
"maxListings": 200
}

Input Parameters

ParameterTypeDescription
modestringsearch (location + filters) or url (direct URLs).
locationsarrayLocation slugs, e.g. madrid-capital, barcelona-capital/centro. Search mode only.
operationstringcomprar (buy) or alquiler (rent). Search mode only.
propertyTypestringProperty category, e.g. viviendas, pisos, casas. Search mode only.
sortBystringrelevance, newest, price_asc, price_desc, surface_asc, surface_desc.
minPrice / maxPriceintegerPrice range filter (EUR).
minRooms / maxRoomsintegerRooms range filter.
minBaths / maxBathsintegerBathrooms range filter.
minSurface / maxSurfaceintegerSurface range filter (mยฒ).
urlsarrayDirect search URLs. URL mode only; filter fields are ignored.
fetchDetailsbooleanAdds energy rating, full features, reference and contact from the listing detail page. Slower and increases cost per listing.
maxPagesintegerOptional safety limit on result pages walked per search. Leave empty (or 0) for unlimited โ€” the walk continues until the site's natural end of results (an empty page) or maxListings is hit; only set a value to hard-stop pagination earlier.
maxListingsintegerThe run's sole cap on total listings scraped. Default 20. 0 = unlimited (walk the whole catalogue, bounded only by maxPages if set).
proxyobjectProxy configuration. Residential proxy with a Spanish (ES) exit is enabled by default, which fotocasa.es requires for reliable access.
residentialCountriesarrayCountry codes used for the residential proxy. fotocasa.es requires a Spanish (ES) exit.
maxResidentialRequestsintegerPer-run residential request budget (default 10000). Set lower to cap cost, or 0 to disable.
backupProxyUrlstringOptional last-resort failover proxy URL used when the Apify proxy is unavailable.
mcpConnectorsarrayMCP connectors to forward a per-listing summary to: notion, linear, airtable, apify. The full record always stays in the dataset.
notionParentPageUrlstringNotion page under which the new database is created (Notion connector only).
maxNotifyListingsintegerMax listings forwarded to MCP connectors per run (default 50).
resumeFromRunIdstringOptional. Paste a previous run ID (or its dataset ID) to continue that run as a delta: listings already saved there are skipped, so this run only adds new ones. Fails fast, before any scraping, if the ID doesn't resolve to a readable run or dataset. For recurring monitoring of the same search, use incrementalMode below instead.
incrementalModebooleanOff by default. Turn on for daily/recurring monitoring of the same search: the actor remembers the previous run's listings itself and classifies every listing NEW / UPDATED / UNCHANGED / REAPPEARED (and EXPIRED, opt-in). UNCHANGED listings are suppressed (not returned, not billed) unless emitUnchanged is on.
stateKeystringOptional, incremental mode only. Names a monitoring campaign so its state stays stable, or so two differently-configured runs can deliberately share one baseline. Leave empty to derive a key automatically from the search/URL and filter/detail settings.
emitUnchangedbooleanOff by default, incremental mode only. Also return (and bill) listings unchanged since the last run, marked UNCHANGED.
emitExpiredbooleanOff by default, incremental mode only. Also return (and bill) synthetic EXPIRED rows for listings that were tracked but no longer appear โ€” only produced once a run has fully scanned the tracked search (not when maxListings capped it, or resumeFromRunId was used that run).

Full-catalogue runs and resuming

To walk an entire search (not just a page or two), set maxListings: 0 and leave maxPages empty (or 0) โ€” the actor then paginates until the site itself runs out of results. If a full-catalogue run is interrupted (platform migration, manual abort, or a fresh run days later to pick up new listings), pass the previous run's ID as resumeFromRunId: the actor pages through that run's dataset, seeds its dedup set with the listing IDs already collected, and then scrapes only new listings. Separately, an interrupted run also survives a platform migration/resurrect on its own โ€” the actor checkpoints its seen-listing state during the run and resumes from it automatically; that checkpoint is cleared once a run finishes cleanly.

Incremental / recurring updates

resumeFromRunId continues one specific interrupted run. incrementalMode is the opposite use case: you schedule this actor to run the same search again and again (daily, weekly) and want only what changed, without pasting any id. Turn incrementalMode on and the actor keeps a baseline in its own key-value store, keyed on a hash of: mode, locations, operation, propertyType, sortBy, urls, every price/rooms/baths/surface filter, and fetchDetails. Two searches with different filters never share a baseline; raising or lowering maxListings/maxPages between runs does not fork a new one (caps are excluded from the key on purpose โ€” only what's tracked matters).

Each listing is classified against the baseline:

  • NEW โ€” not seen before.
  • UPDATED โ€” a tracked field changed; changedFields lists which ones.
  • UNCHANGED โ€” nothing changed. Suppressed by default (not returned, not billed) โ€” turn on emitUnchanged to get the full snapshot every run instead.
  • REAPPEARED โ€” previously marked EXPIRED, now found again.
  • EXPIRED โ€” was tracked, no longer found. Only emitted when emitExpired is on, and only after a run that fully scanned the tracked search (a maxListings/maxPages cap, or resumeFromRunId, skips expiry detection for that run rather than risk tombstoning a listing that simply wasn't reached yet).

Two exclusions from the change-fingerprint, both deliberate:

  • The embedded agency/publisher objects are excluded โ€” they carry that agency's own profile data (name, description, ranking, ...), not the listing's. Including them whole in the change fingerprint would re-flag every listing an agency holds as UPDATED whenever that agency edits its own profile, unrelated to any specific listing. The derived listing-level fields (agencyName, phone, clientAlias, clientType, clientUrl) stay in the diff โ€” a listing switching to a different agency or contact is still reported.
  • Fields only ever populated by fetchDetails (energyCertificate, reference, extraFeatures, constructionType, groundSurface, qualityRate, purchaseType, agentName, agentEmail, contactName, creationDate) are excluded from the diff for one classification whenever either side of the comparison โ€” this run's fetch, or the stored baseline โ€” lacks a landed detail-page fetch. Otherwise a single transient detail-fetch failure would read as those fields being wiped from the listing, and a listing's first-ever successful detail fetch (after an earlier failure) would read as those fields suddenly appearing as a "change".

Everything else โ€” including rawPrice/price and any occupancy/status-shaped field โ€” is real listing data and participates in the diff normally; a genuine price change always reports UPDATED, never silently dropped.

Output Example

Sample shape - values are illustrative placeholders, not from a live listing.

{
"id": "1_000000000",
"propertyId": "000000000",
"title": "C/ de Ejemplo, Centro",
"rawPrice": 295000,
"currency": "EUR",
"pricePerSqm": 4538.46,
"surface": 65,
"rooms": 3,
"baths": 2,
"floor": "4",
"propertyType": 2,
"propertySubtype": 1,
"operation": "sale",
"transactionTypeId": 1,
"city": "Madrid",
"neighborhood": "Centro",
"address": { "municipality": "Madrid", "province": "Madrid", "zipCode": "28000" },
"latitude": 40.4168,
"longitude": -3.7038,
"agencyName": "Example Agency SL",
"clientAlias": "Example Agency",
"clientType": "professional",
"phone": "+34000000000",
"reference": "REF-00000",
"energyCertificate": { "energyEfficiencyRatingType": "C" },
"images": ["https://static.fotocasa.es/images/ads/0000?rule=original"],
"photosCount": 12,
"description": "Bright reformed home in a well-connected central area.",
"url": "https://www.fotocasa.es/es/comprar/vivienda/madrid-capital/centro/000000000/d"
}

Export to Your Apps (MCP Connectors)

Beyond the dataset, this Actor can send a condensed summary of each listing straight into the tools you already use, via Model Context Protocol (MCP) connectors. The full record is always kept in the dataset; the connector receives a readable summary (title plus key fields) per item.

Supported connectors: Notion, Linear, Airtable, and Apify.

  1. Authorize the connector once under Apify โ†’ Settings โ†’ Integrations.
  2. Select one or more in the mcpConnectors input.
  3. (Notion only) Set notionParentPageUrl to the page the new database should be created under.
  4. Optionally cap how many listings are forwarded with maxNotifyListings (default 50).
{
"mode": "search",
"locations": ["madrid-capital"],
"operation": "comprar",
"maxListings": 50,
"mcpConnectors": ["notion"],
"notionParentPageUrl": "https://www.notion.so/your-workspace/Listings-0000"
}