Fotocasa Scraper
Scrape fotocasa.es homes for sale and rent: price, price per m2, surface, rooms, floor, neighbourhood, coordinates, agency or private seller.
How it works
- 1Open it on Apify
Hit Run on Apify — it opens the tool in the cloud, no install.
- 2Set the inputs
Adjust
location,transactionType,propertyType(sensible defaults are pre-filled). - 3Click Run
The tool runs on Apify’s cloud and collects the data for you.
- 4Export the results
Download as JSON, CSV or Excel, or pipe straight into your app, Google Sheets, or an AI agent.
Pricing
$0.00065 per listing = $0.65 per 1,000
| You are charged for | When | Price |
|---|---|---|
| Listing returned | One property listing returned in the dataset. Diagnostic rows and listings dropped by your filters are not charged. | $0.00065 |
Pay-per-event pricing: you are billed per result, not per subscription. Billing is handled by Apify on your own account. These are the live Apify store prices, in effect since 2026-09-20, and they are what you are actually charged.
Inputs
| Field | What it does | Type |
|---|---|---|
location | Type a town, district or neighbourhood the way it appears in Fotocasa's own search box: "Madrid", "Valencia", "Barrio de Salamanca", "Marbella". The "-capital" in their URLs is part of the address, not the name. The Actor looks it up and takes the match with the most live listings, so a bare province name gets you the province; use Area size below to pin it to a town. Leave empty if you are pasting search URLs. | string |
transactionType | Which market to read. Rooms to share and rent-to-own exist for homes only, and business transfers (traspasos) for commercial premises only; any other pairing stops the run before it searches. Only used with the Place field above; a pasted URL already says which one it is. | string |
propertyType | Only used with the Place field above. | string |
locationLevel | Which size of area the place name should resolve to. Automatic takes whichever match has the most live listings, which for a province name means the whole province. Only used with the Place field above. | string |
maxItems | Hard cap on how many listings the run delivers, across every search. You are charged per listing delivered, so this is also your spending cap. | integer |
startUrls | Paste search pages straight from fotocasa.es, for example https://www.fotocasa.es/es/comprar/viviendas/barcelona-capital/todas-las-zonas/l, whatever filters you set on the site come with the URL. The Actor pages through each one until it runs out of results or hits your maximum. One URL per line. | array |
sortType | Newest first is the default because Fotocasa's own relevance order shuffles between requests, which makes deep paging return the same listing twice. Only used with the Place field above. | string |
advertiser | Keep only listings from estate agencies, or only from private sellers. Fotocasa has no server-side filter for this, so the Actor reads the page and drops the rest, you are not charged for anything it drops. | string |
publicationDate | Only listings Fotocasa published in this period. Fotocasa applies it before anything is charged. Only used with the Place field above: for a pasted URL, set the date on the site before you copy it, because a run that has both stops before searching. | string |
minPrice | In euros. For rentals this is the monthly rent. | integer |
maxPrice | In euros. For rentals this is the monthly rent. | integer |
minSurface | Built surface in square metres, as Fotocasa reports it. Applied by Fotocasa before anything is charged. | integer |
maxSurface | Built surface in square metres. Leave empty for no upper limit. | integer |
minRooms | Bedrooms, not total rooms. Fotocasa caps this filter at 10. | integer |
maxRooms | Bedrooms, not total rooms. Leave empty for no upper limit. | integer |
minBathrooms | Bathrooms. Fotocasa caps this filter at 10. | integer |
maxBathrooms | Bathrooms. Leave empty for no upper limit. | integer |
latitude | Only listings within "Radius" of this point, measured from each listing's own map position. Fill in latitude, longitude and radius together, for example 39.4699 and -0.3763 for the middle of Valencia. Fotocasa ignores distance, so the run reads the place's listings and leaves out the ones farther away, uncharged. Keep the place small, the town or district your point is in: a small circle in a big place can come back with fewer rows than you asked for. | string |
longitude | Used together with latitude and radius. West of Greenwich is negative, so most of Spain is: -3.7038 for Madrid, -0.3763 for Valencia. | string |
radiusKm | In km, from 1 to 50. Used together with latitude and longitude. | integer |
What you get
A structured dataset — each result includes fields like:
pricepricePeriodpricePerM2surfaceM2roomsbathroomsfloorpropertySubtypeneighbourhoodmunicipalityprovincepostcodelatitudelongitudeadvertiserTypeadvertiserNamepublishedAturlExport every run as JSON, CSV or Excel, or send it to your app, a database, Google Sheets, or an AI agent.
Related tools in Developer & Research Tools
Other ready-to-run tools in the same category — all pay-per-use on the Apify cloud.
GitHub Scraper
Search GitHub repos and users: stars, forks, language, topics, licence, plus user bio, company and followers. No token needed. $0.90 per 1,000 rows.
Stack Overflow / Stack Exchange Scraper
Search Stack Overflow and Stack Exchange by keyword or tag. Score, answer count, views, reputation and body text. $2 per 1,000 questions.
Package Registry Scraper (npm + PyPI)
Get npm and PyPI package metadata as JSON. Version, license, author, repo, keywords and npm monthly downloads. $2 per 1,000 packages.
arXiv Scraper
Search arXiv papers by title, author, abstract or category. Get full abstracts, authors, categories, DOI, dates and PDF links. $2 per 1,000 papers.
OpenAlex Scholarly Works Scraper
Search 250M+ OpenAlex papers with no API key. Get titles, authors, venue, year, citations, DOI, OA links and full abstracts. $2.00 per 1,000 papers.
Crossref Scholarly Works Scraper
Search 150M+ papers on Crossref: DOI, title, authors, journal, publisher, date, citations and abstract. No API key. $1.00 per 1,000 works.
Where this tool sits
- Categories
- Developer & Research Tools
Fotocasa Scraper: Spanish property listings by town or search URL
Type a place like "Valencia" or paste a fotocasa.es search page, and get the listings back as rows. Asking price, price per m2, built surface, rooms, bathrooms, floor, neighbourhood, coordinates, the advertiser, the feature list and every photo link.
One thing to know before you start: Fotocasa has no server-side filter for agency versus private seller, so that filter is applied after each page is read. Ask for private sellers only in an agency-heavy town and you will get back fewer rows than you asked for. You are not charged for the ones it drops, and the run says how many there were.
| Input | A place name, or fotocasa.es search URLs |
| Output | One row per listing |
| Ceiling | 20,000 listings per run |
| Account needed | None |
| Price | $0.65 per 1,000 listings, flat on every plan |
🏠 What Fotocasa Scraper does
Give it a place and it looks the name up against Fotocasa's own index, picks the match with the most live listings, builds the search and pages through it. Or skip the lookup: set your filters on fotocasa.es, copy the address bar, and paste it in. Whatever you picked on the site travels with the URL.
It covers sales and rentals across eight property types: homes, garages, offices, commercial premises, land, rural houses, whole buildings and storage rooms. It also reads rooms in shared homes, rent-to-own homes and business transfers of commercial premises.
Price, surface, room, bathroom and publication-date filters are handed to Fotocasa, so listings outside them never reach you and never cost anything. The advertiser filter is one exception, described above. A search near a point is the other: Fotocasa ignores distance, so the run reads the place's listings and keeps the ones within radiusKm of your point, measured from each listing's own map position. Type the town or district the point is in, because a small circle in a big place comes back with fewer rows than you asked for.
Order matters more than it looks. Newest first is what the run uses because Fotocasa's own relevance order shuffles between requests, and paging deep into a shuffled list hands you the same flat twice.
📥 What you give it
{
"location": "Valencia",
"transactionType": "rent",
"propertyType": "homes",
"maxItems": 100,
"minPrice": 800,
"maxPrice": 2000,
"minRooms": 2
}
| Field | What the run uses if you leave it | What it is |
|---|---|---|
location | box starts at Valencia | A town, district or neighbourhood, spelled the way Fotocasa's own search box spells it. The -capital in their URLs is part of the address, not the name. |
startUrls | box starts empty | Search pages copied from fotocasa.es, one per line. Use these instead of location when you have already built the search on the site. |
transactionType | sale | sale, rent, share (a room in a shared home), rent-to-own, or transfer (a business transfer, or traspaso). share and rent-to-own exist for homes only and transfer for premises only; any other pairing stops with a free BAD_INPUT row. Ignored when you paste a URL, since the URL already says which. |
propertyType | homes | homes, garages, offices, premises, land, rural-houses, buildings or storage-rooms. |
locationLevel | auto | How big an area the name should resolve to. auto takes whichever match has the most live listings, so a bare province name gets you the province. Set MUNICIPALITY to pin it to a town. |
maxItems | 100 | Hard cap on rows delivered, up to 20,000. This is also your spending cap. |
sortType | publicationDate | publicationDate (newest first), price (cheapest first), pricem2 (cheapest per m2 first), surface (largest first) or scoring. |
advertiser | any | any, agency or private. |
publicationDate | any | lastDay, last48Hours, lastWeek or lastMonth: only listings published in that period, applied by Fotocasa. Place searches only. With startUrls filled in the run stops with a free BAD_INPUT row, so set the date on the site before copying the URL. |
minPrice, maxPrice | none | Euros. On rentals this is the monthly rent. |
minSurface, maxSurface | none | Built surface in m2, as Fotocasa reports it. |
minRooms, maxRooms | none | Bedrooms, not total rooms. Fotocasa caps this filter at 10. |
minBathrooms, maxBathrooms | none | Bathrooms. Fotocasa caps this filter at 10. |
latitude, longitude | none | A point on the map, such as 39.4699 and -0.3763 for the middle of Valencia. Only used with radiusKm. |
radiusKm | none | 1 to 50 km. Only listings that close to the point are delivered, and the ones farther away are dropped uncharged. Set all three point fields or none: a missing one, or a point outside Spain, stops the run with a free BAD_INPUT row. |
proxyConfiguration | none | Optional. Point the run at your own servers if traffic has to leave from a particular network. |
📤 What you get back
A real row from a recent run, with the photo links trimmed and the list cut short:
{
"id": "190879808",
"adId": "41be50f4-1bff-49d8-aa31-7c64409b439a",
"url": "https://www.fotocasa.es/es/alquiler/vivienda/valencia-capital/.../190879808/d",
"transactionType": "rent",
"propertyType": "home",
"propertySubtype": "intermediate floor",
"price": 1800,
"priceText": "1.800 €",
"pricePeriod": "month",
"previousPrice": null,
"pricePerM2": 15,
"surfaceM2": 120,
"rooms": 4,
"bathrooms": null,
"floor": null,
"condition": null,
"isNewConstruction": false,
"address": "Els Orriols",
"neighbourhood": "Els Orriols",
"district": "Rascanya",
"municipality": "Valencia",
"province": "Valencia",
"postcode": "46019",
"latitude": 39.49346496734346,
"longitude": -0.3712033344287845,
"advertiserType": "agency",
"advertiserName": "HOUSINGANYWHERE",
"advertiserUrl": "https://www.fotocasa.es/es/pro/housinganywhere/",
"phone": null,
"features": ["furnished", "washing_machine", "tv", "pets_allowed", "laundry"],
"images": ["https://static.fotocasa.es/images/ads/1cab486a-...?rule=original"],
"imageCount": 10,
"hasFloorPlan": false,
"hasVirtualTour": false,
"publishedAt": "2026-09-20T01:02:40.153Z",
"searchUrl": "https://www.fotocasa.es/es/alquiler/viviendas/espana/...",
"page": 1,
"position": 1,
"scrapedAt": "2026-09-20T02:42:01.740Z"
}
| Field | What it is |
|---|---|
id | Fotocasa's own listing number. Stable, so use it to dedupe across runs. |
price, pricePeriod | A number in euros. pricePeriod is month on rentals and null on sales. |
previousPrice | The old asking price when Fotocasa is showing a reduction, otherwise null. |
bathrooms, floor, condition | null when the advertiser did not fill that in, which is common on rentals. |
latitude, longitude | Fotocasa's own coordinates, which on some listings point at the street rather than the door. |
distanceKm | Only on a search near a point: how far the listing's coordinates are from it, in km. |
advertiserType | agency or private. phone is only present when the advertiser published one. |
features | Fotocasa's own English-ish keys, such as pets_allowed and air_conditioning. |
searchUrl, page, position | Where in which search the listing was found, so you can trace a row back. |
🧾 Reading the output
Three kinds of row can land in your dataset.
| Row | How to spot it | Charged |
|---|---|---|
| A listing | no _sample and no _diagnostic key | yes |
| The sample row | _sample: true | no |
| A diagnostic | _diagnostic: true and an errorCode | no |
Filter on _sample and _diagnostic being absent. Start a run with nothing filled in and you get the sample row and nothing else, so you can see the field shape before spending anything.
| Code | What it means |
|---|---|
NO_RESULTS | The search is valid, Fotocasa just has nothing matching right now. |
LOCATION_NOT_FOUND | The place name matched nothing. Try the plain town name, or paste a search URL. |
LOCATION_LEVEL_UNAVAILABLE | No area of the size you asked for exists there, so the next one up was used. |
NOT_A_FOTOCASA_URL | One of your startUrls is not a fotocasa.es address. The others still ran. |
BAD_INPUT | The input asked for something this search cannot apply, such as publicationDate with pasted URLs or transfer on homes. Nothing was searched. |
FILTERED_OUT | How many listings the advertiser filter dropped, how many were older than the publication period you set, or how many lay outside your radius. None of them were charged. |
FILTER_LIMITED_RESULTS | Fewer rows than asked for, because only some listings in that search match the advertiser filter or fall inside your radius. |
DEADLINE_REACHED | The run timeout was approaching, so paging stopped. Everything delivered is complete. |
PROXY_GROUP_CLAMPED | A network setting in your input was not usable, so the run used its own. |
UNEXPECTED_ERROR | Something broke. The run still exits cleanly with whatever it had. |
One bad URL never stops the others, and a diagnostic row never fails the run.
▶️ How to run it
1. Open Fotocasa Scraper and click Try for free. 2. Type a town into Place, or paste search pages into Fotocasa search URLs. 3. Pick Buy or rent and a Property type. 4. Set Maximum listings. Start around 20 to see the shape of the output. 5. Click Start, then download the dataset as JSON, CSV or Excel, or read it from the Apify API.
💰 How much does it cost?
$0.65 per 1,000 listings. Flat on every Apify plan, no volume tiers.
You pay per listing row delivered. Duplicates found twice across searches, listings dropped by the advertiser filter or the radius, the sample row and diagnostic rows are all free.
💡 What people use it for
- Tracking asking prices in one neighbourhood week by week, with
sortTypeonpublicationDateand
id as the dedupe key.
- Pulling everything a single estate agency has listed in a province, using
advertiser. - Building a price-per-m2 picture of a town before buying, since
pricePerM2comes straight off the
listing rather than being worked out afterwards.
- Finding private-seller rentals under a budget, which is the search most people build by hand and
then reload every morning.
🚧 What it does not do
- No contact details beyond what the advertiser published.
phoneisnullon most listings and
there are no email addresses at all.
- A bare province name gives you the province. "Valencia" resolves to whichever match has the
most live ads. Set locationLevel to MUNICIPALITY if you meant the city.
- The advertiser filter runs after the page is read, so it can return fewer rows than
maxItems. - Fields the advertiser left blank come back
null. Bathrooms, floor and condition are missing
often enough that you should plan for it.
- Coordinates are Fotocasa's, and on some listings they mark the street, not the building.
- The radius is applied here, not by Fotocasa. The place still decides which listings are read,
and the run stops reading a search where fewer than 1 listing in 50 falls inside the circle. The smallest radius is 1 km.
- Photo links point at Fotocasa's image servers. Fine to fetch now, not an archive.
- Rows are a snapshot. A flat can be sold, relisted or repriced an hour later, and
scrapedAt
records when it was read.
- Spain only. Fotocasa does not list anywhere else.
🧭 Which property scraper do you need?
| If you want | Use |
|---|---|
| Spanish listings from Fotocasa | This one |
| Spain, Italy or Portugal from Idealista | Idealista Scraper |
| Brazilian rentals and sales | QuintoAndar Scraper |
| Brazilian listings from VivaReal and ZAP | VivaReal & ZAP Imóveis Scraper |
| United States listings | Realtor.com Scraper |
❓ Questions people ask
Do I need a Fotocasa account? No. Nothing to sign up for and no key to manage.
Can I just paste a search I already built on the site? Yes, that is usually the best way. Put the address-bar URL into startUrls and every filter you set comes with it.
Why did I get fewer listings than I asked for? Either the search does not have that many, or the advertiser filter or the radius dropped some. The diagnostic row tells you which.
Can I watch one area over time? Yes. Schedule it, keep sortType on publicationDate, and dedupe on id. New listings arrive at the top.
Does it read rentals as well as sales? Both. Set transactionType, or paste a rental URL.
Is scraping property listings legal? These are public adverts on a public site. Some rows carry an advertiser's name and phone number, which is personal data under GDPR, so have a reason for collecting it. Apify's write-up on scraping and the law is a sensible starting point, and we are not lawyers.
🆘 If something breaks
Open the Issues tab on the actor page. Send the run ID and the place or URL you used. The errorCode on the diagnostic row usually names the problem on its own.