# Hemnet Scraper \[Only $1.2/1k💰] | Slutpriser | Sweden Prices (`ahmed_jasarevic/hemnet-se-scraper`) Actor

Scrape Sweden's largest property portal hemnet.se: asking prices, sold prices (slutpriser), price per m², broker and agency data, coordinates, and images. No browser needed. Export JSON/CSV.

- **URL**: https://apify.com/ahmed\_jasarevic/hemnet-se-scraper.md
- **Developed by:** [Ahmed Jasarevic](https://apify.com/ahmed_jasarevic) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Hemnet Scraper — Swedish Property Prices & Sold Prices (Slutpriser)

Scrape hemnet.se — Sweden's largest property portal — without an official API. Extract asking prices, sold prices (slutpriser), price per m², rooms, living area, monthly fee, broker and agency, coordinates, and images from Swedish real estate listings for market analysis, valuations, and broker lead generation.

### Main Use Cases

- **Swedish property price monitoring** — track asking and sold prices across municipalities, property types, and price bands
- **Sold price analysis (slutpriser)** — compare final sale price vs asking price with `priceChangeSek` and `priceChangePercent` for valuation comps
- **Price per m² benchmarking (kr/m²)** — compare `squareMeterPriceSek` across Stockholm, Göteborg, Malmö, and every Swedish kommun
- **Broker & agency lead generation** — collect `brokerName` and `brokerAgencyName` with listing details for Swedish realtor prospecting
- **Swedish real estate market research** — build a time series of `askingPriceSek`, `finalPriceSek`, `daysOnHemnet`, and `soldAt` for trend analysis
- **Nordic proptech & housing datasets** — seed a Sweden house-price dataset with structured JSON rows for apps, dashboards, and models

### What Data Does the Hemnet Scraper Extract?

One dataset row per listing, with all fields as clean types — prices in SEK integers, areas in m², ISO 8601 timestamps, and real image URLs.

**For-sale rows include:** `askingPriceSek`, `feeSek`, `runningCostsSek`, `squareMeterPriceSek`, `numberOfRooms`, `livingAreaSqm`, `landAreaSqm`, `streetAddress`, `area`, `municipality`, `region`, `latitude`, `longitude`, `housingForm`, `tenure`, `constructionYear`, `energyClass`, `daysOnHemnet`, `brokerName`, `brokerAgencyName`, `description`, `labels`, `mainImageUrl`, `imageCount`, `imageUrls`.

**Sold rows (slutpriser) add:** `finalPriceSek`, `priceChangeSek`, `priceChangePercent`, `soldAt`.

The actor covers all Hemnet sections: **`/bostader`** (for sale), **`/salda/bostader`** (sold prices), and **`/kommande/bostader`** (upcoming) — driven by the section in your search URL or `searchMode`.

### How It Works — No Browser, Three Data Surfaces

Hemnet is a Next.js + Apollo GraphQL app fronted by Cloudflare Bot Management. Trying to render it with a headless browser does not help — the challenge is an IP-reputation problem, not a JS-rendering problem. The actor instead reads data surfaces in order of cost, cheapest first:

1. **Embedded JSON blob (primary).** Every SSR page ships `<script id="__NEXT_DATA__">` with a full Apollo cache (`__APOLLO_STATE__`) containing listing nodes and search results. Parsed directly — no browser, no DOM scraping.
2. **Internal GraphQL API (fallback).** `POST https://www.hemnet.se/graphql` serves anonymous read queries (`searchForSaleListings`, `searchSales`, `listing(id)`, `soldListing(id)`) via CSRF-token auth, reverse-engineered from the SSR cache.
3. **Static HTML / ld+json (last resort).** If both JSON surfaces are missing, rows are parsed from `application/ld+json`, OpenGraph tags, and headings.

Every row carries a `parser` field (`next-data` | `graphql` | `dom-fallback`) so you can verify which surface produced it. Requests ride the **Apify proxy** (Swedish residential recommended) with TLS fingerprinting — this is what clears the Cloudflare challenge. No login, no API key, no account.

### Find Sold Prices in Sweden (Slutpriser)

Sold-price data is the differentiator. Search `/salda/bostader` URLs or use `searchMode: "sold"` and get `finalPriceSek`, the over/under-asking gap (`priceChangeSek`, `priceChangePercent`), and `soldAt` per listing — the raw material for current-market valuations and "vad blev slutpriset?" comps.

### Build Swedish Property Datasets by Municipality

Use `locationIds` with place names (Stockholm, Göteborg, Malmö, Uppsala...) or raw Hemnet location IDs (e.g. `17744` = Stockholms län) to run full-country searches; pagination is automatic until `maxItems` or the search's result cap (~2 500) is reached. For precise filters (price band, rooms, property type) build the search on hemnet.se and paste the URL.

### Input

| Field | Type | Required | Default | Notes |
|-------|------|----------|---------|-------|
| `urls` | array of {url} | No | — | Hemnet search or listing URLs (`/bostader`, `/salda/bostader`, `/kommande/bostader`). Section is read from each URL. |
| `locationIds` | string\[] | No | `[]` | Free-text places (Stockholm, Göteborg...) or raw Hemnet location IDs (17744). Combined with `searchMode`. |
| `searchMode` | string | No | `for_sale` | `for_sale`, `sold` (slutpriser), or `upcoming`. Applies to `locationIds`. |
| `maxItems` | integer | No | `50` | Max listings saved (1–2500). Free users capped at 10. |
| `maxRequestsPerCrawl` | integer | No | `100` | Hard cap on total HTTP requests (loop safety). |
| `proxyConfiguration` | object | No | proxy on, RESIDENTIAL, SE | Keep enabled; Hemnet is Cloudflare-protected. Swedish residential recommended. |

You must supply at least one of `urls` or `locationIds`.

### Output

One dataset row per listing. Key fields:

| Field | Type | Description |
|-------|------|-------------|
| `id` | string | Stable Hemnet listing ID (use to merge runs) |
| `searchMode` | string | Section the row came from: `for_sale`, `sold`, `upcoming` |
| `url` | string | Full listing URL |
| `streetAddress` / `area` / `municipality` / `region` | string | Location hierarchy |
| `askingPriceSek` / `finalPriceSek` | number | Asking / sold price in SEK (sold rows carry final) |
| `priceChangeSek` / `priceChangePercent` | number | Over/under-asking gap (sold rows) |
| `soldAt` | string | ISO 8601 sale date (sold rows) |
| `squareMeterPriceSek` | number | kr/m² |
| `feeSek` / `runningCostsSek` | number | Monthly fee / running costs |
| `numberOfRooms` / `livingAreaSqm` / `landAreaSqm` | number | Rooms and areas |
| `housingForm` / `tenure` | string | e.g. Lägenhet, Villa / Bostadsrätt, Äganderätt |
| `constructionYear` / `energyClass` / `daysOnHemnet` | number/string | Listing details (may be null if not published) |
| `brokerName` / `brokerAgencyName` | string | Realtor and agency attribution |
| `latitude` / `longitude` | number | Coordinates |
| `description` / `labels` | string / string\[] | Text and tags |
| `mainImageUrl` / `imageCount` / `imageUrls` | string / number / string\[] | Images |
| `parser` | string | `next-data`, `graphql`, or `dom-fallback` |

### Example Input

```json
{
  "urls": [
    "https://www.hemnet.se/bostader?location_ids%5B%5D=17744&item_types%5B%5D=bostadsratt&price_max=5000000"
  ],
  "locationIds": ["Malmö"],
  "maxItems": 100,
  "proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"], "apifyProxyCountry": "SE" }
}
```

### Example Output — Sold Row (slutpriser)

```json
{
  "id": "22153011",
  "searchMode": "sold",
  "url": "https://www.hemnet.se/bostad/lagenhet-2rum-stockholms-kommun-...",
  "streetAddress": "Vasagatan 12",
  "area": "Norrmalm",
  "municipality": "Stockholms kommun",
  "askingPriceSek": 3495000,
  "finalPriceSek": 3700000,
  "priceChangeSek": 205000,
  "priceChangePercent": 5.9,
  "soldAt": "2026-09-01T00:00:00.000Z",
  "squareMeterPriceSek": 92500,
  "numberOfRooms": 2,
  "livingAreaSqm": 40,
  "feeSek": 3275,
  "brokerName": "Anna Lindqvist",
  "brokerAgencyName": "Fastighetsbyrån",
  "parser": "next-data"
}
```

### Cost of Scraping Hemnet

The actor is HTTP-only — no browser compute units. Search results are pulled from Hemnet's GraphQL endpoint in batches (50 listings per request), so cost scales with `maxItems`, not per-listing HTTP calls. Pricing is pay-per-event: **$0.0005 per actor start + $0.0012 per result row** (≈ $1.2 per 1 000 rows). A default 50-item run costs roughly $0.06. Direct listing URLs pasted in `urls` are fetched individually.

### Integrations & Automation

Every run writes to an Apify dataset:

- Download as **JSON, CSV, Excel, XML**, or **HTML**
- Push to **Google Sheets**, **Airtable**, **PostgreSQL**, **Snowflake**, or **BigQuery** via Apify integrations
- Trigger via **Zapier**, **Make**, or Apify **webhooks**
- Call from the Apify **REST API** (any language) or **Python/JS SDKs**

Because prices and sold results change constantly, schedule **daily runs** for price monitoring and **weekly runs** for market research — recurring usage also improves the actor's Apify Store ranking.

### Related Actors

- [Booli Scraper — Sweden Till salu & Slutpriser](https://apify.com/lentic_clockss/booli-scraper) — Sweden's #2 property portal, same sold-price audience
- [Nordic Real Estate Portal Scraper](https://apify.com/jungle_synthesizer/nordic-real-estate-portal-scraper) — Hemnet + Finn.no + Boligsiden + Etuovi in one run
- [Zillow Search Scraper](https://apify.com/maxcopell/zillow-scraper) — the international real-estate cluster anchor (⭐ 4.95, 600+/mo users)
- [Rightmove Scraper](https://apify.com/memo23/rightmove-scraper) — UK listings data (⭐ 5.00)
- [Idealista Scraper](https://apify.com/igolaizola/idealista-scraper) — Spanish property data (270+/mo users)

Together these cover the European property-data cluster: Swedish (Hemnet + Booli), Nordic, UK, Spain, and the international anchor.

### FAQ

#### Is there an official Hemnet API?

No public one. Hemnet's BostadsAPI is broker-only, available under signed contracts. This actor is the practical public-data alternative: it reads the same pages and endpoint a visitor sees, without login or an API key.

#### How can I get Swedish property price data when Hemnet has no official API?

Run this actor in `for_sale` or `sold` mode and export the dataset (JSON/CSV/Excel). For official sources, SCB (Statistics Sweden), Boverket, and Lantmäteriet publish aggregated market statistics — the actor gives you listing-level granularity those sources don't.

#### How do I find sold prices (slutpriser) for homes in Sweden?

Set `searchMode: "sold"` (or paste `/salda/bostader` URLs). Output rows include `finalPriceSek`, `soldAt`, and the over/under-asking gap (`priceChangeSek`, `priceChangePercent`).

#### What is the difference between asking price and final sold price on Hemnet?

`askingPriceSek` is the listing's target price (utgångspris); `finalPriceSek` is what the buyer actually paid (slutpris) — often above asking in hot markets. The gap is expressed in `priceChangeSek` and `priceChangePercent`.

#### Can I track Swedish property prices over time with a scheduled scrape?

Yes. Schedule the actor daily or weekly (Apify schedules), keep the same search URLs, and merge runs on the stable `id` field to build a price time series including `daysOnHemnet`.

#### How much does it cost to scrape Hemnet?

$0.0005 per actor start + $0.0012 per result row — roughly $1.2 per 1 000 listings (search results fetched in batches of 50). A 50-item trial run costs about $0.06.

#### Hemnet vs Booli — which is better for Swedish property data?

Hemnet is the largest portal with the most listings and broker activity; Booli aggregates and offers price statistics. Use this actor for Hemnet data and the [Booli scraper](https://apify.com/lentic_clockss/booli-scraper) for comparison coverage.

#### Is scraping Hemnet legal in Sweden?

The actor only reads publicly visible pages without login and respects request caps. You are responsible for complying with Hemnet's Terms of Service and applicable law — notably GDPR if you store `brokerName` (a person's name); agency-level data is organisational.

#### Why are some fields null?

Hemnet does not publish every field for every listing (e.g. fee on villas, coordinates on some sales, `soldAt` on for-sale rows). Nulls mean "not published" — except `dom-fallback` rows, which are partial by nature.

#### Hur hittar jag slutpriser för bostäder i Sverige?

Sök med `searchMode: "sold"` eller klistra in en `/salda/bostader`-adress. Du får `finalPriceSek`, `soldAt`, och avvikelsen mot utgångspris (`priceChangeSek`/`priceChangePercent`) per bostad.

#### Vilken bostadssajt är bäst för prisstatistik — Hemnet eller Booli?

Hemnet är den största portalen med mest data; Booli har egen statistik. Denna actor hämtar Hemnet-data, och Booli-scrapern täcker jämförelse. För officiell statistik finns SCB och Lantmäteriet.

### For AI Agents & LLM Apps

**Purpose:** Returns Swedish property listings (for sale, sold/slutpriser, or upcoming) from hemnet.se as structured JSON — one section per run.

**Minimal input:**

```json
{ "urls": [ { "url": "https://www.hemnet.se/bostader?location_ids%5B%5D=17744" } ], "maxItems": 50 }
```

**Variant inputs:**

```json
{ "locationIds": ["Malmö"], "searchMode": "sold", "maxItems": 100 }
```

```json
{ "locationIds": ["Stockholm"], "searchMode": "upcoming", "maxItems": 50 }
```

**Output fields (subset notable):** `id`, `searchMode`, `url`, `streetAddress`, `area`, `municipality`, `region`, `latitude`, `longitude`, `housingForm`, `tenure`, `askingPriceSek`, `finalPriceSek`, `priceChangeSek`, `priceChangePercent`, `soldAt`, `feeSek`, `runningCostsSek`, `squareMeterPriceSek`, `numberOfRooms`, `livingAreaSqm`, `landAreaSqm`, `constructionYear`, `energyClass`, `daysOnHemnet`, `brokerName`, `brokerAgencyName`, `description`, `labels`, `mainImageUrl`, `imageCount`, `imageUrls`, `parser`.

**Behaviors an agent should know:**

- `urls` and `locationIds` are alternative entry points; `searchMode` only applies to `locationIds` (section is read from each URL otherwise).
- Sold rows carry `finalPriceSek`/`priceChangeSek`/`priceChangePercent`/`soldAt`; for-sale rows carry `askingPriceSek` — don't expect `finalPriceSek` in `for_sale` mode.
- Free users are capped at 10 items regardless of `maxItems`; paying users get the full value (up to 2500).
- `parser` tells you the data surface used: `next-data` = clean, `graphql` = fallback, `dom-fallback` = partial rows (proxy IPs likely challenged; switch proxy group to residential).
- Fields like `feeSek`, `constructionYear`, `energyClass`, `coordinates` may be null — Hemnet doesn't publish them for every listing.
- Billing: $0.0005 per start + $0.0012 per result row ≈ $0.06 for a default 50-item run.

### Legal & Compliance Disclaimer

This actor is an independent tool and is not affiliated with, endorsed by, or sponsored by Hemnet AB. It accesses only publicly visible pages and endpoints on hemnet.se without login — no CAPTCHA solving, no private data bypass. Users are responsible for complying with Hemnet's Terms of Service and applicable law, including GDPR when storing the `brokerName` field (it is an individual's personal data).

### SEO Keywords

hemnet scraper, hemnet api, hemnet data, swedish property data, sweden property prices, hemnet slutpriser, hemnet bostadspriser, sold price monitoring sweden, price per square meter sweden, swedish real estate market analysis, swedish housing market data, brokerage lead generation sweden, hemnet export, stockholm property prices data, goteborg housing data, malmo real estate data, sweden property prices by municipality, swedish property scraper, nordic proptech, bostadsratt prices, bostader till salu data, sweden house prices dataset, real estate data sweden, hemnet alternative, kr per kvadratmeter

# Actor input Schema

## `urls` (type: `array`):

Hemnet search URLs (/bostader for sale, /salda/bostader for sold prices, /kommande/bostader for upcoming) or individual listing URLs. The section is read from each URL.

## `locationIds` (type: `array`):

Free-text locations to search listings for, e.g. Stockholm, Göteborg or Malmö. Each is resolved to a Hemnet location and its results are paginated. You can also paste raw Hemnet location IDs (e.g. 17744). Combined with Search mode below. For precise filters (price, rooms, type), build the search on hemnet.se and paste the URL under "Hemnet URLs" instead.

## `searchMode` (type: `string`):

Which Hemnet section to search when Location IDs are used.

## `maxItems` (type: `integer`):

Maximum listings to save. Free users are capped at a 10-item preview.

## `maxRequestsPerCrawl` (type: `integer`):

Hard cap on total HTTP requests for the run (loop safety).

## `proxyConfiguration` (type: `object`):

Apify proxy settings. Hemnet is Cloudflare-protected: keep enabled with Swedish residential IPs (default).

## Actor input object example

```json
{
  "urls": [
    {
      "url": "https://www.hemnet.se/bostader?location_ids%5B%5D=17744"
    }
  ],
  "locationIds": [],
  "searchMode": "for_sale",
  "maxItems": 50,
  "maxRequestsPerCrawl": 100,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "SE"
  }
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "urls": [
        {
            "url": "https://www.hemnet.se/bostader?location_ids%5B%5D=17744"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("ahmed_jasarevic/hemnet-se-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "urls": [{ "url": "https://www.hemnet.se/bostader?location_ids%5B%5D=17744" }] }

# Run the Actor and wait for it to finish
run = client.actor("ahmed_jasarevic/hemnet-se-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "urls": [
    {
      "url": "https://www.hemnet.se/bostader?location_ids%5B%5D=17744"
    }
  ]
}' |
apify call ahmed_jasarevic/hemnet-se-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,ahmed_jasarevic/hemnet-se-scraper"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/ovKZ02PuDKA9zWaml/builds/nL0PENBhv99gthKuJ/openapi.json
