willhaben Scraper & New-Listing Monitor - Austria Property
Pricing
from $0.73 / 1,000 property returneds
willhaben Scraper & New-Listing Monitor - Austria Property
Turn monitoring on and every later run returns only the listings it has not returned before, so you are never charged for the same property twice. Every willhaben.at listing as clean JSON: price with its meaning, price per m2, rooms, area, postcode, coordinates. No private sellers named. Unofficial.
Pricing
from $0.73 / 1,000 property returneds
Rating
0.0
(0)
Developer
NeverEmpty
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
18 hours ago
Last modified
Categories
Share
willhaben Scraper - Austria Real Estate Data, Price & Size
Pull property listings from willhaben.at — Austria's largest property portal — as clean JSON: the price as a number and what it means, price per m², rooms, living and plot area, floor, outdoor spaces, address with postcode and coordinates, and the agency, for flats, houses and land, for sale or to rent, anywhere in Austria.
Unofficial. This Actor is not affiliated with, endorsed by, or sponsored by willhaben. All product names are trademarks of their respective owners.
No API key. Reads the same public pages a visitor sees.
Run it tomorrow and you only get what is new
Schedule this Actor with monitoringMode: true and each run returns only the listings it has not returned before. Not "here is everything again, please de-duplicate it yourself" — the Actor remembers what it already gave you, so a daily feed of a 4,000-listing search costs you the handful of new homes, not 4,000 rows every morning. You are never charged for the same property twice.
Listings your filters removed are remembered too, so widening a filter later does not resurrect them as false "new" listings. Listings that did not fit under your limit are not remembered, so they are still waiting on the next run instead of being silently lost.
Why this one is different
The price means what it says
willhaben stores every price in the same field, whether it is a sale total or a monthly rent. This Actor labels it: priceType: "sale" on sales and priceType: "monthly-rent" on rentals (median rent in the 30 Vienna flats to rent measured: €1,249 a month; median price of the 80 unique Vienna flats for sale: €476,000). Land priced Preis auf Anfrage (on request) comes back as price: null with the display text in priceDisplay and isPriceOnRequest: true — never as a zero. willhaben's own price per m² is passed through in pricePerSqm.
Size means the right thing for the category
willhaben's main size field is the living area for flats and houses, but the plot for land. This Actor returns sizeSqm (willhaben's figure) plus livingAreaSqm, usableAreaSqm and plotAreaSqm, each filled only where it is the right meaning: all 30 land listings measured have plotAreaSqm and none has livingAreaSqm.
The publish time is the real one
willhaben ships two publish fields: a Unix timestamp and a text version that carries local Austrian time with a Z suffix — two hours in the future on every one of the 210 listings measured. publishedAt is built from the timestamp, so it never post-dates scrapedAt.
"0 rooms" is not sold as zero rooms
willhaben writes 0 in the room count on listings that simply did not fill it in (14 of the 210 measured, including a 188 m² detached house). Those come back as rooms: null, not 0.
Private sellers are never named — because willhaben does not name them either
Private listings (26 of the 210 measured) carry no name on willhaben, only a Privat label. This Actor returns advertiserType: "private" with agencyName: null for them and the agency name only for agency listings; Austrian phone numbers and e-mail addresses written into the text are removed. Property data, not a contact list.
An unknown place is a 404, and it is reported as one
willhaben answers a state or district it does not know with an honest 404. This Actor returns a no-such-search row that lists how willhaben spells its states and districts — distinct from no-results, which is willhaben's own "zero listings" answer. Both are free.
One request, 30 complete listings
willhaben embeds the full data of every listing in the search page. This Actor reads all 30 from that single page and never opens individual listing pages. willhaben's second page starts at the 21st listing, so 9 of its 30 cards were already on page one; repeats are dropped before delivery, so you are never charged twice for the same listing, and the page budget is sized for 21 new listings per page rather than 30.
Filters run here, because willhaben's robots.txt says so
willhaben's robots.txt disallows price and keyword query parameters (PRICE_FROM, PRICE_TO, keyword, TYPE …). This Actor therefore requests only the plain path plus ?page=N, and every filter — price, price per m², rooms, size, postcode, property type, advertiser, outdoor space, keywords, agency, publish date — runs on the rows already fetched. Nothing extra is requested and nothing extra is charged. A listing is never dropped for a value willhaben did not publish.
Input
Either paste a search URL, or build one from the fields below.
| Field | Type | Default | Description |
|---|---|---|---|
searchUrl | string | — | e.g. https://www.willhaben.at/iad/immobilien/eigentumswohnung/wien. Query parameters are dropped |
category | string | flat-buy | flat-buy, flat-rent, house-buy, house-rent, land |
state | string | wien | wien, niederoesterreich, oberoesterreich, salzburg, tirol, vorarlberg, kaernten, steiermark, burgenland. Empty = all of Austria |
district | string | — | As willhaben writes it: wien-1020-leopoldstadt, salzburg-stadt. Needs the state |
maxListings | integer | 20 | 1-1000. One listing = one row = one charged event |
maxPages | integer | 0 | Hard cap on requests; 0 = decide from maxListings |
includeDescription | boolean | true | The card text. The keyword filter searches it either way |
useProxy | boolean | false | Off by default — willhaben answers Apify's network directly. Switches on by itself if blocked |
keywords / keywordMatch / excludeKeywords | array / string / array | — | Match on title, description, type, address, district, outdoor spaces and agency |
agencyNames | array | — | Keep only these agencies (partial match) |
minPrice / maxPrice | integer | 0 | EUR. Sale total or monthly rent. A listing priced on request is kept |
maxPricePerSqm | integer | 0 | EUR per m², willhaben's figure |
requirePrice | boolean | false | Drop listings priced on request |
minRooms / maxRooms | integer | -1 | -1 = off. An unfilled room count is kept |
minSizeSqm / maxSizeSqm | integer | 0 | willhaben's main size. 0 = off |
postcodes | array | — | 4-digit Austrian postcodes |
propertyTypes | array | — | willhaben's German words, partial match: Wohnung, Dachgeschoßwohnung, Einfamilienhaus, Reihenhaus, Villa, Baugrundstück … |
advertiserType | string | any | agency or private |
outdoorSpaces | array | — | Balkon, Terrasse, Garten, Loggia. A listing with none published is kept |
excludeProjects | boolean | false | Drop listings that belong to a development project or advertise several units ("from" prices are flagged isPriceFrom) |
publishedWithinDays | integer | 0 | By willhaben's publish timestamp. 0 = off |
monitoringMode | boolean | false | Return only listings not returned on a previous run |
resetMonitoringState | boolean | false | One-shot: forget what was already returned |
{ "category": "flat-buy", "state": "wien", "district": "wien-1020-leopoldstadt", "maxListings": 100,"minRooms": 3, "maxPrice": 500000, "maxPricePerSqm": 7000, "outdoorSpaces": ["Balkon", "Terrasse"], "advertiserType": "agency" }
Monitoring mode turns this into a daily feed
Schedule it and set monitoringMode: true: each run returns only the listings it has not returned before. Listings removed by your filters are remembered too, so changing a filter later does not resurrect them as false "new" listings — and listings that simply did not fit under maxListings, or were cut off by the run's charge limit, are not remembered, so they are still waiting for you on the next run rather than being silently lost. willhaben lists newest first, so a small daily run catches new stock.
Measured on 2026-09-05: 20,089 flats for sale in Vienna; 4,645 flats to rent in Vienna; 418 plots in Tyrol.
Output
One row per listing:
{"source": "willhaben.at","status": "ok","listingId": "1459808476","title": "Exklusives Airbnb-Apartment mit Büro im 1. Bezirk - Zentrum Wien","description": "Zum Verkauf gelangt ein attraktives Apartment mit zusätzlichem Büro …","url": "https://www.willhaben.at/iad/immobilien/d/eigentumswohnung/wien/wien-1020-leopoldstadt/…-1459808476/","searchedLocation": "Eigentumswohnungen in Wien","category": "flat-buy","transactionType": "sale","propertyType": "Wohnung","propertyTypeId": "3","price": 169000,"priceCurrency": "EUR","priceType": "sale","priceDisplay": "€ 169.000","isPriceOnRequest": false,"pricePerSqm": 5633.3335,"rooms": null,"sizeSqm": 30,"livingAreaSqm": 30,"usableAreaSqm": null,"plotAreaSqm": null,"floor": null,"outdoorSpaces": [],"outdoorAreaSqm": null,"address": "Czerninplatz","postcode": "1020","location": "Wien, 02. Bezirk, Leopoldstadt","district": "Wien","state": "Wien","country": "Österreich","latitude": 48.21454,"longitude": 16.38717,"advertiserType": "private","agencyName": null,"isPriceFrom": false,"isProject": false,"projectUnits": null,"isPromoted": false,"isBumped": true,"imagesCount": 9,"mainImageUrl": "https://cache.willhaben.at/mmo/6/145/980/8476_-265142440.jpg","publishedAt": "2026-09-05T07:56:07.200Z","scrapedAt": "2026-09-05T08:19:55.370Z"}
Measured across 210 live listings (200 unique) on 2026-09-05 — flats for sale, flats to rent, houses for sale, houses to rent and land: id, title, description, url, location, district, state, coordinates and publish date on 210 of 210; postcode on 209; size on 208; a numeric price on 204; price per m² on 202; rooms on 166; outdoor spaces on 145; floor on 89; a street address on 87.
Rows that are never charged
status | when |
|---|---|
no-results | willhaben reports zero listings for this search. That is its answer, not a failure |
no-such-search | willhaben has no page at that address (HTTP 404) - a state or district spelled differently from willhaben's addresses. Not a claim that there is nothing there |
no-filter-match | Listings were read, but your filters removed all of them. The row says how many were read |
no-new-listings | Monitoring mode: nothing new since the previous run |
unreadable | The page could not be read, its embedded data was missing, or it claimed a total above zero while yielding nothing |
Pricing
Pay per listing returned. Rows that report an empty search, an unknown address, a filter that matched nothing, or a page that could not be read are not charged. A listing that appears twice across pages is dropped before delivery, so it is never charged twice.
Notes
robots.txtwas read in full on 2026-09-05. TheUser-agent: *section disallows/iad/admin,/iad/myprofile,/iad/searchagent,/mob/,/pal/and the query parameterscounterId,PRICE_FROM,PRICE_TO,SEGMENT,TYPE,keyword,periode,sid. This Actor requests only/iad/immobilien/<category>/<state>[/<district>]with?page=N.- Only public pages are read. No login, no API key.