Boliga Scraper – Danish Real Estate Listings & Sold Prices avatar

Boliga Scraper – Danish Real Estate Listings & Sold Prices

Pricing

from $2.00 / 1,000 results

Go to Apify Store
Boliga Scraper – Danish Real Estate Listings & Sold Prices

Boliga Scraper – Danish Real Estate Listings & Sold Prices

Boliga scraper & API for Danish real estate: search homes for sale and sold prices and export address, price, rooms, m2, lot, type, sale type, energy, days on market and coordinates. Denmark property and sold-price market data — fast, no login.

Pricing

from $2.00 / 1,000 results

Rating

0.0

(0)

Developer

Haketa

Haketa

Maintained by Community

Actor stats

0

Bookmarked

13

Total users

6

Monthly active users

a day ago

Last modified

Features

Limited permissions

Share

🇩🇰 Boliga Scraper — Danish Real Estate Listings & Historical Sold Prices (Solgte Boliger)

Apify Actor Denmark Real Estate Pagination Export Formats

Extract active property listings (til salg) and historical sold prices (solgte boliger / salgspriser) from Boliga.dk — Denmark's largest and most comprehensive real estate marketplace. This Boliga scraper pulls clean, structured Boliga data as JSON, CSV, or Excel: prices in DKK, price per m², rooms, living area, lot size, build year, energy class, street addresses, municipality codes, GPS coordinates, sale dates, sale types and foreclosure flags. No login, no coding.

Export every result to JSON, CSV, Excel, XML, or API for Danish property valuation, PropTech applications, mortgage underwriting, real-estate lead generation, and housing market analytics.

🇩🇰 Built for Danish real-estate analysts, PropTech builders, mortgage & valuation teams, investors, brokers and data journalists — anyone who needs reliable Boliga.dk listing and sold-price data on demand. This Boliga data extractor covers BOTH homes currently for sale and the official nationwide sold-price history (solgte boliger) spanning decades.


⚡ At a glance

