# Property Valuation API - AVM, Rent Estimate, Sold Prices (`nabeelbaghoor/property-valuation-data-api`) Actor

Value any European residential address for sale or rent with a confidence range, search live listings and recorded sold prices around any point, compute market statistics and percentile ranks, and read location scores and demographics.

- **URL**: https://apify.com/nabeelbaghoor/property-valuation-data-api.md
- **Developed by:** [Nabeel Hassan](https://apify.com/nabeelbaghoor) (community)
- **Categories:** Real estate, Business, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $18.00 / 1,000 property valuation returneds

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

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

## What's an Apify Actor?

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

## How to integrate an Actor?

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

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

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

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

# README

## Property Valuation API - AVM, Rent Estimate, Sold Prices

Value any European residential address for sale or for rent with a confidence range, and pull the listings, recorded sold prices, market statistics and neighbourhood scores around it from the same actor.

### What this actor does

- **Automated valuation for sale or rent.** Paste addresses, get a sale price with a lower and upper bound, or a gross and a net monthly rent each with their own bounds. Every valuation carries the provider's confidence grade, the coordinates it resolved the address to, and a location score.
- **Value the same property at several dates.** Give a list of valuation dates and get one row per property per date, which is how to measure what a portfolio has done rather than only what it is worth today.
- **Live listings around any point.** Asking price and price per square metre, days on market, listing start and end dates, price change count, agency contact, images, and a flag saying whether the provider placed the listing at its real address or only in the right area.
- **Recorded sold prices.** Actual registered transactions with the date, price, price per square metre and per square foot, plus the property attributes on file including land area, bedrooms, bathrooms, leasehold status, energy label and planning use.
- **Market statistics and percentile ranks.** Mean, count and any percentile of price, rent, area, rooms or days on market, grouped by month, quarter, year or trailing 90 days. Ask for the percentile rank of a specific price and the provider tells you where it falls in its market.
- **Location scores.** Nine measures for a point - overall location, catering, family, health, leisure, shopping, view, noise and nuisance - each between 0 and 1 and each oriented so that higher is better.
- **Demographics by administrative division.** One socio-economic series at a time, returned per division, year and subtype with both the absolute figure and its share of the division.
- **Pay per result.** You are charged for rows that carry a real record. Addresses the provider cannot place are free.

### Bring your own credentials

This provider authenticates with an **account username and password** rather than an API key, and exchanges them for an access token that lasts twelve hours. Paste yours into the API username and API password fields, or set them as the `DATA_API_USERNAME` and `DATA_API_PASSWORD` secrets. If you keep one combined secret across actors, `DATA_API_KEY` set to `username:password` also works.

Both halves are stored as secrets. The actor signs in once per run rather than once per request, because the provider rate limits repeated authentication specifically, and it refreshes the token silently if a long run outlasts it.

### Coverage is licensed per country

Every request names the country it is about, and your account is licensed for the countries you bought. A country outside your plan comes back as a refusal rather than as an empty result, and the actor reports that as a plan problem rather than a bad credential.

### Example output

```json
{
  "recordType": "valuation",
  "requested": "Gerechtigkeitsgasse 19, 8001 Zurich",
  "found": true,
  "valuationDate": "2026-09-01",
  "dealType": "sale",
  "salePrice": 1845000,
  "salePriceLower": 1705000,
  "salePriceUpper": 1985000,
  "currency": "CHF",
  "confidence": "good",
  "locationScore": 0.91,
  "latitude": 47.36925,
  "longitude": 8.531118,
  "statusCode": 200,
  "statusMessage": "OK"
}
```

### FAQ

#### How accurate is an automated valuation?

Every valuation comes with a lower and upper bound and a confidence grade of poor, medium or good, so you can judge it rather than trust it. A good grade with a tight range means the provider had comparable evidence nearby; a poor grade with a wide range means it did not. Supplying the building year, living area and room count materially narrows the range, because those are the strongest inputs the model has.

#### What is the difference between gross rent and net rent?

Gross rent includes the service charges a tenant pays on top of the base rent; net rent excludes them. They are separate fields in the output because they are different figures, and which one a local market quotes varies by country. A rent valuation returns both, each with its own range.

#### Why does the output not have a single "value" column?

Because the provider's own `value` field is deprecated and shadows three different numbers - the sale price, the gross rent and the net rent. Reading it would work today and silently return the wrong figure once it is withdrawn, so this actor reads each price by its own name and keeps them in separate columns.

#### How do I get sold prices rather than asking prices?

Use recorded sale search. Listings are what a property was advertised at; recorded sales are what it actually changed hands for, taken from the registry. The two answer different questions, and comparing them for the same area is how you measure the gap between asking and achieved. Recorded sale coverage is strongest in Austria, France and the UK.

#### Can I tell whether an asking price is high for its area?

Yes, in one request. Use listing statistics, choose the percentile rank type, and give the asking price as the percentile value. The provider answers with where that price falls in the distribution, so 78 means it is higher than 78 percent of comparable listings.

#### How do I build a price time series for a neighbourhood?

Use either statistics mode, group by the transaction date or the listing start date, and set the grouping period. Trailing 90 days smooths a thin market better than a calendar month does, because a month with four sales in it produces a median that moves for no real reason.

#### Are the listing coordinates exact?

The row tells you. The `preciselyLocated` flag is true when the provider placed the listing at its real address and false when it could only place it in the right area. Mapping an approximate pin as though it were exact is the usual mistake with listing data.

#### Why are the noise and nuisance scores high in quiet places?

All nine location scores are oriented the same way, so a higher number is better on every one of them. A noise score of 0.95 means the location is quiet, not that it is loud. They are also read from the provider's nested score block rather than from the top level copy, so a score somebody has overridden on their own account is reported as overridden instead of passing as a measured one.

#### How many properties can I value in one request?

The provider caps a call at fifty valuations, counted as properties multiplied by dates. So fifty addresses on one date is one request, and the same fifty on three dates is three. The actor works that out and batches accordingly; you set the addresses and the dates and it sizes the requests.

#### What does it cost?

Pricing is pay per result: 0.018 USD per valuation, 0.01 USD per listing or recorded sale, 0.01 USD per location scored, and 0.008 USD per market statistic or demographic figure, with Apify platform usage included. Rows the provider found nothing for are not charged. You also need your own account with the data provider, which bills on its own plans.

#### Does the actor fail if my credentials are wrong?

No. Missing credentials, a rejected username or password, an endpoint or country outside your plan, or an empty input all end the run cleanly with a message saying what to change. Only a real outage or a bug fails the run.

### Keyword map

property valuation API, AVM API, automated valuation model, European property data API, rent estimate API, sold house prices API, property price per square metre, real estate market statistics API, Swiss property data, German property data, French property data, UK sold prices, property listings API Europe, days on market, location score API, neighbourhood scores, socio-economic data API, property confidence range, gross rent net rent

# Actor input Schema

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

Valuation returns a sale price or a gross and net rent for each address with a confidence grade and a range. Listing search and recorded sale search return what is around a point. The two statistics modes answer the same questions in aggregate. Location scores rates a point across nine neighbourhood measures. Demographics reads one socio-economic series.

## `countryCode` (type: `string`):

Required in every mode. The two letter country the request is about, for example CH, DE, FR, AT, NL, BE or UK. Coverage is licensed per country, so a country outside your plan is refused rather than returning nothing.

## `addresses` (type: `array`):

Valuation and location scores modes, and the centre point for a search. One address per line, written as street and number, then comma, then post code and city, for example Gerechtigkeitsgasse 19, 8001 Zurich. A line that cannot be split is reported rather than guessed at.

## `latitude` (type: `string`):

An alternative to an address in every mode that takes one. Give a longitude with it.

## `longitude` (type: `string`):

An alternative to an address in every mode that takes one. Give a latitude with it.

## `radiusMeters` (type: `integer`):

Listing and recorded sale search. How far from the point to search, in metres. 5000 is five kilometres.

## `dealType` (type: `string`):

Valuation, listing search and listing statistics. Sale returns a sale price; rent returns a gross and a net monthly rent, which are different figures and both are kept in the output.

## `valuationDates` (type: `array`):

Valuation mode. One date per line as YYYY-MM-DD, to value the same property at several points in time. Leave empty for today. The provider caps a call at fifty valuations counted as properties multiplied by dates, so three dates means fewer addresses per request.

## `propertyTypeCode` (type: `string`):

Describes the property in valuation mode and filters in the search and statistics modes.

## `propertyTypeSubcode` (type: `string`):

An optional refinement of the property type in the provider's own spelling, for example apartment\_normal, apartment\_penthouse or house\_detached.

## `buildingYear` (type: `integer`):

Valuation mode. The year the building was completed. One of the strongest inputs to a valuation, so supply it when you have it.

## `livingArea` (type: `integer`):

Valuation mode. Interior floor area in square metres.

## `landArea` (type: `integer`):

Valuation mode, for houses. Plot size in square metres.

## `numberOfRooms` (type: `integer`):

Valuation mode. Room count as counted locally, which in several of these markets includes the living room and uses half steps.

## `numberOfBathrooms` (type: `integer`):

Valuation mode.

## `numberOfUnits` (type: `integer`):

Valuation mode, for a multi family house. How many dwellings the building contains.

## `annualRentIncome` (type: `integer`):

Valuation mode, for a multi family house. The building's current yearly rent roll, which the provider uses when valuing it as an investment.

## `balconyArea` (type: `integer`):

Valuation mode. Balcony or terrace area in square metres.

## `gardenArea` (type: `integer`):

Valuation mode. Private garden area in square metres.

## `numberOfIndoorParkingSpaces` (type: `integer`):

Valuation mode. Garage or underground spaces, which are valued differently from outdoor ones.

## `numberOfOutdoorParkingSpaces` (type: `integer`):

Valuation mode. Open or surface spaces.

## `floorNumber` (type: `integer`):

Valuation mode, for an apartment. Ground floor is 0.

## `hasLift` (type: `boolean`):

Describes the property in valuation mode. In listing search, leave this alone to ignore it: the filter is applied only when you set it either way.

## `energyLabel` (type: `string`):

Valuation mode. The building's energy rating in the local scheme, for example a, b, c or minergie in Switzerland.

## `quality` (type: `string`):

Valuation mode. How well appointed the property is. One grade is applied to the bathrooms, kitchen, flooring and windows together, which is the level of precision a list of addresses supports.

## `condition` (type: `string`):

Valuation mode. How well maintained the property is, applied to the bathrooms, kitchen, flooring and windows together.

## `returnScores` (type: `boolean`):

Valuation mode. On by default. Turn off only if you do not need the location score beside each valuation.

## `activeOnly` (type: `boolean`):

Listing search. Ticked keeps only what is on the market now. Leave it off to include withdrawn listings, which is how to study recent market history.

## `dateFrom` (type: `string`):

Keeps only records on or after this date, as YYYY-MM-DD. Applied to the listing start date in listing modes and to the transaction date in recorded sale modes.

## `dateTo` (type: `string`):

Keeps only records on or before this date, as YYYY-MM-DD.

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

Search modes. Applied to the sale price, or to the gross rent when the deal type is rent.

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

Search modes. Applied to the sale price, or to the gross rent when the deal type is rent.

## `priceCurrency` (type: `string`):

The currency the price filter is expressed in, for example CHF, EUR or GBP. Required by the provider whenever a price filter is set.

## `livingAreaMin` (type: `integer`):

Search modes. Interior floor area in square metres.

## `livingAreaMax` (type: `integer`):

Search modes. Interior floor area in square metres.

## `numberOfRoomsMin` (type: `integer`):

Search modes.

## `numberOfRoomsMax` (type: `integer`):

Search modes.

## `numberOfBathroomsMin` (type: `integer`):

Search modes.

## `numberOfBathroomsMax` (type: `integer`):

Search modes.

## `numberOfBedroomsMin` (type: `integer`):

Search modes. Bedrooms are recorded separately from rooms in the UK and France.

## `numberOfBedroomsMax` (type: `integer`):

Search modes.

## `buildingYearMin` (type: `integer`):

Search modes. A four digit year.

## `buildingYearMax` (type: `integer`):

Search modes. A four digit year.

## `hasParkingSpaces` (type: `boolean`):

Search modes. Leave this alone to ignore it; the filter is applied only when you set it either way.

## `isNew` (type: `boolean`):

Search modes. Leave this alone to ignore it; the filter is applied only when you set it either way.

## `orderBy` (type: `string`):

Search modes. Distance is measured from the reference address or point. The price and rent options only apply to the search they belong to.

## `orderDirection` (type: `string`):

Search modes.

## `statisticsMetrics` (type: `array`):

Statistics modes. Which measures to compute. Sale price and price per square metre work on both sides; gross and net rent and days on market are listing measures only.

## `statisticsTypes` (type: `array`):

Statistics modes. Mean and count are computed for every metric. Percentile needs a rank and percentile rank needs a value, both set below.

## `percentileRank` (type: `integer`):

Statistics modes, for the percentile type. Which percentile to return, so 50 is the median.

## `percentileValue` (type: `integer`):

Statistics modes, for the percentile rank type. Give a price or rent and the provider answers where it falls in the distribution, which is how to tell whether an asking price is high for its market.

## `divisionId` (type: `string`):

Statistics modes. Narrows the statistics to one division, for example a post code such as 8001. Leave empty for the whole country.

## `groupBy` (type: `string`):

Statistics modes. Returns one set of statistics per group instead of one overall, which is how to get a time series or a breakdown by size.

## `groupPeriod` (type: `string`):

Statistics modes, when grouping by a date. Trailing 90 days smooths a thin market better than a calendar month does.

## `socioEconomicType` (type: `string`):

Demographics mode. Which series to read, in the provider's own spelling, for example education\_levels, age\_distribution, household\_sizes, income or population.

## `divisionIds` (type: `array`):

Demographics mode. One division ID per line. Which identifiers apply depends on the level chosen below and on the country.

## `divisionLevel` (type: `string`):

Demographics mode. Which administrative level the IDs above belong to. Level 6 is roughly a municipality and level 100 a post code.

## `yearMin` (type: `integer`):

Demographics mode. The earliest year to include.

## `yearMax` (type: `integer`):

Demographics mode. The latest year to include.

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

The most rows this run will save and charge for. This is the spending control on both sides.

## `pageSize` (type: `integer`):

Search modes. How many rows to ask for at a time.

## `requestsPerMinute` (type: `integer`):

How fast to call the provider. Lower this if your plan is metered tightly.

## `baseUrl` (type: `string`):

Only set this if the provider has given you a different host. Leave empty to use the documented one.

## `apiUsername` (type: `string`):

Your own account username for the property valuation provider. This actor is bring your own credentials: it never uses anyone else's, and both halves are stored as secrets.

## `apiPassword` (type: `string`):

Your own account password for the property valuation provider. Exchanged once per run for an access token that lasts twelve hours, rather than sent with every request.

## Actor input object example

```json
{
  "mode": "valuation",
  "countryCode": "CH",
  "radiusMeters": 5000,
  "dealType": "sale",
  "propertyTypeCode": "apartment",
  "returnScores": true,
  "priceCurrency": "EUR",
  "orderBy": "distance",
  "orderDirection": "asc",
  "percentileRank": 50,
  "divisionLevel": "divisionsLevel6",
  "maxResults": 1000,
  "pageSize": 100,
  "requestsPerMinute": 120
}
```

# Actor output Schema

## `records` (type: `string`):

One row per record, alongside the address, point or division that produced it.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("nabeelbaghoor/property-valuation-data-api").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("nabeelbaghoor/property-valuation-data-api").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 '{}' |
apify call nabeelbaghoor/property-valuation-data-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nabeelbaghoor/property-valuation-data-api"
        }
    }
}
```

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/VmvIcnOh6jhavqEWM/builds/zQdYpAQnOUK7EdTcZ/openapi.json
