DVF Property Sales API (Valeurs Foncières): Price/m², GPS avatar

DVF Property Sales API (Valeurs Foncières): Price/m², GPS

Pricing

from $0.43 / 1,000 property sales

Go to Apify Store
DVF Property Sales API (Valeurs Foncières): Price/m², GPS

DVF Property Sales API (Valeurs Foncières): Price/m², GPS

Official French property sales (DVF / valeurs foncières) by commune, postal code or department: date, price, surface, rooms, price per m², GPS, median €/m² per commune. No login. MCP-ready for Claude, Cursor, ChatGPT and AI agents. Pay per result, empty results free. $0.50 per 1,000 sales.

Pricing

from $0.43 / 1,000 property sales

Rating

0.0

(0)

Developer

ABM

ABM

Maintained by Community

Actor stats

0

Bookmarked

3

Total users

2

Monthly active users

2 days ago

Last modified

Security

Limited permissions

Share

DVF Property Sales API: France sold prices (Valeurs Foncières)

$0.50 per 1,000 property sales. Pay per result. No API key, no login, no monthly rental. Errors, unknown places and empty searches cost nothing.

This Actor returns official French property sales from DVF (Demandes de valeurs foncières, published by the tax administration DGFiP and geolocated by Etalab). Search by commune, postal code or department, filter by year, property type, surface, price, rooms or price per m², and get one clean JSON object per sale: date, price, built surface, Carrez surface, rooms, land surface, price per m², address, GPS coordinates and cadastral parcels. Optionally, it computes the median price per m² per commune for you.

Raw DVF files are hard to use: one sale is spread over several rows (one per unit, parcel and land type), the price is repeated on every row, and surfaces get double-counted. This Actor merges the rows into one sale, removes the duplicates, and only computes a price per m² when it makes sense.

How much does it cost?

WhatPrice
One sale delivered (sale event)$0.0005
1,000 sales$0.50
10,000 sales (e.g. every apartment sold in Toulouse in two years)$5.00
Statistics per commune (includeStatistics)free
Unknown commune, empty result, source errorfree

Example: all apartment sales in Bordeaux in 2024 (about 4,000 sales) cost about $2. Set maxResults to cap your spend; the run stops cleanly when your budget is reached.

What data do you get?

FieldDescription
saleIdUnique DVF transaction id
saleDate, yearDate of the deed
saleTypesale, offPlan (VEFA), auction, buildingLand, exchange, expropriation
pricePrice in EUR (whole transaction)
propertyTypeapartment, house, commercial, outbuilding, land
builtSurface, carrezSurface, rooms, landSurfaceSurfaces in m², main rooms
pricePerSqmPrice / built surface (price / land surface for land)
isMultiUnit, unitCount, outbuildingCount, lotCountSeveral flats sold together, parking spaces, cellars…
address, fullAddress, postalCode, communeName, communeCode, departmentCodeLocation
latitude, longitudeCoordinates of the parcel
parcelIds, unitsCadastral parcels and the detail of every unit
summaryOne plain-text sentence ready for LLMs and RAG

Input example

{
"postalCodes": ["31000"],
"years": ["2024"],
"propertyTypes": ["apartment"],
"maxResults": 20
}

Other ways to search:

{
"communes": ["Saint-Étienne", "Lyon", "Saint-Denis (93)", "33063"],
"departments": ["2A"],
"years": ["2023", "2024"],
"propertyTypes": ["house"],
"minSurface": 80,
"maxPrice": 400000,
"minPricePerSqm": 500,
"includeStatistics": true
}
  • communes: names or INSEE codes. Paris, Lyon and Marseille include all their arrondissements. For homonyms, add the department: "Saint-Denis (93)".
  • postalCodes: only sales whose address has that postal code.
  • departments: codes ("31", "2A", "971") or names ("Gironde").
  • years: empty = latest year available. dateFrom / dateTo narrow it down to the day.
  • Results are sorted newest first.