FeatureDetails
Target PlatformBoliga.dk (boliga.dk — Denmark's leading real-estate portal)
Data ModesFor Sale (forSale) active listings (til salg) OR Sold Prices (sold) historical sales (solgte boliger)
Geographic CoverageNationwide across all of Denmark — 40+ popular cities/zip areas in dropdown + any custom Danish postal code (1000–9990)
Property TypesVilla, Rækkehus (Townhouse), Ejerlejlighed (Apartment), Fritidshus (Vacation Home), Andelsbolig (Cooperative), Landejendom, Helårsgrund, Fritidsgrund, Villalejlighed
Pagination & ScaleAutomatic multi-page extraction (50 properties/page) — supports 1,000+ to 100,000+ properties per run
Unique Sold-Price FieldsFinal price (DKK), soldDate (YYYY-MM-DD), salesType (Alm. Salg, Fam. Salg, Auktion), squareMeterPrice, priceChangePercent
Active Listing FieldsAsking price (DKK), daysForSale, isForeclosure, energyClass (A–G), priceChangePercent, latitude/longitude
Deduplication100% deduplicated by canonical Boliga property id
Export FormatsBulk export to JSON, CSV, Excel, XML, RSS, or programmatic access via Apify REST API

🔎 Why scrape Boliga?

Boliga is Denmark's premier property search engine and housing data repository. Danes use it daily to browse homes for sale and — crucially — to look up what properties actually sold for. Boliga aggregates the entire Danish housing market and combines live agency listings with official Danish land-registry transaction history, making it the single richest public source of Danish real-estate intelligence.

Collecting this data manually is slow and impractical. Boliga paginates results 50 properties at a time, and a regional or nationwide sold-price archive contains hundreds of thousands of transactions. Copy-pasting addresses, square-meter prices, and sale dates into a spreadsheet does not scale and cannot feed automated models. This Boliga scraper turns the entire platform into a clean, on-demand data pipeline — delivering valuation-grade comparables, market trends and property lead lists in seconds.

Common reasons people scrape Boliga:

  • 💰 Build automated valuation models (AVMs) and comparative market analyses (CMA) backed by real historical sold prices (solgte boliger).
  • 📊 Track Danish housing-market trends — monitor DKK/m² (squareMeterPrice), days-on-market (daysForSale), and price reductions (priceChangePercent) by postal code over time.
  • 🏦 Feed mortgage, risk and collateral valuation systems with verified transaction history and sale-type classifications (Alm. Salg vs Fam. Salg).
  • 🏘️ Benchmark active agency listings, monitor inventory in specific Copenhagen, Aarhus, Odense or Aalborg postal codes, and spot distressed or foreclosure properties (isForeclosure).
  • 🤖 Power PropTech apps, dashboards and AI valuation assistants with structured Danish property feeds.
  • 🎯 Generate real-estate leads from newly listed properties, long-standing listings (daysForSale > 120), and price-reduced homes.

✨ What this Boliga scraper does

  • ✅ Two data modes in one actor — scrape homes currently for sale (forSale / til salg) or the complete archive of sold prices (sold / solgte boliger). Switch modes with a single dropdown.
  • ✅ Sold prices (solgte boliger) with sale-type classification — captures final sale price, exact sale date (soldDate), sale type (salesType) (distinguishing open-market Alm. Salg from family transfers Fam. Salg and auctions Auktion), price per m², and price change percentage.
  • ✅ Unlocked 1,000+ automatic pagination — walks page after page (50 records per page) and merges results into one clean dataset until your maxItems limit is reached or all matching pages are exhausted.
  • ✅ Comprehensive targeting & filtering — select Danish cities/areas from a 41-location dropdown, enter any comma-separated Danish postal codes (zipCodes), and filter by property type, price range (DKK), rooms, living area (m²), build year, and sale year (soldYearMin / soldYearMax).
  • ✅ Multi-zip sold-price orchestration — automatically seeds and paginates each postal code across sold-price searches and deduplicates all records into a single unified dataset.
  • ✅ Zero-config sample mode — hitting Start with empty filters returns a fast, ready-to-inspect sample of Danish homes so you can verify the schema immediately.
  • ✅ Export anywhere — download as JSON, CSV, Excel, XML, or RSS, or integrate directly via the Apify API.

🎯 Use cases

1. Real Estate Investors & Acquisition Analysts

Compare asking squareMeterPrice on active forSale listings against recent sold transactions (Alm. Salg) in the exact same zipCode and propertyType to immediately spot undervalued apartments (Ejerlejlighed) and houses (Villa).

2. PropTech Platforms & Automated Valuation Models (AVMs)

Ingest historical sold transactions (soldYearMin: 2020) with size, lotSize, rooms, buildYear, municipalityCode, and latitude/longitude to train spatial machine-learning valuation models for the Danish housing market.

3. Banks, Mortgage Lenders & Appraisers

Distinguish arms-length market transactions (salesType: "Alm. Salg") from non-market family transfers ("Fam. Salg") and forced auctions ("Auktion") when underwriting loans or auditing portfolio collateral values.

4. Estate Agencies & Broker Lead Generation

Identify high-opportunity seller leads by filtering active listings with long market exposure (daysForSale), negative priceChangePercent, or foreclosure status (isForeclosure: true).

5. Economic Research & Data Journalism

Analyze regional housing affordability, urban vs. rural price divergence, and energy-label (energyClass) price premiums across Copenhagen, Frederiksberg, Aarhus, Odense, and Aalborg.


📥 Input parameters

Configure a run from the Apify Console UI or pass a JSON payload via the API. All fields are optional.

FieldTypeDefaultDescription
listingTypestring"forSale"Choose "forSale" (homes currently for sale / til salg) or "sold" (historical sold prices / solgte boliger).
zipAreasarray[]Select one or more Danish cities/postal areas from the dropdown (e.g. 2100 Copenhagen Ø, 8000 Aarhus C). Empty = all of Denmark.
zipCodesstring""Additional Danish 4-digit postal codes, comma-separated (e.g. "2100,2200,8000"). Combined with zipAreas.
propertyTypesarray[]Dwelling type codes ("1"–"9"): 1 Villa, 2 Rækkehus, 3 Ejerlejlighed, 4 Fritidshus, 5 Andelsbolig, 6 Landejendom, 7 Helårsgrund, 8 Fritidsgrund, 9 Villalejlighed.
priceMin / priceMaxinteger—Minimum and maximum price in Danish Kroner (DKK).
roomsMin / roomsMaxinteger—Minimum and maximum number of rooms.
sizeMin / sizeMaxinteger—Minimum and maximum living area in square meters (m²).
buildYearMin / buildYearMaxinteger—Earliest and latest construction year (buildYear).
soldYearMin / soldYearMaxinteger—Sale-year range (e.g. 2023 to 2026) — used for sold mode only.
startUrlsarray[]Optional custom Boliga search URLs. When provided, these take priority over the filter inputs above.
maxItemsinteger0Maximum number of properties to collect (prefilled to 100 for fast trial runs; 0 = unlimited for filtered searches).
proxyConfigurationobjectDK ResidentialProxy settings. Pre-configured with Danish (DK) residential proxies for reliable, rate-limit-free extraction.

Example 1 — 1,000+ Villas & Apartments for sale in Copenhagen

{
"listingType": "forSale",
"zipAreas": ["1050", "2000", "2100", "2200", "2300", "2400"],
"propertyTypes": ["1", "3"],
"priceMax": 12000000,
"maxItems": 1000,
"proxyConfiguration": {
"useApifyProxy": true,
"apifyProxyGroups": ["RESIDENTIAL"],
"apifyProxyCountry": "DK"
}
}

Example 2 — Historical sold prices (solgte boliger) in Aarhus & Odense 💰

{
"listingType": "sold",
"zipAreas": ["8000", "8200", "5000"],
"soldYearMin": 2023,
"maxItems": 1500
}

Example 3 — Nationwide affordable homes under 3,000,000 DKK

{
"listingType": "forSale",
"priceMax": 3000000,
"roomsMin": 3,
"maxItems": 2000
}

📤 Output & field reference

Each property is saved as a normalized JSON record in your dataset. Below are two real records — one active listing (forSale) and one historical sale (sold).

Sample JSON — Active listing (forSale)

{
"listingType": "forSale",
"id": "2353911",
"url": "https://www.boliga.dk/bolig/2353911",
"propertyType": "Villa",
"propertyTypeCode": 1,
"address": "Ved Grænsen 26",
"zipCode": "2000",
"city": "Frederiksberg",
"municipalityCode": 147,
"price": 10750000,
"squareMeterPrice": 107500,
"priceChangePercent": -6,
"rooms": 4,
"size": 100,
"lotSize": 399,
"floor": null,
"buildYear": 1915,
"energyClass": "E",
"basementSize": 35,
"daysForSale": 95,
"isForeclosure": false,
"soldDate": null,
"salesType": null,
"latitude": 55.68379,
"longitude": 12.49919,
"guid": "A8655DA2-45D3-4CEC-BC8A-3690FB211EEB",
"scrapedAt": "2026-11-01T23:29:34.898Z"
}

Sample JSON — Sold property (sold)

{
"listingType": "sold",
"id": "1062099617",
"url": "https://www.boliga.dk/bolig/1062099617",
"propertyType": "Ejerlejlighed",
"propertyTypeCode": 3,
"address": "Jette Tikjøbs Plads 5, st.",
"zipCode": "8000",
"city": "Aarhus C",
"municipalityCode": 751,
"price": 1783200,
"squareMeterPrice": 31284,
"priceChangePercent": 0,
"rooms": 2,
"size": 57,
"lotSize": null,
"floor": null,
"buildYear": 2017,
"energyClass": null,
"basementSize": null,
"daysForSale": null,
"isForeclosure": null,
"soldDate": "2026-10-26",
"salesType": "Fam. Salg",
"latitude": 56.167065,
"longitude": 10.2278,
"guid": "CAC07A06-FC8C-4918-BDE9-58842CDB679D",
"scrapedAt": "2026-11-01T23:30:45.936Z"
}

🏷️ Identity & Location Fields

FieldTypeCoverageDescription
listingTypestring🟢 High (100%)Dataset mode: "forSale" or "sold".
idstring🟢 High (100%)Canonical Boliga property/transaction ID (used for deduplication).
urlstring🟢 High (100%)Direct link to the property page on boliga.dk.
addressstring🟢 High (100%)Street name, house number, and floor/door suffix.
zipCodestring🟢 High (100%)4-digit Danish postal code (postnummer).
citystring🟢 High (100%)City or postal district name (by).
municipalityCodenumber🟢 High (~99%)Official Danish municipality code (kommunekode, e.g. 101 Copenhagen, 751 Aarhus).
latitude / longitudenumber🟢 High (~99%)WGS84 GPS coordinates for mapping and spatial analysis.
guidstring🟢 High (~95%)Internal property GUID when present.
scrapedAtstring🟢 High (100%)ISO 8601 extraction timestamp.

💰 Pricing & Transaction Fields

FieldTypeCoverageDescription
pricenumber🟢 High (100%)Price in DKK — asking price (kontantpris) for forSale, final transaction price (salgspris) for sold.
squareMeterPricenumber🟢 High (~99%)Price per living square meter in DKK (DKK/m²), rounded to integer.
priceChangePercentnumber🟢 High (~98%)Percentage price change (%) from initial listing price.
daysForSalenumber🟡 Active OnlyNumber of days on the market (liggetid) — populated on forSale records (null on sold).
isForeclosureboolean🟡 Active Onlytrue if the listing is a forced auction (tvangsauktion) — populated on forSale records.
soldDatestring🟡 Sold OnlyOfficial transaction date in YYYY-MM-DD format — populated on sold records (null on forSale).
salesTypestring🟡 Sold OnlyTransaction category on sold records: "Alm. Salg" (regular market sale), "Fam. Salg" (family transfer), "Auktion", or "Andet".

📐 Property Classification & Specs

FieldTypeCoverageDescription
propertyTypestring🟢 High (100%)Human-readable Danish dwelling type (Villa, Ejerlejlighed, Rækkehus, Andelsbolig, Fritidshus, etc.).
propertyTypeCodenumber🟢 High (100%)Numeric property type code (1–10).
roomsnumber🟢 High (~98%)Number of rooms (værelser).
sizenumber🟢 High (~99%)Living area in square meters (boligareal m²).
lotSizenumber🟡 Conditional (~70%)Land plot area in m² (grundareal, populated primarily for houses, villas and plots).
basementSizenumber🟡 Conditional (~40%)Basement area in m² (kælderareal) when present.
floorstring🟡 Conditional (~35%)Floor level for apartments (etage).
buildYearnumber🟢 High (~98%)Construction year (opførelsesår).
energyClassstring🟡 Conditional (~85% active)Danish energy label (energimærke, A–G), populated mainly on active listings.

🔁 Pagination & 1,000+ scaling

The Boliga scraper handles deep pagination automatically across both active and sold datasets:

  1. 50-record high-speed page stepping — fetches 50 properties per page and inspects the total page count (totalPages) to advance through page 1, 2, 3... until maxItems is reached or all pages are collected.
  2. Multi-zip sold-price fan-out — when scraping sold prices across multiple postal codes (zipAreas / zipCodes), the actor automatically creates a dedicated paginated stream per postal code and merges all records.
  3. Resilient deduplication — tracks every seen property id (with an address|price|soldDate fallback) and tolerates overlapping pages without stopping early, ensuring you can cleanly extract 1,000+ to 50,000+ unique Danish properties in a single run.

⚙️ How to use

  1. Open Boliga Scraper in Apify Console and click Try for free.
  2. Select Listing type: For sale (til salg) or Sold prices (solgte boliger).
  3. (Optional) Pick Danish cities/areas in Areas / cities (zipAreas) or type postal codes into More zip codes (zipCodes).
  4. (Optional) Filter by Property types, Price (DKK), Rooms, Living area (m²), Build year, or Sold year.
  5. Set Max items (maxItems) to your desired dataset size (e.g. 100, 1000, 5000, or 0 for unlimited).
  6. Click Start and export your results to JSON, CSV, Excel, XML, or consume them via the Apify API.

💡 Pro tips for best results

  • Filter out family sales (Fam. Salg) for valuations: When building comparable-sales models from sold records, filter your exported dataset to salesType === "Alm. Salg" so below-market family transfers do not skew your DKK/m² averages.
  • Target specific postal codes for deep sold history: Denmark's nationwide sold archive contains hundreds of thousands of records going back decades. Combine zipAreas / zipCodes with soldYearMin (e.g. 2022) and maxItems to keep runs fast and focused.
  • Property type code quick reference:
    • 1 = Villa (Detached house)
    • 2 = Rækkehus (Townhouse / terraced house)
    • 3 = Ejerlejlighed (Owner-occupied apartment / condo)
    • 4 = Fritidshus (Holiday / summer house)
    • 5 = Andelsbolig (Housing cooperative)
    • 6 = Landejendom (Country / agricultural property)
    • 7 = Helårsgrund (Year-round building plot)
    • 8 = Fritidsgrund (Holiday building plot)
    • 9 = Villalejlighed (Villa apartment)

⚠️ Honest limitations

  • Mode-specific fields: soldDate and salesType exist only on historical sold records (null on active listings), whereas daysForSale and isForeclosure exist only on active forSale listings (null on sold records).
  • Energy class on historical sales: energyClass is populated on almost all active forSale listings (~90%+), but is often null on historical sold records where the Danish property register does not include an energy certificate.
  • Empty-run safety cap: If you start the actor with maxItems: 0 and zero filters/URLs, it caps the preview run at 150 properties so an accidental blank run does not crawl the entire country. Set maxItems explicitly (e.g. 1000 or 5000) or add any filter to scrape as many records as you want.

❓ FAQ

Does this scraper extract historical sold prices (solgte boliger)?

Yes. Set listingType to "sold" to extract historical Danish property sale prices, exact sale dates (soldDate), sale types (salesType), and square-meter prices (squareMeterPrice).

How many properties can I scrape in a single run, and how fast?

You can collect 1,000+ to 50,000+ properties per run. Because the actor fetches 50 listings per page over lightweight HTTP requests, 1,000 properties typically complete in well under a minute.

Do I need a Boliga login or account?

No login or account is required. Pre-configured Danish (DK) residential proxies are used by default to ensure smooth, uninterrupted pagination.

What is the difference between Alm. Salg, Fam. Salg, and Auktion?

In sold mode, salesType tells you how the property was transferred:

  • Alm. Salg — Regular open-market transaction.
  • Fam. Salg — Transfer between family members (frequently priced up to 15% below public valuation).
  • Auktion — Forced/foreclosure auction sale.

Can I scrape all of Denmark at once?

Yes — leave zipAreas and zipCodes empty, and set maxItems to your desired cap (e.g. 2000 or 10000), or add a price/type/year filter.

Can I schedule recurring runs or connect to Google Sheets / BigQuery?

Yes. Use Apify Schedules to run the scraper daily or weekly, and connect the output to Google Sheets, Make, Zapier, Slack, BigQuery, Snowflake, or webhooks to track new listings (forSale) or newly recorded transactions (sold).


💻 API & programmatic integration

Run Boliga Scraper programmatically from Python, Node.js, or any HTTP client via the Apify REST API.

cURL example

curl -X POST "https://api.apify.com/v2/acts/haketa~boliga-scraper/runs?token=YOUR_APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"listingType": "sold",
"zipAreas": ["2100", "2200", "8000"],
"soldYearMin": 2023,
"maxItems": 1000
}'

