Hemnet.se API & Scraper
The Hemnet API returns Swedish real-estate listings as clean JSON.
🤖 Using an AI assistant? Copy this link into ChatGPT / Claude / Cursor — it reads every endpoint and parameter instantly and tells you if this API fits your use case.
The primary search endpoint returns listings with id, URL, street address, area, housing form, asking price (SEK), fee and square meters, and you can pull sold history, a detail and a location. It is built for real-estate tools and Swedish market analytics that need Hemnet data without a scraper. One ReefAPI key, one shared credit pool, the standard envelope.
Hemnet ids, units and date formats, and how sold records differ from for-sale ones
Hemnet is a Swedish site, so the money is SEK, the areas are square metres and the labels come back in Swedish. The bigger surprise is that a sold record and a for-sale record do not share an id space, so you cannot join them on id alone. Everything below was measured on Stockholm and Malmö inventory: a search on Stockholm apartments (2,561 hits), a sold lookup on Malmö apartments (60,266 hits) and a detail call on listing 21735707.
| Field | What it actually contains | Watch out for |
|---|---|---|
| location (input) | free text resolved to Hemnet's numeric location id and echoed back as meta.location_id | measured: Stockholm resolves to 18031, Malmö to 17989, Göteborgs kommun to 17920. Pass the number directly to skip the lookup. |
| id (search) | the 8-digit for-sale listing id, also the last path segment of the url (21735707) | this is the id the detail action takes |
| id (sold) | an 18-19 digit sale id in its own namespace (5945646448150441589) | it is NOT the listing id. A separate listing_id field carries the 8-digit one, and it comes back as an empty string when Hemnet no longer links the two. |
| published_at / sold_at | unix epoch SECONDS delivered as a string with a trailing .0 ("1787780606.0") | not milliseconds and not a number. Cast to float, then to int, before you convert it. |
| asking_price / final_price / fee / square_meter_price | objects: {amount_sek, currency, formatted} | read amount_sek for arithmetic; formatted is the Swedish display string ("3 275 000 kr") |
| fee | the monthly bostadsrätt charge in SEK | search formats it "5 114 kr/mån", detail formats the same value "5 114 kr" with no suffix. Both are per month. |
| price_change (sold) | a formatted string, not a number: "±0 %", "-1 %" | compute the percentage yourself from asking_price.amount_sek and final_price.amount_sek if you need arithmetic |
| housing_form / housing_form_symbol | Swedish label plus an enum: Lägenhet/APARTMENT, Villa/HOUSE | filter on the symbol, display the label |
| rooms / living_area_m2 | floats from search (3.0, 54.0), ints from detail (3, 54) | same listing, two numeric types |
| area | null on every search row; populated on detail ("Årsta") | on search rows the neighbourhood lives in location_description ("Årsta, Stockholms kommun") instead |
| page / max_pages | 50 listings per page, max_pages 50 | meta.total can be far larger than what you can page to. Page 51 returns ok:true with count 0, not an error. |
meta.total is Hemnet's own hit count, not what you can retrieve: the Malmö sold search reported total 60266 and the window still stops at 50 pages / 2500 rows. Narrow with price, area, rooms or home_type rather than paging deeper.
Real request and response JSON
Captured from the indexed primary action, search, on .
{
"method": "POST",
"url": "https://api.reefapi.com/hemnet/v1/search",
"headers": {
"x-api-key": "$REEF_KEY",
"content-type": "application/json"
},
"body": {
"location": "Stockholm"
}
}{
"ok": true,
"meta": {
"api": "hemnet",
"endpoint": "search",
"mode": "live",
"latency_ms": 20672.7,
"record_count": 50,
"bytes": 1580495,
"cache_hit": false,
"stop_reason": "limit_reached",
"locale": "sv-SE",
"currency": "SEK",
"total": 2596,
"count": 50,
"page": 1,
"max_pages": 50,
"location_id": "18031",
"filters_applied": {},
"charged_credits": 1,
"version": "1.0.0"
},
"data": {
"results": [
{
"id": "21730662",
"url": "https://www.hemnet.se/bostad/lagenhet-2rum-alvsjo-stockholms-kommun-alvsjovagen-28,-van-3-21730662",
"street_address": "Älvsjövägen 28, vån 3",
"area": null,
"location_description": "Älvsjö, Stockholms kommun",
"housing_form": "Lägenhet",
"housing_form_symbol": "APARTMENT",
"asking_price": {
"amount_sek": 2795000,
"currency": "SEK",
"formatted": "2 795 000 kr"
},
"fee": {
"amount_sek": 3050,
"currency": "SEK",
"formatted": "3 050 kr/mån"
},
"square_meter_price": {
"amount_sek": 68171,
"currency": "SEK",
"formatted": "68 171 kr/m²"
},
"rooms": 2,
"living_area_m2": 41,
"living_and_supplemental_areas": "41 m²",
"land_area_m2": null,
"floor": "vån 3/6",
"new_construction": false,
"is_foreclosure": null,
"published_at": "1790194977.0",
"labels": [
"Mån 28 sep kl 17:15",
"Premium",
"Balkong"
],
"latitude": 59.28182,
"longitude": 17.9986935,
"broker_agency": "Svensk Nyproduktion (Svenska Mäklarhuset)",
"primary_photo_url": "https://bilder.hemnet.se/images/itemgallery_cut/d5/e2/d5e20b5c7e6841f1511ed3c74ceed20c.jpg",
"photos": [
"https://bilder.hemnet.se/images/itemgallery_cut/d5/e2/d5e20b5c7e6841f1511ed3c74ceed20c.jpg",
"https://bilder.hemnet.se/images/itemgallery_cut/ec/9e/ec9e86e34a047d813acfca996a23894c.jpg",
"https://bilder.hemnet.se/images/itemgallery_cut/32/37/3237cf0f015fb6d219109b1dfb971713.jpg"
]
},
{
"id": "21674702",
"url": "https://www.hemnet.se/bostad/lagenhet-2rum-bromma-traneberg-stockholms-kommun-tranebergsvagen-24-21674702",
"street_address": "Tranebergsvägen 24",
"area": null,
"location_description": "Bromma - Traneberg, Stockholms kommun",
"housing_form": "Lägenhet",
"housing_form_symbol": "APARTMENT",
"asking_price": {
"amount_sek": 2600000,
"currency": "SEK",
"formatted": "2 600 000 kr"
},
"fee": {
"amount_sek": 4023,
"currency": "SEK",
"formatted": "4 023 kr/mån"
},
"square_meter_price": {
"amount_sek": 54167,
"currency": "SEK",
"formatted": "54 167 kr/m²"
},
"rooms": 2,
"living_area_m2": 48,
"living_and_supplemental_areas": "48 m²",
"land_area_m2": null,
"floor": "vån 1/4",
"new_construction": false,
"is_foreclosure": null,
"published_at": "1790194346.0",
"labels": [
"Sön 27 sep kl 14:00",
"Premium"
],
"latitude": 59.3338661,
"longitude": 17.98592,
"broker_agency": "Bjurfors Bromma",
"primary_photo_url": "https://bilder.hemnet.se/images/itemgallery_cut/41/d7/41d71c64c16469bd4b17f2ae01062bd6.jpg",
"photos": [
"https://bilder.hemnet.se/images/itemgallery_cut/41/d7/41d71c64c16469bd4b17f2ae01062bd6.jpg",
"https://bilder.hemnet.se/images/itemgallery_cut/05/eb/05eb96e5636b32ea7ec2b32b248935f6.jpg",
"https://bilder.hemnet.se/images/itemgallery_cut/cf/7b/cf7b76cfdca696e37ad571d0ea99532a.jpg"
]
},
{
"id": "21793097",
"url": "https://www.hemnet.se/bostad/lagenhet-2rum-liljeholmskajen-stockholms-kommun-argangsgatan-1-21793097",
"street_address": "Årgångsgatan 1",
"area": null,
"location_description": "Liljeholmskajen, Stockholms kommun",
"housing_form": "Lägenhet",
"housing_form_symbol": "APARTMENT",
"asking_price": {
"amount_sek": 5995000,
"currency": "SEK",
"formatted": "5 995 000 kr"
},
"fee": {
"amount_sek": 4645,
"currency": "SEK",
"formatted": "4 645 kr/mån"
},
"square_meter_price": {
"amount_sek": 89478,
"currency": "SEK",
"formatted": "89 478 kr/m²"
},
"rooms": 2,
"living_area_m2": 67,
"living_and_supplemental_areas": "67 m²",
"land_area_m2": null,
"floor": "vån 9/23",
"new_construction": false,
"is_foreclosure": null,
"published_at": "1790192940.0",
"labels": [
"Sön 4 okt kl 13:00",
"Premium",
"Balkong"
],
"latitude": 59.306399,
"longitude": 18.0340794,
"broker_agency": "Mäklarhuset Liljeholmen",
"primary_photo_url": "https://bilder.hemnet.se/images/itemgallery_cut/dc/03/dc03d6331d628d1069e0e12b427dc99e.jpg",
"photos": [
"https://bilder.hemnet.se/images/itemgallery_cut/dc/03/dc03d6331d628d1069e0e12b427dc99e.jpg",
"https://bilder.hemnet.se/images/itemgallery_cut/fb/ca/fbca96deafd30c675ad9ccf52650c356.jpg",
"https://bilder.hemnet.se/images/itemgallery_cut/47/10/4710c7621c00adfc41fcbf532d9327dd.jpg"
]
}
],
"total": 2596,
"count": 50,
"page": 1,
"max_pages": 50,
"location": {
"query": "Stockholm",
"id": "18031",
"name": "Stockholms kommun",
"type": "MUNICIPALITY",
"matched": true
},
"filters_applied": {}
}
}What the Hemnet.se API does
| Action | Description | Concrete use case | Key params |
|---|---|---|---|
| search | Search Hemnet.se for-sale property listings by location, with structured filters: price (SEK), rooms, living area (m²), plot, property type, price-per-m², construction year, keyword and sort. Each result carries asking price, fee, square-metre price, rooms, living area, housing form, coordinates, broker agency, address and photos. Paginate with page. | Real-estate investors call search to search Hemnet.se for-sale property listings by location, with structured filters. | location, home_type, sort, page, price_min, ... |
| sold | Recently-SOLD property prices (slutpriser) by location, with the same filters as search — the comparable-sales / price-history surface. Each record carries asking price, FINAL sold price, sold date, price change (%) and square-metre price. | Brokerage tools call sold to get recently-SOLD property prices (slutpriser) by location, with the same filters as search. | location, home_type, sort, page, price_min, ... |
| detail | Full record for a single listing by its Hemnet listing URL, slug or id (hemnet.se/bostad/<slug>). Returns asking price, fee, rooms, living & plot area, construction year, energy class, tenure, the full description, every photo, amenities, days-on-market, view count and any sale history. | Property dashboards call detail to get full record for a single listing by its Hemnet listing URL, slug or id (hemnet.se/bostad/<slug>). | url |
| location | Location resolver / autocomplete — map a free-text Swedish place name to Hemnet locations (city, municipality, county, district, postal area) with their ids. Use it to power a search box or to confirm the exact location a search will use. | Lead-generation teams call location to get location resolver / autocomplete. | query |
Call search from your stack
curl -X POST https://api.reefapi.com/hemnet/v1/search \
-H "x-api-key: $REEF_KEY" \
-H "content-type: application/json" \
-d '{"location":"Stockholm"}'import requests
r = requests.post(
"https://api.reefapi.com/hemnet/v1/search",
headers={"x-api-key": REEF_KEY},
json={
"location": "Stockholm"
},
)
print(r.json()["data"])const res = await fetch("https://api.reefapi.com/hemnet/v1/search", {
method: "POST",
headers: {
"x-api-key": process.env.REEF_KEY,
"content-type": "application/json",
},
body: JSON.stringify({
"location": "Stockholm"
}),
});
const { ok, data, meta, error } = await res.json();Ask your MCP-connected assistant: call reefapi.hemnet.search with {"location":"Stockholm"}.Who uses this API and why
- Investors call search and sold to compare asking and sold prices.
- Dashboards use detail and fee to enrich a listing.
- Analysts use location and sold to track Swedish market trends.
Questions developers ask before integrating
Which action gives me the price a property actually sold for?
The sold action. search returns properties currently on the market and its price field is the asking price (utgångspris) only. sold returns slutpriser and carries both: asking_price and final_price, plus price_change as a display string. A measured Malmö apartment sold at 1,475,000 SEK against a 1,495,000 SEK asking price, reported as "-1 %".
Why is area null on every search result?
Because the search listing card does not publish a separate neighbourhood field. The value is there, it is just in location_description instead, formatted as neighbourhood plus municipality ("Årsta, Stockholms kommun"). Measured on 50 Stockholm apartment rows and 50 Stockholm villa rows: area was null on all 100. The detail action does fill area ("Årsta") and adds post_code, so call detail when you need the field split out.
The listing ids from sold do not match anything from search. Why?
They are different id spaces. A for-sale listing is an 8-digit id (21735707) under /bostad/; a sold record is an 18-19 digit sale id (5945646448150441589) under /salda/. Sold rows carry a listing_id field that holds the original 8-digit id when Hemnet still links them, but it is an empty string on plenty of records, so do not build a pipeline that assumes the join always resolves.
days_on_hemnet and times_viewed came back 0. Is the detail action broken?
No, those are real zeros for a listing that has just gone up. A listing published two days before the call returned days_on_hemnet 0 and times_viewed 0; an older Stockholm villa returned 124 days and 18,166 views on the same fields in the same kind of call. Zero means new here, not missing.
What does fee mean, and do houses have one?
fee is the monthly avgift a bostadsrätt owner pays the housing association, in SEK. It is the number Swedish buyers compare almost as closely as the price, which is why the sort enum includes fee_low. Freehold properties (tenure Äganderätt, typically villa and radhus) have no association charge. land_area_m2 works the other way round: null on every apartment measured, 613.0 on the villa.
How deep can I page, and why is total so much bigger?
50 listings per page and 50 pages, so 2,500 rows is the ceiling. meta.total reports Hemnet's own hit count, which was 60,266 on the Malmö sold search, and meta.max_pages tells you the real limit in the same response. Asking for page 51 returns ok:true with count 0 rather than an error, so check count rather than assuming a 200 means rows. To get past 2,500, split the query by price band, room count or a narrower location id.
Can I search by municipality or only by city?
Both, plus county and district. The location action shows what a free-text string will resolve to: "Göteborg" returned 10 suggestions typed MUNICIPALITY (Göteborgs kommun, id 17920) and DISTRICT (Göteborg - Innerstaden, Göteborg - Östra and so on), with the municipality picked as resolved. Call location first when you want to be sure which id a search will use, or pass a numeric id straight to search.
What is the Hemnet.se API?
Hemnet.se API is a ReefAPI endpoint group for hemnet.se It returns live JSON through POST requests under /hemnet/v1.
Is the Hemnet.se API free to try?
Yes. ReefAPI starts with 1,000 free credits, no card required. Hemnet.se calls use the same shared credit balance as every other ReefAPI engine.
Do I need a Hemnet.se login or account?
No login to Hemnet.se is needed for the API response. You call ReefAPI with your x-api-key header, and the playground can run live examples before you create a production key.
How fresh is the Hemnet.se data?
The page example is captured from a live search call, and production requests fetch live data through ReefAPI rather than a static sample.
How many credits does the Hemnet.se API use?
Hemnet.se actions currently cost 1 credit per successful call. Failed or blocked calls are free. All APIs draw from one credit pool.
Can I call Hemnet.se from an AI assistant or MCP client?
Yes. Connect ReefAPI once through MCP and your assistant can call hemnet actions with the same key, credit pool and JSON envelope used by normal REST requests.
Is the Hemnet.se API a Hemnet.se scraper?
It is the managed alternative to a DIY Hemnet.se scraper. Instead of building and maintaining your own scraper — proxies, headless browsers, captcha and constant breakage — you call one ReefAPI endpoint and get the same hemnet.se back as clean JSON.