Output example

{
"saleId": "2024-412873",
"saleDate": "2024-12-20",
"year": 2024,
"saleType": "sale",
"saleTypeLabel": "Vente",
"price": 210000,
"propertyType": "apartment",
"propertyTypeLabel": "Appartement",
"builtSurface": 46,
"carrezSurface": 45.5,
"rooms": 2,
"landSurface": null,
"pricePerSqm": 4565.22,
"unitCount": 1,
"outbuildingCount": 1,
"lotCount": 3,
"isMultiUnit": false,
"address": "12B RUE DE METZ",
"fullAddress": "12B RUE DE METZ, 31000 Toulouse",
"postalCode": "31000",
"communeCode": "31555",
"communeName": "Toulouse",
"departmentCode": "31",
"latitude": 43.6003,
"longitude": 1.4477,
"parcelIds": ["31555000AB0001"],
"units": [
{"type": "apartment", "builtSurface": 46, "rooms": 2, "carrezSurface": 45.5, "parcelId": "31555000AB0001"},
{"type": "outbuilding", "builtSurface": null, "rooms": 0, "carrezSurface": null, "parcelId": "31555000AB0001"}
],
"summary": "Appartement sold on 2024-12-20 for 210 000 EUR, 46 m² built, 2 rooms, 4 565 EUR/m² - 12B RUE DE METZ, 31000 Toulouse.",
"sourceFile": "https://files.data.gouv.fr/geo-dvf/latest/csv/2024/departements/31.csv.gz",
"dataSource": "DVF - Demandes de valeurs foncières (DGFiP), geolocated by Etalab (geo-dvf)"
}

With includeStatistics: true, the key-value store record STATISTICS contains, per commune and property type:

{
"communeCode": "31555", "communeName": "Toulouse", "propertyType": "apartment",
"salesCount": 1000, "salesUsedForPricePerSqm": 942,
"medianPricePerSqm": 3610.5, "p25PricePerSqm": 2980.0, "p75PricePerSqm": 4312.4,
"meanPricePerSqm": 3702.1, "medianPrice": 189000, "medianSurface": 52,
"firstSaleDate": "2024-07-01", "lastSaleDate": "2024-12-31"
}

Statistics are computed on the sales delivered in the run (single-unit sales only for price per m²).

Use cases

1. Estate agent: comparable sales for a valuation

An agent in Toulouse values a 3-room flat of 65 m². Before the visit, they pull every comparable sale of the year in the same postal code.

Input:

{"postalCodes": ["31400"], "years": ["2024"], "propertyTypes": ["apartment"], "minRooms": 3, "maxRooms": 3, "minSurface": 55, "maxSurface": 75, "excludeMultiUnitSales": true, "includeStatistics": true}

Output (extract):

[{"saleDate": "2024-11-14", "price": 238000, "builtSurface": 66, "rooms": 3, "pricePerSqm": 3606.06, "address": "8 RUE ...", "latitude": 43.58, "longitude": 1.46}]

Next: about 150 sales, about $0.08. The median price per m² from STATISTICS goes into the valuation report, and the sales go on a map in Google Sheets or Looker Studio.

2. Investor or proptech: monthly market watch on several cities

A rental investor follows small flats in 5 cities. A scheduled run with onlyNew only returns the sales added since the last DVF release (April and October).

Input:

{"communes": ["Rennes", "Nantes", "Angers", "Le Mans", "Tours"], "years": ["2025"], "propertyTypes": ["apartment"], "maxSurface": 35, "onlyNew": true, "includeStatistics": true}

Output (extract):

[{"communeName": "Angers", "saleDate": "2025-06-27", "price": 98000, "builtSurface": 28, "pricePerSqm": 3500}]

Next: about 3,000 new sales per release, about $1.50. A Make scenario writes them to Google Sheets and sends the median price per m² per city to Slack.

