# FINN Property Sales Scraper (`crawlstone/finn-property-sales-scraper`) Actor

Find properties for sale on FINN.no and collect structured listing and property details for market research, lead discovery, comparisons, and data workflows.

- **URL**: https://apify.com/crawlstone/finn-property-sales-scraper.md
- **Developed by:** [Crawl Stone](https://apify.com/crawlstone) (community)
- **Categories:** Real estate, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.13 / 1,000 discovery pages

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/platform/actors/running/actors-in-store#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

## FINN Property Sales Scraper

We built FINN Property Sales Scraper to provide a straightforward, query-based way to discover property listings in Norway and retrieve structured details for specific real estate. Whether you are running regional price-per-square-meter analyses, collecting lead listings, or feeding property data directly into your integrations, this Actor delivers structured datasets directly from FINN.no on-demand.

> **Unofficial Actor:** This is an independent tool and is not affiliated with, authorized, or endorsed by FINN.no.

***

### From Search to Listing Analysis: The Customer Journey

The Actor is designed around a three-stage workflow that matches how you explore a real estate market: discover listings, refine your search boundaries, and retrieve details for individual properties.

#### Stage 1: Discover the Market (`discover` view)

Start by identifying listings across categories. The Actor supports six category-specific discovery modes to return a clean, compact snapshot of listings:

- `discoverHomes` — apartments, houses, terraced homes, and residential properties.
- `discoverNewBuildings` — new residential projects and individual new-build units.
- `discoverLeisureHomes` — cabins, cottages, and holiday homes.
- `discoverAbroad` — international properties listed on the Norwegian market.
- `discoverPlots` — residential plots and building land.
- `discoverLeisurePlots` — holiday home plots and undeveloped leisure land.

**Discovery Mechanics:** To keep execution predictable and lightweight, **discovery fetches exactly one selected page (pages 1–50) per run** and does not automatically paginate. Each successful run emits exactly one Dataset row containing a nested `results` array of compact listings. This preserves the original source ordering and duplicate occurrences without deduplication.

#### Stage 2: Refine the Search

You can group search refinements by your data requirements in the Apify Store form:

- **Core Search:** Filter by free-text search (`query`), listing recency (`publishedToday`), and page numbers (`page`).
- **Financial Filters:** Refine using range filters for asking price, total price, and monthly common costs.
- **Physical Filters:** Target specific sizes, plot areas, construction years, bedroom counts, or energy labels.
- **Geographic Filters:** Use standard location taxonomy codes, or run geographical boundary searches. Define your target area using either `mapAreaRadius` (defining a center latitude/longitude and a radius in meters) or `mapAreaPolygon` (requiring at least three coordinates, repeating the first point last to close the boundary). *Note that radius and polygon options are mutually exclusive—use one or the other, not both.*

#### Stage 3: Retrieve Property Details (`propertyDetail` view)

Once you have identified a listing's `canonicalUrl` from a discovery run, transition to collecting its details using `propertyDetail`.

Provide exactly one supported, canonical FINN property-sale URL. The Actor maps the page layout into one of eleven strict detail families identified by `detailType`:

- **Residential**: `home`, `plannedProperty`
- **New Developments**: `newBuildingProject`, `newBuildingUnit`, `newBuildingSingle`
- **Leisure Properties**: `leisureHome`, `newLeisureProject`, `newLeisureUnit`
- **Land Plots**: `plot`, `leisurePlot`
- **International**: `abroadProperty`

Unlike the compact discovery results, a saved property-detail row extracts richer facts directly from the listing. Depending on what the seller has provided and what the specific detail family supports, this may include transaction cost breakdowns, room counts, cadastral registry numbers, viewing schedules, contact details, coordinates, and description texts.

***

### Quick Start

1. Click **Try for free** on the Actor page.
2. Select your desired **Mode** (the prefilled default is `discoverHomes`).
3. Set your search terms, location, or range filters.
4. Click **Start**.
5. View or download your results in the **Dataset** tab.

For your first run, you can use the prefilled homes search on page `1`:

```json
{
  "mode": "discoverHomes",
  "page": 1
}
```

If no listings match your query, the run succeeds with a valid empty results array (`"results": []`).

***

### URL Requirements for Detailed Inspection

When running the `propertyDetail` mode, the input URL must be a clean, canonical HTTPS link pointing to a supported FINN property-sale page.

- **Canonical Format:** Must start with `https://www.finn.no/realestate/` and end with the file name `ad.html?finnkode=` followed by a positive numerical ID (e.g., `https://www.finn.no/realestate/homes/ad.html?finnkode=123456789`).
- **Query Parameter Rules:** Do not include any additional query parameters (such as `&orgId=...` or `&clickSource=...`) or hash fragments (like `#section`) beyond the single positive `finnkode`.
- **Supported Routes:** The URL path segment must match a supported FINN real estate route, including `/homes/`, `/project/`, `/projectsingle/`, `/projectunit/`, `/planned/`, `/projectleisure/`, `/projectunitleisure/`, `/leisuresale/`, `/abroad/`, or `/plots/`.
- **Single URL:** The detail mode accepts exactly one URL per run. To analyze multiple properties, schedule separate runs using Apify Tasks or your own client pipeline.

***

### Data Structure & Examples

The Dataset output is organized under two distinct views: `discover` and `propertyDetail`. Tabular exports (like CSV or Excel) flatten nested structures, whereas JSON exports preserve the raw relationships.

#### Discover View Envelope

Each successful discovery run produces exactly one Dataset row containing the page metadata and the nested array of listings.

*This is an abridged preview of selected fields, not a complete schema-valid Dataset row.*

```json
{
  "page": 1,
  "lastPage": 18,
  "resultCount": 50,
  "matchCount": 874,
  "groupCount": 0,
  "results": [
    {
      "finnCode": "320495810",
      "sourceType": "realestate",
      "detailType": "home",
      "canonicalUrl": "https://www.finn.no/realestate/homes/ad.html?finnkode=320495810",
      "title": "Lys og innbydende 3-roms selveierleilighet",
      "location": "Oslo",
      "askingPrice": {
        "amount": 5450000,
        "currencyCode": "NOK"
      },
      "area": {
        "size": 68,
        "unit": "m²"
      }
    }
  ]
}
```

##### Understanding the Metadata & Results

- **Page & Last Page:** `page` represents the page returned. `lastPage` is FINN's reported last page capped at 50.
- **Search Counts:** `matchCount` is FINN's reported total matching result count, and `groupCount` is FINN's reported grouped-result count.
- **Source Preservation:** The Actor preserves exact source values, original ordering, and repeated listings. Confirmed zero, `false`, or empty arrays are explicitly serialized, while unknown or missing optional fields are omitted instead of guessed.

***

### Pricing & Proxies

#### Managed Proxies & Billing

FINN requests use the managed Norway residential proxy automatically. Platform compute and managed proxy expenses are fully included in the Actor's price; there is no customer proxy configuration or separate platform/proxy fee to manage.

You pay strictly for successful operations using Apify’s Pay Per Event (PPE) model:

- **`discover-page`** — charged once per successful discovery page saved. This includes valid empty pages (which save a valid envelope with `results: []`).
- **`property-detail`** — charged once per successfully saved property-detail row.

**Failed Operations:**

If a scraping operation fails due to network errors or source unavailability, or if a Dataset-save failure occurs, the run terminates, no Dataset row is written, and you are **not** charged a PPE event. No synthetic error rows are produced.

Please check the Actor's **Pricing** tab for current custom PPE event rates.

***

### Use with Apify MCP

If you integrate property data into AI assistant workflows, you can connect this Actor directly to compatible Model Context Protocol (MCP) clients (such as Claude Desktop):

```text
https://mcp.apify.com?tools=crawlstone/finn-property-sales-scraper
```

Once connected, you can discover local listings, filter real estate options, and retrieve property details using natural language query patterns.

***

### Frequently Asked Questions

#### Can I retrieve multiple pages or analyze multiple URLs in one run?

No. To keep execution lightweight and predictable, each discovery run fetches exactly one page (with page inputs supported up to page 50) and each detail run accepts exactly one canonical URL. To collect multiple available pages or analyze a list of discovered URLs, configure successive runs using Apify Tasks, Schedules with prepared inputs, API clients, or user-owned automation.

#### Does discovery return the same details as property detail?

No. Discovery results are compact and optimized for high-level search and screening. If you need rich interior details, transaction fees, and contact information, extract the `canonicalUrl` from the discovery results and feed it to a run in `propertyDetail` mode.

#### What happens if a discovery page has no matching listings?

If no listings match your query, the run completes successfully and saves one row with an empty `"results": []` array. Because this represents a completed search operation, it charges exactly one `discover-page` event.

#### Why are some fields missing from my results?

FINN listings are highly unstructured, and many details (such as construction year or common debt) are optional and do not apply to all property types. To preserve the source's integrity, missing fields are omitted from the row rather than guessed or padded with placeholders, while verified numeric zeros and boolean flags are explicitly serialized.

#### Does the Actor remove duplicate listings?

No. Results remain in their original source order, preserving any repeated listings or duplicate advertisements exactly as returned by FINN.

***

### Support

If you need assistance, please open a ticket on this Actor's **Discussion** tab in the Apify Console and include:

- Your Apify **Run ID**.
- The selected **Mode** and the **Input** parameters you provided.
- A clear description of what you expected versus what occurred.

*To protect your account security, please do not share your Apify API Token or proxy credentials in public support tickets.*

# Actor input Schema

## `mode` (type: `string`):

Choose one FINN property-sale discovery or detail operation. Only fields belonging to the selected mode are used.

## `propertyUrl` (type: `string`):

Required only when Mode is propertyDetail. Enter one exact canonical HTTPS www.finn.no property-detail URL with a recognized route and one positive finnkode; do not include a fragment or any other query parameter.

## `query` (type: `string`):

Used by every discovery mode. Optional free text sent to the selected FINN property search.

## `publishedToday` (type: `boolean`):

Used by every discovery mode. Enable to return listings in FINN's Nye i dag filter.

## `page` (type: `integer`):

Used by every discovery mode. Fetch exactly one FINN result page; FINN may clamp it to the current last page.

## `mapAreaPolygon` (type: `array`):

Used by every discovery mode. Enter at least three distinct vertices and repeat the first point last to close the polygon. Cannot be combined with mapAreaRadius; taxonomy locations may still be used.

## `mapAreaRadius` (type: `object`):

Used by every discovery mode. Define a center and a positive radius in metres. Cannot be combined with mapAreaPolygon; taxonomy locations may still be used.

## `askingPriceFrom` (type: `integer`):

Used by every discovery mode. Optional inclusive minimum; it cannot exceed askingPriceTo.

## `askingPriceTo` (type: `integer`):

Used by every discovery mode. Optional inclusive maximum; it cannot be lower than askingPriceFrom.

## `totalPriceFrom` (type: `integer`):

Used by every discovery mode. Optional inclusive minimum; it cannot exceed totalPriceTo.

## `totalPriceTo` (type: `integer`):

Used by every discovery mode. Optional inclusive maximum; it cannot be lower than totalPriceFrom.

## `monthlyCommonCostsFrom` (type: `integer`):

Used only when Mode is discoverHomes. Optional inclusive minimum; it cannot exceed monthlyCommonCostsTo.

## `monthlyCommonCostsTo` (type: `integer`):

Used only when Mode is discoverHomes. Optional inclusive maximum; it cannot be lower than monthlyCommonCostsFrom.

## `areaFrom` (type: `integer`):

Used when Mode is one of discoverHomes, discoverNewBuildings, discoverLeisureHomes, and discoverAbroad. Optional inclusive minimum; it cannot exceed areaTo.

## `areaTo` (type: `integer`):

Used when Mode is one of discoverHomes, discoverNewBuildings, discoverLeisureHomes, and discoverAbroad. Optional inclusive maximum; it cannot be lower than areaFrom.

## `minimumBedrooms` (type: `string`):

Used when Mode is one of discoverHomes, discoverNewBuildings, discoverLeisureHomes, and discoverAbroad.

## `constructionYearFrom` (type: `integer`):

Used when Mode is discoverHomes, discoverLeisureHomes, or discoverAbroad. Optional inclusive minimum; it cannot exceed constructionYearTo.

## `constructionYearTo` (type: `integer`):

Used when Mode is discoverHomes, discoverLeisureHomes, or discoverAbroad. Optional inclusive maximum; it cannot be lower than constructionYearFrom.

## `plotAreaFrom` (type: `integer`):

Used when Mode is discoverHomes, discoverPlots, or discoverLeisurePlots. Optional inclusive minimum; it cannot exceed plotAreaTo.

## `plotAreaTo` (type: `integer`):

Used when Mode is discoverHomes, discoverPlots, or discoverLeisurePlots. Optional inclusive maximum; it cannot be lower than plotAreaFrom.

## `viewingDates` (type: `array`):

Used when Mode is one of discoverHomes, discoverNewBuildings, discoverLeisureHomes, and discoverAbroad. Enter one or more unique real calendar dates as YYYYMMDD; the runtime will encode each date as a repeated FINN viewing parameter.

## `propertyConditions` (type: `array`):

Used when Mode is discoverHomes or discoverLeisureHomes.

## `ownershipTypes` (type: `array`):

Used when Mode is discoverHomes or discoverNewBuildings.

## `sellerTypes` (type: `array`):

Used only when Mode is discoverHomes.

## `videoTypes` (type: `array`):

Used when Mode is discoverHomes, discoverLeisureHomes, or discoverAbroad.

## `floors` (type: `array`):

Used only when Mode is discoverHomes.

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

Used when Mode is discoverHomes or discoverNewBuildings. The stable FINN mapping accepts A through G even when current inventory hides zero-count values.

## `leisureSituations` (type: `array`):

Used when Mode is discoverLeisureHomes or discoverAbroad.

## `plotOwned` (type: `boolean`):

Used when Mode is discoverLeisureHomes or discoverAbroad. Enable to send FINN's true-only Selveiet filter; false is treated as omitted.

## `homesLocations` (type: `array`):

Used only when Mode is discoverHomes. Select unique exact identifiers from this mode's current FINN location taxonomy. Mixed hierarchy levels are allowed.

## `homesSort` (type: `string`):

Used only when Mode is discoverHomes. Omit it to preserve FINN's default ordering.

## `homesLifecycles` (type: `array`):

Used only when Mode is discoverHomes.

## `homesPropertyTypes` (type: `array`):

Used only when Mode is discoverHomes.

## `homesFacilities` (type: `array`):

Used only when Mode is discoverHomes.

## `newBuildingLocations` (type: `array`):

Used only when Mode is discoverNewBuildings. Select unique exact identifiers from this mode's current FINN location taxonomy. Mixed hierarchy levels are allowed.

## `newBuildingSort` (type: `string`):

Used only when Mode is discoverNewBuildings. Omit it to preserve FINN's default ordering.

## `newBuildingLifecycles` (type: `array`):

Used only when Mode is discoverNewBuildings.

## `newBuildingPropertyTypes` (type: `array`):

Used only when Mode is discoverNewBuildings.

## `newBuildingFacilities` (type: `array`):

Used only when Mode is discoverNewBuildings.

## `leisureHomeLocations` (type: `array`):

Used only when Mode is discoverLeisureHomes. Select unique exact identifiers from this mode's current FINN location taxonomy. Mixed hierarchy levels are allowed.

## `leisureHomeSort` (type: `string`):

Used only when Mode is discoverLeisureHomes. Omit it to preserve FINN's default ordering.

## `leisureHomeLifecycles` (type: `array`):

Used only when Mode is discoverLeisureHomes.

## `leisureHomePropertyTypes` (type: `array`):

Used only when Mode is discoverLeisureHomes.

## `leisureHomeFacilities` (type: `array`):

Used only when Mode is discoverLeisureHomes.

## `abroadLocations` (type: `array`):

Used only when Mode is discoverAbroad. Select unique exact identifiers from this mode's current FINN location taxonomy. Mixed hierarchy levels are allowed.

## `abroadSort` (type: `string`):

Used only when Mode is discoverAbroad. Omit it to preserve FINN's default ordering.

## `abroadLifecycles` (type: `array`):

Used only when Mode is discoverAbroad.

## `abroadPropertyTypes` (type: `array`):

Used only when Mode is discoverAbroad.

## `abroadFacilities` (type: `array`):

Used only when Mode is discoverAbroad.

## `plotLocations` (type: `array`):

Used only when Mode is discoverPlots. Select unique exact identifiers from this mode's current FINN location taxonomy. Mixed hierarchy levels are allowed.

## `plotSort` (type: `string`):

Used only when Mode is discoverPlots. Omit it to preserve FINN's default ordering.

## `leisurePlotLocations` (type: `array`):

Used only when Mode is discoverLeisurePlots. Select unique exact identifiers from this mode's current FINN location taxonomy. Mixed hierarchy levels are allowed.

## `leisurePlotSort` (type: `string`):

Used only when Mode is discoverLeisurePlots. Omit it to preserve FINN's default ordering.

## Actor input object example

```json
{
  "mode": "discoverHomes",
  "propertyUrl": "https://www.finn.no/realestate/homes/ad.html?finnkode=123456789",
  "query": "Oslo",
  "page": 1,
  "mapAreaPolygon": [
    {
      "latitude": 61.54334,
      "longitude": 9.83717
    },
    {
      "latitude": 59.45027,
      "longitude": 9.98702
    },
    {
      "latitude": 59.7158,
      "longitude": 11.69149
    },
    {
      "latitude": 61.43605,
      "longitude": 11.65403
    },
    {
      "latitude": 61.54334,
      "longitude": 9.83717
    }
  ],
  "mapAreaRadius": {
    "latitude": 63.277425343347915,
    "longitude": 11.183341344287783,
    "radiusMeters": 38774
  },
  "viewingDates": [
    "20260719",
    "20260720"
  ]
}
```

# Actor output Schema

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

Open the default Dataset to inspect the discovery page envelope or property-detail record produced by the selected mode.

# 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 = {
    "mode": "discoverHomes"
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawlstone/finn-property-sales-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 = { "mode": "discoverHomes" }

# Run the Actor and wait for it to finish
run = client.actor("crawlstone/finn-property-sales-scraper").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "mode": "discoverHomes"
}' |
apify call crawlstone/finn-property-sales-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=crawlstone/finn-property-sales-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/3Qt4FBTnmdKSKyC4J/builds/T2iemrfaHqoSwHQ2Q/openapi.json