Python (apify-client) example

from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run_input = {
"listingType": "forSale",
"zipAreas": ["1050", "2000", "2100"],
"propertyTypes": ["1", "3"],
"maxItems": 1000,
}
run = client.actor("haketa/boliga-scraper").call(run_input=run_input)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(f"{item.get('address')}, {item.get('zipCode')} {item.get('city')} — {item.get('price')} DKK ({item.get('squareMeterPrice')} DKK/m²)")

Node.js (apify-client) example

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('haketa/boliga-scraper').call({
listingType: 'sold',
zipAreas: ['8000'],
soldYearMin: 2024,
maxItems: 1000,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(`Fetched ${items.length} Danish property records from Boliga.`);

Scraping real estate in other European and global markets? Pair the Boliga scraper with:


📋 Changelog

  • v1.2 (2026-11) — Enhanced 1,000+ multi-page pagination resilience across overlapping postal-code searches, added automatic conversion for standard boliga.dk web search URLs in startUrls, and expanded documentation.
  • v1.1 (2026-11) — Added multi-zip range seeding (zipcodeFrom/zipcodeTo) for sold mode, normalized salesType and positive id resolution (id/estateId/ouId).
  • v1.0 (2026-06) — Initial release supporting both active Danish listings (forSale) and historical sold prices (sold).
⌂ 换网址