DVF Property Sales API (Valeurs Foncières): Price/m², GPS
Pricing
from $0.43 / 1,000 property sales
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
Maintained by CommunityActor stats
0
Bookmarked
3
Total users
2
Monthly active users
2 days ago
Last modified
Categories
Security
Limited permissionsShare
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?
| What | Price |
|---|---|
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 error | free |
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?
| Field | Description |
|---|---|
saleId | Unique DVF transaction id |
saleDate, year | Date of the deed |
saleType | sale, offPlan (VEFA), auction, buildingLand, exchange, expropriation |
price | Price in EUR (whole transaction) |
propertyType | apartment, house, commercial, outbuilding, land |
builtSurface, carrezSurface, rooms, landSurface | Surfaces in m², main rooms |
pricePerSqm | Price / built surface (price / land surface for land) |
isMultiUnit, unitCount, outbuildingCount, lotCount | Several flats sold together, parking spaces, cellars… |
address, fullAddress, postalCode, communeName, communeCode, departmentCode | Location |
latitude, longitude | Coordinates of the parcel |
parcelIds, units | Cadastral parcels and the detail of every unit |
summary | One 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/dateTonarrow 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 ApifyClientclient = 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
maxResultsto control your cost.