3. Data analyst or local authority: land and house prices on a whole department

A planning office studies building land prices in Haute-Savoie over 3 years.

Input:

{"departments": ["74"], "years": ["2022", "2023", "2024"], "propertyTypes": ["land"], "saleTypes": ["sale", "buildingLand"], "minSurface": 300, "maxResults": 0, "includeStatistics": true}

Output (extract):

[{"communeName": "Annecy", "propertyType": "land", "landSurface": 612, "price": 245000, "pricePerSqm": 400.33, "parcelIds": ["74010000AK0123"]}]

Next: about 6,000 sales, about $3. The STATISTICS record gives the median land price per m² per commune for the report; coordinates and parcels go into QGIS.

4. AI agent: answer "how much do flats sell for in Lyon 3e?"

An assistant calls the Actor through MCP with {"postalCodes": ["69003"], "propertyTypes": ["apartment"], "maxResults": 200, "includeStatistics": true} and answers from the summary fields and the median, for $0.10.

Use via the API

Python:

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("<USERNAME>/dvf-property-sales").call(run_input={
"postalCodes": ["31000"], "years": ["2024"], "propertyTypes": ["apartment"], "maxResults": 100,
})
for sale in client.dataset(run["defaultDatasetId"]).iterate_items():
print(sale["saleDate"], sale["price"], sale["builtSurface"], sale["pricePerSqm"])

JavaScript:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('<USERNAME>/dvf-property-sales').call({
communes: ['Bordeaux'], years: ['2024'], propertyTypes: ['house'], maxResults: 100,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.map((s) => `${s.saleDate} ${s.price} EUR ${s.pricePerSqm} EUR/m²`));

Use with AI agents (MCP)

The Actor works as a tool in Claude, Cursor, ChatGPT and any MCP client through the Apify MCP server (https://mcp.apify.com). Add <USERNAME>/dvf-property-sales to your tools. The agent passes a commune, postal code or department and gets structured sales back, each with a plain-text summary.

Integrations

  • Google Sheets: export the dataset, or use the Apify Google Sheets integration to append new sales after each scheduled run.
  • Make / Zapier / n8n: "Run Actor", then "Get dataset items". Example n8n flow: Schedule (1st of the month), Apify Run Actor (onlyNew: true), Google Sheets Append, then Slack with the median price per m².
  • Webhooks: get notified when a run finishes.
  • Export formats: JSON, CSV, Excel, XML, RSS, HTML table.

FAQ

Where does the data come from? From the official open data "Demandes de valeurs foncières géolocalisées" (Etalab, data.gouv.fr), Licence Ouverte 2.0. It's the same data the tax administration publishes, with coordinates added.

How recent is it? DVF is updated twice a year (April and October) and covers the last 5 full years, currently 2021 to 2025. The most recent months are not available yet.

Why is pricePerSqm null sometimes? When the sale mixes several kinds of property (e.g. a house and a shop), or when there is no built surface. For multi-unit sales (isMultiUnit: true), the price per m² is calculated on the total surface but left out of the statistics.

Why can a postal-code search miss a sale? Bare land parcels often have no address in DVF. Search by commune to get them.

Is it legal? Yes. DVF is public open data published by the French State. Using it to re-identify people is forbidden by law (article R112 A-3 of the Livre des procédures fiscales), and the data contains no buyer or seller names.

Do I pay for empty results? No. You only pay for sales delivered to your dataset.

Limits

  • No data for Alsace-Moselle (departments 57, 67, 68) or Mayotte (976). DVF doesn't cover them.
  • Years before the 5-year window (e.g. 2019) are not online anymore.
  • The price is the price of the whole transaction, as declared at the notary (furniture and agency fees may or may not be included).
  • Coordinates are those of the cadastral parcel, not the exact building entrance.
  • A whole department returns tens of thousands of sales. Use filters and maxResults to control your cost.