atHome.lu Scraper - Luxembourg Real Estate Data & Prices
Pricing
from $7.30 / 1,000 property returneds
atHome.lu Scraper - Luxembourg Real Estate Data & Prices
atHome.lu listings for sale or rent as clean JSON: price as a number with its meaning (sale, monthly rent or new-build range), charges apart from rent, price per m2, surface, bedrooms, energy class, address with coordinates and the agency. No agent contacts. Unofficial.
Pricing
from $7.30 / 1,000 property returneds
Rating
0.0
(0)
Developer
NeverEmpty
Maintained by CommunityActor stats
0
Bookmarked
3
Total users
2
Monthly active users
5 hours ago
Last modified
Categories
Share
Pull property listings from atHome.lu — Luxembourg's largest property portal — as clean JSON: the price as a number and what it means, price per m², surface, bedrooms, energy class, address with coordinates and the agency, for sale or to rent, across Luxembourg.
Unofficial. This Actor is not affiliated with, endorsed by, or sponsored by atHome. 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, and a new-build project is a range
atHome keeps a sale total in one field and a monthly rent in another. This Actor labels the number: priceType: "sale" (median in the 40 Luxembourg-city flats for sale measured: €1,000,000) or priceType: "monthly-rent" (median in the 20 houses to rent: €4,900), with the monthly charges in their own monthlyCharges column when atHome publishes them on the list page (it did not for any of the 26 rentals measured) and atHome's own price per m² in pricePerSqm (€/m² for a sale, €/m² per month for a rental). A new-build project (5 of the 60 listings measured) carries no single price: it comes back as priceType: "sale-range" with price: null, priceMin, priceMax and the surface range. A confidential price stays null with isPriceConfidential: true — never a zero.
A project's bedroom count is not sold as one flat's bedrooms
On a project card atHome sums the bedrooms of every unit (a block with 7 or 10 "bedrooms"). This Actor returns bedroomsMin / bedroomsMax for projects and leaves bedrooms, bathrooms and floor empty rather than passing the sum off as one home. For a single home the floor comes from the card data atHome keeps in a second list on the same page (0 is the ground floor); the land is published in ares and is returned both as landAres and as landSqm (1 are = 100 m²). Flags the list page does not really carry — new-build, lift, furnished — are not returned at all, because every listing came back the same.
A place atHome does not know is reported, not silently widened
atHome answers an unknown town with HTTP 200 and 20 listings from the whole country, French border towns included. This Actor checks atHome's own resolvedLocations: when it is empty, one free no-such-search row explains how atHome spells its places instead of 20 charged listings from the wrong end of the country. searchedLocation on every row carries the place atHome actually resolved.
No agent e-mails, no phone numbers
atHome's card data carries the agency's e-mail and phone on every one of the 60 listings measured, and the named agent's e-mail and landline on 29. This Actor returns the agency name only; private sellers are not named at all; Luxembourg phone numbers and e-mail addresses written into the text are removed. Property data, not a contact list.
atHome's page is read, never executed
atHome embeds its data as a JavaScript object, not JSON. This Actor turns it into JSON by text replacement and parses it — it never evaluates atHome's code.
One request, 20 complete listings
atHome embeds every card's full data in the list page. This Actor reads all 20 from that single page and never opens individual listing pages. A listing that repeats across pages is dropped before delivery, so you are never charged twice.
Filters run here
Every filter — price, bedrooms, surface, subtype, postcode, city, energy class, projects, sold, advertiser, keywords, agency — runs on the rows already fetched. Nothing extra is requested from atHome and nothing extra is charged. A property is never dropped for a value atHome 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.athome.lu/en/buy/apartment/luxembourg. Query parameters are dropped |
channel | string | sale | sale or rent |
propertyType | string | apartment | apartment or house — atHome's words |
location | string | luxembourg | A town as atHome spells it: luxembourg, esch-sur-alzette, differdange. Every row carries the place atHome resolved it to — kirchberg, for example, is a village in Germany on atHome, not the Luxembourg district |
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 English description. The keyword filter searches it either way |
useProxy | boolean | false | Off by default — atHome answers Apify's network directly. Switches on by itself if blocked |
keywords / keywordMatch / excludeKeywords | array / string / array | — | Match on title, description, type, address, city, energy class and agency |
agencyNames | array | — | Keep only these agencies (partial match) |
minPrice / maxPrice | integer | 0 | EUR. Sale total or monthly rent; a project is kept if any part of its range fits |
requirePrice | boolean | false | Drop listings with no single published price (a range counts as none) |
minBedrooms / maxBedrooms | integer | -1 | -1 = off. An unpublished count is kept |
minSurfaceSqm / maxSurfaceSqm | integer | 0 | m². An unpublished surface is kept |
propertyTypes | array | — | Partial match: Apartment, Penthouse, Duplex, Studio, House, Apartment block … |
postalCodes / cities | array | — | Keep only these postcodes or cities (partial match on the city) |
energyClasses | array | — | A … I. An unpublished class is kept |
excludeProjects | boolean | false | Drop new-build projects that carry a price range |
excludeSold | boolean | false | Drop listings flagged sold or under agreement |
advertiserType | string | any | agency or private |
monitoringMode | boolean | false | Return only listings not returned on a previous run |
resetMonitoringState | boolean | false | One-shot: forget what was already returned |
{ "channel": "sale", "propertyType": "apartment", "location": "luxembourg", "maxListings": 100,"minBedrooms": 2, "maxPrice": 900000, "energyClasses": ["A", "B"], "excludeProjects": true }
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.
atHome does not sort by date: its list puts paid placements first, so a new listing can sit on any page. In monitoring mode this Actor therefore keeps reading — up to 60 pages, or maxPages if you set it — until it has found maxListings listings it has not returned before. A search wider than that (Luxembourg city has 131 pages of flats for sale) needs maxPages raised to be covered fully; reading pages is free, only returned listings are charged.
Measured on 2026-09-05: 2,618 flats for sale in Luxembourg city (131 pages); 24 houses to rent.
Output
One row per listing:
{"source": "athome.lu","status": "ok","listingId": "7900775","title": "Résidences Mont Carmin & Mont Ruby à Luxembou","description": "For sale - luxury apartments - Luxembourg-city …","url": "https://www.athome.lu/en/buy/new-property/apartment-block/residences-mont-carmin-mont-ruby-a-luxembou-luxembourg/id-7900775.html","searchedLocation": "Luxembourg (LU)","transactionType": "sale","propertyType": "Apartment block","propertyTypeId": "26","isProject": true,"projectUnitsLeft": 7,"price": null,"priceCurrency": "EUR","priceType": "sale-range","priceMin": 849000,"priceMax": 1249000,"isPriceConfidential": false,"monthlyCharges": null,"pricePerSqm": null,"surfaceSqm": 68.19,"surfaceMinSqm": 68.19,"surfaceMaxSqm": 93.57,"landAres": null,"landSqm": null,"bedrooms": null,"bedroomsMin": 1,"bedroomsMax": 2,"bathrooms": null,"rooms": null,"floor": null,"garages": null,"hasBalcony": false,"hasTerrace": false,"hasGarden": false,"energyClass": null,"thermalInsulationClass": null,"address": "Rue de l'Ouest","city": "Luxembourg-Belair","postalCode": "2273","country": "lu","latitude": 49.6149591,"longitude": 6.0950029,"availability": null,"isSold": false,"isUnderAgreement": false,"advertiserType": "agency","agencyName": "THOMAS & PIRON (Luxembourg)","imagesCount": 14,"mainImageUrl": "https://i1.static.athome.eu/images/annonces2/image_/76/e8/87/…_600x315.jpg","scrapedAt": "2026-09-05T09:08:56.457Z"}
Measured across 60 live listings on 2026-09-05: id, description, url, type, city, coordinates, agency and main image on 60 of 60; a surface on 59; a single price on 55 (the other 5 are project ranges); energy class on 55; price per m² on 54; a postcode on 49; bathrooms on 41.
Rows that are never charged
status | when |
|---|---|
no-results | atHome reports zero listings for this search. That is its answer, not a failure |
no-such-search | atHome does not know the place and silently widened the search to the whole country. 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 place, 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 admin, print,/search/,/recherche/,/suchen/,/myathome/, publishing and error pages. This Actor requests only/en/buy/<type>/<place>or/en/rent/<type>/<place>with?page=N.- Only public pages are read. No login, no API key.