Boliga Scraper – Danish Real Estate Listings & Sold Prices
Pricing
from $2.00 / 1,000 results
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
Maintained by CommunityActor stats
0
Bookmarked
13
Total users
6
Monthly active users
a day ago
Last modified
Categories
Features
Share
🇩🇰 Boliga Scraper — Danish Real Estate Listings & Historical Sold Prices (Solgte Boliger)
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
| Feature | Details |
|---|---|
| Target Platform | Boliga.dk (boliga.dk — Denmark's leading real-estate portal) |
| Data Modes | For Sale (forSale) active listings (til salg) OR Sold Prices (sold) historical sales (solgte boliger) |
| Geographic Coverage | Nationwide across all of Denmark — 40+ popular cities/zip areas in dropdown + any custom Danish postal code (1000–9990) |
| Property Types | Villa, Rækkehus (Townhouse), Ejerlejlighed (Apartment), Fritidshus (Vacation Home), Andelsbolig (Cooperative), Landejendom, Helårsgrund, Fritidsgrund, Villalejlighed |
| Pagination & Scale | Automatic multi-page extraction (50 properties/page) — supports 1,000+ to 100,000+ properties per run |
| Unique Sold-Price Fields | Final price (DKK), soldDate (YYYY-MM-DD), salesType (Alm. Salg, Fam. Salg, Auktion), squareMeterPrice, priceChangePercent |
| Active Listing Fields | Asking price (DKK), daysForSale, isForeclosure, energyClass (A–G), priceChangePercent, latitude/longitude |
| Deduplication | 100% deduplicated by canonical Boliga property id |
| Export Formats | Bulk 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. SalgvsFam. 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-marketAlm. Salgfrom family transfersFam. Salgand auctionsAuktion), 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
maxItemslimit 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.
| Field | Type | Default | Description |
|---|---|---|---|
listingType | string | "forSale" | Choose "forSale" (homes currently for sale / til salg) or "sold" (historical sold prices / solgte boliger). |
zipAreas | array | [] | Select one or more Danish cities/postal areas from the dropdown (e.g. 2100 Copenhagen Ø, 8000 Aarhus C). Empty = all of Denmark. |
zipCodes | string | "" | Additional Danish 4-digit postal codes, comma-separated (e.g. "2100,2200,8000"). Combined with zipAreas. |
propertyTypes | array | [] | 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 / priceMax | integer | — | Minimum and maximum price in Danish Kroner (DKK). |
roomsMin / roomsMax | integer | — | Minimum and maximum number of rooms. |
sizeMin / sizeMax | integer | — | Minimum and maximum living area in square meters (m²). |
buildYearMin / buildYearMax | integer | — | Earliest and latest construction year (buildYear). |
soldYearMin / soldYearMax | integer | — | Sale-year range (e.g. 2023 to 2026) — used for sold mode only. |
startUrls | array | [] | Optional custom Boliga search URLs. When provided, these take priority over the filter inputs above. |
maxItems | integer | 0 | Maximum number of properties to collect (prefilled to 100 for fast trial runs; 0 = unlimited for filtered searches). |
proxyConfiguration | object | DK Residential | Proxy 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
| Field | Type | Coverage | Description |
|---|---|---|---|
listingType | string | 🟢 High (100%) | Dataset mode: "forSale" or "sold". |
id | string | 🟢 High (100%) | Canonical Boliga property/transaction ID (used for deduplication). |
url | string | 🟢 High (100%) | Direct link to the property page on boliga.dk. |
address | string | 🟢 High (100%) | Street name, house number, and floor/door suffix. |
zipCode | string | 🟢 High (100%) | 4-digit Danish postal code (postnummer). |
city | string | 🟢 High (100%) | City or postal district name (by). |
municipalityCode | number | 🟢 High (~99%) | Official Danish municipality code (kommunekode, e.g. 101 Copenhagen, 751 Aarhus). |
latitude / longitude | number | 🟢 High (~99%) | WGS84 GPS coordinates for mapping and spatial analysis. |
guid | string | 🟢 High (~95%) | Internal property GUID when present. |
scrapedAt | string | 🟢 High (100%) | ISO 8601 extraction timestamp. |
💰 Pricing & Transaction Fields
| Field | Type | Coverage | Description |
|---|---|---|---|
price | number | 🟢 High (100%) | Price in DKK — asking price (kontantpris) for forSale, final transaction price (salgspris) for sold. |
squareMeterPrice | number | 🟢 High (~99%) | Price per living square meter in DKK (DKK/m²), rounded to integer. |
priceChangePercent | number | 🟢 High (~98%) | Percentage price change (%) from initial listing price. |
daysForSale | number | 🟡 Active Only | Number of days on the market (liggetid) — populated on forSale records (null on sold). |
isForeclosure | boolean | 🟡 Active Only | true if the listing is a forced auction (tvangsauktion) — populated on forSale records. |
soldDate | string | 🟡 Sold Only | Official transaction date in YYYY-MM-DD format — populated on sold records (null on forSale). |
salesType | string | 🟡 Sold Only | Transaction category on sold records: "Alm. Salg" (regular market sale), "Fam. Salg" (family transfer), "Auktion", or "Andet". |
📐 Property Classification & Specs
| Field | Type | Coverage | Description |
|---|---|---|---|
propertyType | string | 🟢 High (100%) | Human-readable Danish dwelling type (Villa, Ejerlejlighed, Rækkehus, Andelsbolig, Fritidshus, etc.). |
propertyTypeCode | number | 🟢 High (100%) | Numeric property type code (1–10). |
rooms | number | 🟢 High (~98%) | Number of rooms (værelser). |
size | number | 🟢 High (~99%) | Living area in square meters (boligareal m²). |
lotSize | number | 🟡 Conditional (~70%) | Land plot area in m² (grundareal, populated primarily for houses, villas and plots). |
basementSize | number | 🟡 Conditional (~40%) | Basement area in m² (kælderareal) when present. |
floor | string | 🟡 Conditional (~35%) | Floor level for apartments (etage). |
buildYear | number | 🟢 High (~98%) | Construction year (opførelsesår). |
energyClass | string | 🟡 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:
- 50-record high-speed page stepping — fetches 50 properties per page and inspects the total page count (
totalPages) to advance through page1, 2, 3...untilmaxItemsis reached or all pages are collected. - Multi-zip sold-price fan-out — when scraping
soldprices across multiple postal codes (zipAreas/zipCodes), the actor automatically creates a dedicated paginated stream per postal code and merges all records. - Resilient deduplication — tracks every seen property
id(with anaddress|price|soldDatefallback) 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
- Open Boliga Scraper in Apify Console and click Try for free.
- Select Listing type: For sale (til salg) or Sold prices (solgte boliger).
- (Optional) Pick Danish cities/areas in Areas / cities (
zipAreas) or type postal codes into More zip codes (zipCodes). - (Optional) Filter by Property types, Price (DKK), Rooms, Living area (m²), Build year, or Sold year.
- Set Max items (
maxItems) to your desired dataset size (e.g.100,1000,5000, or0for unlimited). - 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 fromsoldrecords, filter your exported dataset tosalesType === "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/zipCodeswithsoldYearMin(e.g.2022) andmaxItemsto 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:
soldDateandsalesTypeexist only on historicalsoldrecords (nullon active listings), whereasdaysForSaleandisForeclosureexist only on activeforSalelistings (nullon sold records). - Energy class on historical sales:
energyClassis populated on almost all activeforSalelistings (~90%+), but is oftennullon historicalsoldrecords where the Danish property register does not include an energy certificate. - Empty-run safety cap: If you start the actor with
maxItems: 0and zero filters/URLs, it caps the preview run at150properties so an accidental blank run does not crawl the entire country. SetmaxItemsexplicitly (e.g.1000or5000) 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 ApifyClientclient = 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.`);
🔗 Related scrapers
Scraping real estate in other European and global markets? Pair the Boliga scraper with:
- FazWaz Thailand Property Scraper — Thailand sale & rent listings, THB prices, rental yields and GPS.
- ImmobilienScout24 Scraper — Germany's leading property portal.
- Daft.ie Scraper — Irish property listings for sale and rent.
- Yad2 Scraper — Israel's #1 real estate and classifieds marketplace.
- ZAP Imóveis Scraper — Brazilian real estate listings.
- Domain.com.au Scraper — Australian property listings and sold prices.
📋 Changelog
- v1.2 (2026-11) — Enhanced 1,000+ multi-page pagination resilience across overlapping postal-code searches, added automatic conversion for standard
boliga.dkweb search URLs instartUrls, and expanded documentation. - v1.1 (2026-11) — Added multi-zip range seeding (
zipcodeFrom/zipcodeTo) forsoldmode, normalizedsalesTypeand positiveidresolution (id/estateId/ouId). - v1.0 (2026-06) — Initial release supporting both active Danish listings (
forSale) and historical sold prices (sold).