# Boligsiden Scraper - Denmark Property, Sold Prices & Agents (`sian.agency/boligsiden-property-scraper`) Actor

Scrape boligsiden.dk: boliger til salg, salgspriser, lejeboliger and every Danish ejendomsmaegler. Price, m2-pris, ejerudgift, energimaerke, BBR data and full agency contacts.

- **URL**: https://apify.com/sian.agency/boligsiden-property-scraper.md
- **Developed by:** [SIÁN OÜ](https://apify.com/sian.agency) (community)
- **Categories:** Real estate, Lead generation, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.32 / 1,000 homes for sales

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## Boligsiden Scraper — Danish Property, Salgspriser & Estate Agents 🚀

[![Store-SIÁN Agency](https://img.shields.io/badge/Store-SI%C3%81N%20Agency-1AE392)](https://apify.com/sian.agency?fpr=sian) [![Store-Hemnet Sweden](https://img.shields.io/badge/Store-Hemnet%20Sweden-DA0060)](https://apify.com/sian.agency/hemnet-property-scraper?fpr=sian) [![Store-FINN.no Norway](https://img.shields.io/badge/Store-FINN.no%20Norway-0063FB)](https://apify.com/sian.agency/finn-no-property-scraper?fpr=sian) [![Store-Idealista](https://img.shields.io/badge/Store-Idealista-E60023)](https://apify.com/sian.agency/smart-idealista-scraper?fpr=sian)

#### 🎉 Every listing arrives with the estate agency selling it — email, direct phone, CVR number and customer ratings

##### Four modes over one Danish place name: boliger til salg · salgspriser · lejeboliger · ejendomsmæglere

### 🔍 What is the Boligsiden Scraper — and when should you use it?

The **Boligsiden Scraper** turns a Danish place name into clean, structured rows you can filter, export and feed straight into a spreadsheet, database or AI agent. Type "Aarhus", "8000" or "Østjylland". No account, no portal key, no browser automation to maintain.

**Use it when you need:** Danish homes for sale, with price, m²-pris, ejerudgift and days listed. The salgspriser register, with the amount, the date and the sale type. Lejeboliger, where rent and deposit are separate numbers. The BBR building record. And on every listing, the estate agency selling it: email, direct phone, CVR number, ratings, local market share.

**Use something else when:** you want a different Nordic country. [Hemnet Scraper](https://apify.com/sian.agency/hemnet-property-scraper?fpr=sian) covers Sweden and its slutpriser archive; [FINN.no Scraper](https://apify.com/sian.agency/finn-no-property-scraper?fpr=sian) covers Norway. This one reads Boligsiden, which is where the Danish broker chains publish, so it does not cover for-sale-by-owner sites or an individual chain's own portal.

### 🔎 What is the Boligsiden Scraper — and when should you use it?

The **Boligsiden Scraper** turns any Danish place name on Boligsiden, Denmark's largest housing portal into clean, structured rows you can filter, export and feed straight into a spreadsheet, database or AI agent. No account, no portal API key, no browser automation to maintain.

**Use it when you need:** Danish homes for sale with the asking price in kroner, the kvadratmeterpris, the ejerudgift and how many days the listing has been up. The salgspriser register returns what a home actually sold for, with the date, the price per square metre and whether it was a normal sale, a family transfer or an auction. Rentals return monthly rent, deposit, prepaid rent and utilities as four separate numbers, plus the date the home is free. Every row carries the BBR building record: year built, wall and roof material, heating installation and the recorded state of the kitchen and bathroom. And on every for-sale and rental listing, the estate agency selling it, with its office email, direct phone, CVR company number, customer ratings and its share of local sales.

**Use something else when:** the property is outside Denmark. Use [Hemnet Scraper](https://apify.com/sian.agency/hemnet-property-scraper?fpr=sian) for Sweden, including its slutpriser sold-price archive. Use [FINN.no Scraper](https://apify.com/sian.agency/finn-no-property-scraper?fpr=sian) for Norway's dominant marketplace, for sale and to rent. Use [Smart Idealista Scraper](https://apify.com/sian.agency/smart-idealista-scraper?fpr=sian) for Spain, Italy and Portugal. This actor reads Boligsiden, which is where the Danish broker chains publish, so it does not cover for-sale-by-owner sites or a single chain's own portal. One search reaches 10,000 rows and no further; that ceiling is Boligsiden's own, and a national dataset is built by splitting the run across kommuner, price bands or sold periods. Sold rows come from the public sale register, which records the transaction and not who brokered it, so the agency columns are empty on that mode by construction. The agency directory is at office level: the agency, its CVR and its office contacts, never an individual maegler's personal mobile.

### 🤖 Use with AI agents

Already connected to the [Apify MCP server](https://mcp.apify.com)? Just ask for this Actor by name: sian.agency/boligsiden-property-scraper

**Your agent can pay for its own runs.** This Actor is eligible for [agentic payments](https://docs.apify.com/platform/actors/publishing/monetize), so an agent can discover it, run it and settle the bill over [x402](https://www.x402.org/) (USDC on Base) or [Skyfire](https://www.skyfire.xyz/) — without an Apify account or API token of its own. Billing is the same either way: per successful row, never for errors.

Otherwise copy this prompt into Claude, ChatGPT, Cursor or any MCP-enabled assistant:

```text
I want to research the Danish housing market, its sold prices and the estate agencies working in it using the Apify Actor `sian.agency/boligsiden-property-scraper`.

Use it when I need: Danish homes for sale with the asking price in kroner, the kvadratmeterpris, the ejerudgift and how many days the listing has been up. The salgspriser register returns what a home actually sold for, with the date, the price per square metre and whether it was a normal sale, a family transfer or an auction. Rentals return monthly rent, deposit, prepaid rent and utilities as four separate numbers, plus the date the home is free. Every row carries the BBR building record: year built, wall and roof material, heating installation and the recorded state of the kitchen and bathroom. And on every for-sale and rental listing, the estate agency selling it, with its office email, direct phone, CVR company number, customer ratings and its share of local sales.

Don't use it when: the property is outside Denmark — use hemnet-property-scraper or finn-no-property-scraper or smart-idealista-scraper instead.

How to call it: pick one `operation` per run. `search` returns homes for sale, `sold` returns the salgspriser register, `rentals` returns lejeboliger and `agents` returns the estate-agency directory. Then give `location` a Danish place written the way Boligsiden writes it: a kommune such as `Aarhus`, `Odense` or `Koebenhavn`, a by such as `Aarhus C`, a postcode such as `8000`, or a landsdel such as `Oestjylland`. Danish letters are optional. Narrow it with `propertyTypes` (`villa`, `condo`, `terraced house`, `cooperative`, `holiday house` and 18 more), a `priceMin`/`priceMax` band in kroner, `areaMin`/`areaMax` in square metres, or `energyLabels` from `A2020` down to `G`..

Start with this input:
{
  "operation": "search",
  "location": "Aarhus",
  "propertyTypes": [
    "villa"
  ],
  "priceMax": 5000000,
  "maxResults": 100
}

Ask me which Danish place they mean, whether they want homes for sale, sold prices, rentals or estate agencies, and what they intend to do with the rows, then run the Actor and summarise the results as a table.
```

**Things you can ask your agent for:**

- *Which estate agencies sell the most villas in Aarhus, and what are their office phone numbers and CVR numbers?*
- *Pull every villa sold in Odense over the last twelve months, normal sales only, and give me the median price per square metre by postcode.*
- *Find rentals in 8000 under 12,000 kroner a month, and tell me the deposit and the prepaid rent on each one.*
- *Screen Nordjylland for villaer built before 1980 with an energy label of E or worse, and list the ones still heated by oil.*

Machine-readable API, MCP config and OpenAPI definition for this Actor are published at [apify.com/sian.agency/boligsiden-property-scraper.md](https://apify.com/sian.agency/boligsiden-property-scraper.md).

### 📋 Overview

**Denmark's property data, in four modes, from one place name.** Boligsiden is Denmark's largest housing portal: 673,000 people search for it by name every month. This Actor reads its for-sale listings, its sold-price register, its rental market and its agency directory into flat rows.

**What you get:**

- ✅ **The agency comes with the listing**: name, chain, email, direct phone, CVR number, customer ratings and its share of local sales, on every for-sale and rental row
- ⚡ **250 rows per request**: a whole kommune is a handful of calls, not hundreds
- 🎯 **94 fields per row**, including the full BBR building record and the municipality's own tax rates
- 💰 **From $1.50 per 1,000 rows** — no subscription, no minimum, no proxy bill hiding underneath
- 💎 **Salgspriser as a first-class mode**: the amount, the date and whether it was a normal sale, a family transfer or an auction
- ✨ **NEW**: an estate-agency directory as its own mode, with the CVR number that joins each office to its filed accounts

### ✨ Features

- 🏠 **Homes for sale**: every active listing in a place, filtered by price, size, rooms, plot, year built, energy label and monthly cost
- 💰 **Salgspriser register**: what Danish homes actually sold for, with the sale type separated so family transfers never pollute your comparables
- 🔑 **Rentals**: rent, deposit, prepaid rent and utilities as four distinct numbers, plus the date the home is free
- 🧑‍💼 **Estate-agency directory**: every ejendomsmægler in a kommune with email, phone, CVR, headcount, ratings and local market share
- 📍 **Place names, not codes**: "Aarhus", "Aarhus C", "8000" and "Østjylland" all resolve against Boligsiden's own index
- 🧱 **BBR building record**: year built, wall material, roof material, heating installation, and the recorded state of the kitchen and bathroom
- 🗂️ **Sale history on every address**: every past registration with amount, date and price per m², newest first
- 🏛️ **Municipal tax rates**: kommuneskat, kirkeskat and grundskyld, joined to the row
- 🚪 **Open-house filter**: keep only the homes with an aabent hus scheduled, and get the date and sign-up link
- 📉 **Price-drop filter**: keep only the listings whose asking price has come down, with the percentage on the row

### 🎬 Quick Start

Pick a mode, name a Danish place, press Start. The place is matched against Boligsiden's own index, so a kommune, a by, a postcode or a landsdel all work. Rows land in your dataset as JSON, CSV or Excel.

```bash
curl -X POST "https://api.apify.com/v2/acts/sian.agency~boligsiden-property-scraper/runs?token=YOUR_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"operation": "search", "location": "Aarhus", "propertyTypes": ["villa"], "maxResults": 100}'
```

### 🚀 Getting Started (3 Simple Steps)

#### Step 1: Pick a mode

Choose **Homes for Sale**, **Sold Prices**, **Rentals** or **Estate Agents** in the first field.

#### Step 2: Name a place in Denmark

Type it the way you would on Boligsiden — Aarhus, Aarhus C, 8000 or Østjylland.

#### Step 3: Narrow it and run

Set a price band, a size, a property type or an energy label if you want, then press Start.

**That's it. In about a minute you'll have:**

- A table of Danish homes, sales, rentals or agencies with 94 possible columns
- The estate agency behind every listing, with its direct contact details
- A JSON, CSV or Excel export ready for a model, a map or a CRM

### 📥 Input Configuration

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `operation` | string | No | `search`, `sold`, `rentals` or `agents`. Defaults to `search`. |
| `location` | string | No | A Danish kommune, by, postcode or landsdel. Defaults to Aarhus. |
| `areaLevel` | string | No | Pin the match to `municipality`, `city`, `zip_code` or `province`. Defaults to best match. |
| `locations` | array | No | Extra places to cover in the same run, one per line. |
| `propertyTypes` | array | No | `villa`, `condo`, `terraced house`, `cooperative`, `holiday house` and 18 more. |
| `maxResults` | integer | No | Row limit for the whole run. Up to 10,000. |
| `priceMin` / `priceMax` | integer | No | Price band in DKK. On Rentals these are read as monthly rent. |
| `roomsMin` / `roomsMax` | integer | No | Number of vaerelser. |
| `areaMin` / `areaMax` | integer | No | Living area in m². |
| `lotAreaMin` | integer | No | Minimum plot area in m². Homes for Sale only. |
| `yearBuiltFrom` | integer | No | Skip anything built before this year. Homes for Sale only. |
| `energyLabels` | array | No | `A2020`, `A2015`, `A2010`, `A1`, `A2`, `A`, `B`…`G`. Homes for Sale only. |
| `monthlyExpenseMax` | integer | No | Maximum ejerudgift per month. Homes for Sale only. |
| `onlyOpenHouse` | boolean | No | Keep only listings with an aabent hus scheduled. |
| `onlyPriceDrop` | boolean | No | Keep only listings whose asking price has come down. |
| `soldMonthsBack` | string | No | `3`, `6`, `12`, `24`, `60` or `all`. Sold Prices only. |
| `saleTypes` | array | No | `normal`, `family`, `auction`, `other`. Sold Prices only. |
| `sortBy` | string | No | `newest`, `priceLowToHigh`, `priceHighToLow`, `largestFirst`, `sqmPriceLowToHigh`. |
| `agentAddressType` | string | No | Which property type the agency's local market share is measured on. |

**Example:**

```json
{
  "operation": "search",
  "location": "Aarhus",
  "propertyTypes": ["villa"],
  "priceMax": 5000000,
  "maxResults": 100
}
```

**Several places in one run:**

```json
{
  "operation": "sold",
  "location": "Aarhus",
  "locations": ["Odense", "Aalborg", "Esbjerg"],
  "soldMonthsBack": "12",
  "saleTypes": ["normal"],
  "maxResults": 2000
}
```

### 📤 Output

Results are saved to the Apify dataset with **94 fields**, grouped into a view per mode. The most useful:

| Field | Type | Description |
|-------|------|-------------|
| `propertyUrl` | string | The listing's page on Boligsiden |
| `streetAddress` | string | Road name and house number |
| `price` | integer | Asking price in DKK |
| `pricePerSqm` | integer | Kvadratmeterpris in DKK |
| `monthlyOwnerExpense` | integer | Ejerudgift per month |
| `soldPrice` / `soldDate` | integer / date | What it sold for, and when |
| `saleType` | string | `normal`, `family`, `auction` or `other` |
| `monthlyRent` / `deposit` | integer | Rent and deposit, as two separate numbers |
| `housingArea` / `lotArea` | integer | Boligareal and grundareal in m² |
| `energyLabel` | string | Energimærke, from A2020 to G |
| `yearBuilt` | integer | From the BBR building record |
| `heatingInstallation` | string | District heating, heat pump, oil, gas — from BBR |
| `agentName` / `agentChain` | string | The selling agency and its chain |
| `agentEmail` / `agentPhone` | string | The office's own address and direct line |
| `agentCvr` | string | Danish company register number |
| `agentSellerRating` | number | Boligsiden's own seller satisfaction score |
| `agentLocalSalesShare` | number | The agency's share of sales in that place |
| `saleHistory` | array | Every registered sale on the address, newest first |
| `imageUrls` / `imageCount` | array / integer | Up to 5 preview photos; the search feed caps them at five per listing |
| `councilTaxPercentage` | number | Kommuneskat for the municipality |
| `latitude` / `longitude` | number | Coordinates |

**Example:**

```json
{
  "propertyUrl": "https://www.boligsiden.dk/adresse/holme-parkvej-252-8270-hoejbjerg-07513375_252_______",
  "propertyTitle": "Fuldmuret kvalitetsvilla med moderne komfort",
  "streetAddress": "Holme Parkvej 252",
  "zipCode": 8270,
  "cityName": "Højbjerg",
  "municipality": "Aarhus",
  "province": "Østjylland",
  "price": 7795000,
  "pricePerSqm": 41243,
  "monthlyOwnerExpense": 4338,
  "currency": "DKK",
  "propertyType": "villa",
  "housingArea": 184,
  "lotArea": 958,
  "numberOfRooms": 6,
  "yearBuilt": 2006,
  "energyLabel": "C",
  "heatingInstallation": "Fjernvarme/blokvarme",
  "roofingMaterial": "Betontagsten",
  "publicValuation": 3800000,
  "saleHistory": [{ "date": "2019-02-13", "amount": 4900000, "type": "normal", "perAreaPrice": 25926 }],
  "agentName": "home Højbjerg",
  "agentChain": "home",
  "agentEmail": "hoejbjerg@home.dk",
  "agentPhone": "86277170",
  "agentCvr": "41366338",
  "agentSellerRating": 9.21,
  "agentLocalSalesShare": 87.1,
  "daysListed": 2,
  "_operation": "search"
}
```

### 💼 Use Cases & Examples

#### 1. Estate-agency lead generation

**Sales teams selling to Danish brokers — CRM vendors, photographers, staging firms, portals.**

**Input:** `operation: agents`, a kommune or landsdel
**Output:** every agency there with email, direct phone, CVR number, headcount, ratings and local market share
**Use:** a prospect list you can rank by how much business each office actually does, with a company number that joins straight to their filed accounts

#### 2. Salgspriser analysis and valuation

**Valuers, banks and proptech teams building Danish comparables.**

**Input:** `operation: sold`, a kommune, `saleTypes: ["normal"]`, a 12-month window
**Output:** every registered sale with amount, date, price per m² and the BBR record of the property
**Use:** a comparable set that is not polluted by family transfers or forced auctions

#### 3. Housing-market monitoring

**Analysts and journalists tracking a local market week by week.**

**Input:** `operation: search`, a kommune, `sortBy: newest`, on a schedule
**Output:** what is new since the last run, with price, m²-pris, ejerudgift and days listed
**Use:** a running feed of supply and asking-price movement, next to the sold register for what actually cleared

#### 4. Energy-retrofit and renovation targeting

**Heat-pump installers, insulation firms and energy consultants.**

**Input:** `operation: search`, `energyLabels: ["E","F","G"]`, `propertyTypes: ["villa"]`
**Output:** rows carrying year built, wall material, roof material and heating installation from BBR
**Use:** a list of oil-heated houses with a poor label, in a specific kommune, ready to route to a field team

#### 5. Rental-market research

**Build-to-rent operators, relocation firms and housing researchers.**

**Input:** `operation: rentals`, a kommune, a rent band
**Output:** rent, deposit, prepaid rent, utilities and availability date as separate fields
**Use:** honest rent benchmarking, where the deposit is never mistaken for the monthly price

#### 6. Proptech and portal data feeds

**Teams building a Danish valuation model, map or comparison site.**

**Input:** any mode, several kommuner via `locations`
**Output:** flat rows with coordinates, area, tenure, tax rates and price history
**Use:** a feed that drops into a model or a database without a parsing layer of your own

#### 7. Chain and market-share benchmarking

**Franchise heads and M\&A teams comparing broker networks.**

**Input:** `operation: agents`, several kommuner, `agentAddressType` set to a segment
**Output:** every office with its chain, its rating and its share of local sales in that segment
**Use:** a map of who is strong where, by property type, across Denmark

### 🔗 Integration Examples

#### JavaScript/Node.js

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });

const run = await client.actor('sian.agency/boligsiden-property-scraper').call({
  operation: 'search',
  location: 'Aarhus',
  propertyTypes: ['villa'],
  maxResults: 100,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0]);
```

#### Python

```python
from apify_client import ApifyClient
client = ApifyClient('YOUR_TOKEN')

run = client.actor('sian.agency/boligsiden-property-scraper').call(
    run_input={
        'operation': 'sold',
        'location': 'Odense',
        'soldMonthsBack': '12',
        'saleTypes': ['normal'],
        'maxResults': 500,
    }
)

for item in client.dataset(run['defaultDatasetId']).iterate_items():
    print(item['streetAddress'], item['soldPrice'], item['soldDate'])
```

#### cURL

```bash
curl -X POST 'https://api.apify.com/v2/acts/sian.agency~boligsiden-property-scraper/runs?token=YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"operation": "agents", "location": "Aarhus", "agentAddressType": "villa"}'
```

#### Automation Workflows (N8N / Zapier / Make)

1. **Trigger**: a schedule, or a webhook from your own system
2. **HTTP Request**: call the Actor's run endpoint with the input above
3. **Process**: read the dataset items as JSON
4. **Action**: write new listings to a sheet, push agencies into a CRM, or alert on a price drop

### 📊 Performance & Pricing

#### FREE Tier (Try It Now)

- **25 rows** per run — every field, every mode, same quality
- No credit card required
- Enough to see the agency block, the BBR record and the sale history before you commit

#### PAID Tier (Production Ready)

- **Up to 10,000 rows** per search, across as many places as you like
- 250 rows per request, so a kommune finishes in seconds
- Pay per result: you are charged for rows returned, never for a place that matched nothing

💰 **From $1.50 per 1,000 homes.** You pay per row, so a single kommune costs cents and there is no monthly subscription to carry.

🔗 [View current pricing](https://apify.com/sian.agency/boligsiden-property-scraper?fpr=sian)

### ❓ Frequently Asked Questions

**Q: Do I need an API key, a login or a proxy?**
A: No. Name a Danish place and press Start.

**Q: How many rows can I get?**
A: FREE tier: 25 per run. PAID tier: up to 10,000 per search. That ceiling is Boligsiden's own. To go wider, split the run by kommune, price band or sold period.

**Q: What is salgspriser, and does this return it?**
A: Salgspriser is Denmark's register of what homes actually sold for. The Sold Prices mode returns the amount, the date, the price per m² and the sale type, going back through the whole register.

**Q: Does every row really carry the estate agency?**
A: Every for-sale and rental row does. Sold rows come from the public register, which records the transaction and not who brokered it, so the agency columns are empty there by construction.

**Q: What is a CVR number and why is it on an agency row?**
A: CVR is Denmark's public company register number. It joins an agency to its filed accounts, its ownership and its VAT status, which is what turns a name and a phone number into something a sales or diligence process can use.

**Q: Are rent and deposit separate?**
A: Yes. Monthly rent, deposit, prepaid rent and utilities are four distinct fields, plus the date the home is free. Danish adverts headline the deposit as often as the rent, so collapsing them into one price column is how rental datasets go wrong.

**Q: Which fields come from BBR?**
A: Year built, wall material, roof material, heating installation, floors, and the recorded state of the kitchen, bathroom and toilet. BBR is Denmark's national building register, joined to the listing for you.

**Q: What output formats are available?**
A: JSON, CSV, Excel and XML — export straight from the Apify dataset.

### 🐛 Troubleshooting

**"No Danish place matched…"**

- Use the place as Boligsiden spells it: a kommune (Aarhus), a by (Aarhus C), a postcode (8000) or a landsdel (Østjylland)
- Danish letters are optional — Oestjylland and Østjylland both work
- Very small villages may not be indexed; use the kommune instead

**"Nothing matched these filters"**

- Widen the price band, the living area or the property types
- Set **Match the place as** to Kommune for a wider catchment
- Some filters only apply to Homes for Sale — the run log names any that were skipped

**Fewer rows than you asked for**

- Boligsiden will not page past 10,000 rows in one search. Split the run by kommune, price band or sold period
- On the FREE tier every run stops at 25 rows

**An agency has no rating**

- Boligsiden publishes a score only once enough customers have answered. The review count is on the row either way

### ⚖️ Is it legal to scrape data?

Our actors are ethical and do not extract any private user data, such as email addresses, gender, or location. They only extract what the user has chosen to share publicly. We therefore believe that our actors, when used for ethical purposes by Apify users, are safe.

However, you should be aware that your results could contain personal data. Personal data is protected by the **GDPR** in the European Union and by other regulations around the world. You should not scrape personal data unless you have a legitimate reason to do so. If you're unsure whether your reason is legitimate, consult your lawyers.

You can also read Apify's blog post on the [legality of web scraping](https://blog.apify.com/is-web-scraping-legal/).

Boligsiden is a trademark of Boligsiden A/S. This actor is not affiliated with, endorsed by, or sponsored by Boligsiden.

### 🤝 Support

**Join our active support community**

- For issues or questions, open an issue in the actor's repository
- Check [SIÁN Agency Store](https://apify.com/sian.agency?fpr=sian) for more automation tools
- 📧 <apify@sian-agency.online>

***

**Built by [SIÁN Agency](https://www.sian-agency.online)** | **[More Tools](https://apify.com/sian.agency?fpr=sian)**

# Actor input Schema

## `operation` (type: `string`):

Pick one per run. Homes for Sale returns every active listing that matches your filters, each one carrying the estate agency that is selling it. Sold Prices returns Denmark's salgspriser register with the amount, the date and the sale type. Rentals returns the lejebolig market with rent, deposit and prepaid rent split out. Estate Agents returns every ejendomsmaegler in a place with contact details, CVR number, customer ratings and local market share.

## `location` (type: `string`):

Where to search. A kommune (Aarhus, Odense, Aalborg, Gentofte), a by (Aarhus C, Hellerup), a postcode (8000, 2100) or a landsdel (Oestjylland, Koebenhavn By) all work, with or without Danish letters. The best match is used and the run log prints which place it resolved to. Leave it as it is for a quick first run.

## `areaLevel` (type: `string`):

Boligsiden knows several places by the same name - Aarhus is a kommune, Aarhus C is a by and 8000 is its postcode. Best match picks the widest one that matched, which is what you almost always want. Pin it to a level when you need exactly that scope, for example a single postcode rather than the whole kommune.

## `locations` (type: `array`):

Extra Danish places to cover in the same run, one per line — for example Odense, Aalborg, 5000. Each place is searched separately and gets its own share of the row limit, which is how you build a national dataset without hitting Boligsiden's 10,000-row-per-search ceiling. Leave empty to search only the place above.

## `propertyTypes` (type: `array`):

Which kinds of home to include. Leave empty for every type. A villa is a detached house, a condo is an ejerlejlighed and a cooperative is an andelsbolig. Homes: villa, terraced house, condo, cooperative, villa apartment, double house, multiple family house, room. Holiday and land: holiday house, holiday plot, full year plot, allotment, houseboat. Rural: farm, hobby farm, cattle farm, pig farm, plant farm, forest. Other: garage, parking, business, special.

## `maxResults` (type: `integer`):

Stop after this many rows. Each call returns up to 250 rows, so the run stops at the first call that crosses your limit. Boligsiden itself will not page past 10,000 rows in one search, so ask for more than that only by splitting the run across several places, price bands or sold periods. The Estate Agents option ignores this - one call returns every agency in the place.

## `priceMin` (type: `integer`):

Lowest price to include, in Danish kroner. On the Rentals option this is read as the lowest monthly rent instead. 0 means no lower bound.

## `priceMax` (type: `integer`):

Highest price to include, in Danish kroner. On the Rentals option this is read as the highest monthly rent instead. 0 means no upper bound.

## `roomsMin` (type: `integer`):

Fewest vaerelser to include. Danish listings count every room, not only bedrooms. 0 means no lower bound. Not applied by the Sold Prices or Estate Agents options.

## `roomsMax` (type: `integer`):

Most vaerelser to include. 0 means no upper bound. Not applied by the Sold Prices or Estate Agents options.

## `areaMin` (type: `integer`):

Smallest boligareal in square metres. 0 means no lower bound. Not applied by the Estate Agents option.

## `areaMax` (type: `integer`):

Largest boligareal in square metres. 0 means no upper bound. Not applied by the Estate Agents option.

## `lotAreaMin` (type: `integer`):

Smallest grundareal in square metres. Houses and holiday homes carry one; flats normally do not, so a plot filter quietly excludes them. 0 means no lower bound. Homes for Sale only.

## `yearBuiltFrom` (type: `integer`):

Skip anything built before this year. 0 means no lower bound. Homes for Sale only.

## `energyLabels` (type: `array`):

Only keep homes carrying one of these energimaerker. Accepted values: A2020, A2015, A2010, A1, A2, A, B, C, D, E, F, G. Leave empty for every label, including homes with none. Homes for Sale only.

## `monthlyExpenseMax` (type: `integer`):

Highest ejerudgift per month - the running cost an owner pays on top of the mortgage. 0 means no upper bound. Homes for Sale only.

## `onlyOpenHouse` (type: `boolean`):

Keep only listings with an aabent hus scheduled. Each kept row carries the date and, where the agency requires one, the sign-up link. Homes for Sale only.

## `onlyPriceDrop` (type: `boolean`):

Keep only listings whose asking price has come down since it was published. The percentage is on every row either way. Homes for Sale only.

## `soldMonthsBack` (type: `string`):

How far back to reach into Denmark's salgspriser register. Shorter windows are what you want on a schedule - you pay for the sales that are new since your last run instead of re-buying the same history. The whole register goes back to the 1990s and is large enough that the 10,000-row ceiling will bite on a big kommune.

## `saleTypes` (type: `array`):

Which registered sales to include. Accepted values: normal, family, auction, other. Leave empty for all of them. Family transfers and auctions clear well below market, so a valuation model usually wants normal only.

## `sortBy` (type: `string`):

Newest first is what you want for monitoring a market on a schedule - the rows that arrive are the ones that were not there last time. Price per m² is the ordering Danish buyers and analysts actually compare on, and Rentals has no such ordering, so on that option it falls back to newest and the run log says so. Estate Agents is always ordered by customer rating.

## `agentAddressType` (type: `string`):

Which property type the agency's local market share is measured on. All property types gives each agency's overall share of sales in the place; picking one narrows it to that type, which is what you want when you are looking for whoever actually sells sommerhuse or andelsboliger there.

## Actor input object example

```json
{
  "operation": "search",
  "location": "Aarhus",
  "areaLevel": "auto",
  "locations": [],
  "propertyTypes": [
    "villa"
  ],
  "maxResults": 100,
  "priceMin": 0,
  "priceMax": 0,
  "roomsMin": 0,
  "roomsMax": 0,
  "areaMin": 0,
  "areaMax": 0,
  "lotAreaMin": 0,
  "yearBuiltFrom": 0,
  "energyLabels": [],
  "monthlyExpenseMax": 0,
  "onlyOpenHouse": false,
  "onlyPriceDrop": false,
  "soldMonthsBack": "12",
  "saleTypes": [],
  "sortBy": "newest",
  "agentAddressType": "all"
}
```

# Actor output Schema

## `boligsidenListings` (type: `string`):

Every listing this run returned.

## `scrapingSummary` (type: `string`):

HTML summary showing successful and failed results with key metrics

# 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 = {
    "operation": "search",
    "location": "Aarhus",
    "areaLevel": "auto",
    "locations": [],
    "propertyTypes": [
        "villa"
    ],
    "maxResults": 100,
    "priceMin": 0,
    "priceMax": 0,
    "roomsMin": 0,
    "roomsMax": 0,
    "areaMin": 0,
    "areaMax": 0,
    "lotAreaMin": 0,
    "yearBuiltFrom": 0,
    "energyLabels": [],
    "monthlyExpenseMax": 0,
    "onlyOpenHouse": false,
    "onlyPriceDrop": false,
    "soldMonthsBack": "12",
    "saleTypes": [],
    "sortBy": "newest",
    "agentAddressType": "all"
};

// Run the Actor and wait for it to finish
const run = await client.actor("sian.agency/boligsiden-property-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 = {
    "operation": "search",
    "location": "Aarhus",
    "areaLevel": "auto",
    "locations": [],
    "propertyTypes": ["villa"],
    "maxResults": 100,
    "priceMin": 0,
    "priceMax": 0,
    "roomsMin": 0,
    "roomsMax": 0,
    "areaMin": 0,
    "areaMax": 0,
    "lotAreaMin": 0,
    "yearBuiltFrom": 0,
    "energyLabels": [],
    "monthlyExpenseMax": 0,
    "onlyOpenHouse": False,
    "onlyPriceDrop": False,
    "soldMonthsBack": "12",
    "saleTypes": [],
    "sortBy": "newest",
    "agentAddressType": "all",
}

# Run the Actor and wait for it to finish
run = client.actor("sian.agency/boligsiden-property-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 '{
  "operation": "search",
  "location": "Aarhus",
  "areaLevel": "auto",
  "locations": [],
  "propertyTypes": [
    "villa"
  ],
  "maxResults": 100,
  "priceMin": 0,
  "priceMax": 0,
  "roomsMin": 0,
  "roomsMax": 0,
  "areaMin": 0,
  "areaMax": 0,
  "lotAreaMin": 0,
  "yearBuiltFrom": 0,
  "energyLabels": [],
  "monthlyExpenseMax": 0,
  "onlyOpenHouse": false,
  "onlyPriceDrop": false,
  "soldMonthsBack": "12",
  "saleTypes": [],
  "sortBy": "newest",
  "agentAddressType": "all"
}' |
apify call sian.agency/boligsiden-property-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,sian.agency/boligsiden-property-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/qxLZijspGlYd9qxn3/builds/cHeYljsZBWNiRhtZa/openapi.json
