French Buildings API — RNB Building ID, Address, Parcel avatar

French Buildings API — RNB Building ID, Address, Parcel

Pricing

from $1.00 / 1,000 building returneds

Go to Apify Store
French Buildings API — RNB Building ID, Address, Parcel

French Buildings API — RNB Building ID, Address, Parcel

Returns French buildings from the national register (RNB) by address, parcel, point or ID: ID-RNB, status, footprint, addresses, parcels, BD TOPO/BDNB ids; failed and unchanged rows are never charged. Not affiliated with or endorsed by the RNB, IGN or the French government.

Pricing

from $1.00 / 1,000 building returneds

Rating

0.0

(0)

Developer

COMPASS DEV

COMPASS DEV

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Share

Returns French building records from the national building register (RNB) — ID-RNB, status, location, footprint, addresses, cadastral parcels and BD TOPO / BDNB ids — by ID-RNB, address, cadastral parcel, point or commune, and is never charged for failed, no-data or unchanged rows.

Give it ID-RNB building ids, French postal addresses, cadastral parcel ids, points (latitude,longitude) or commune INSEE codes; get one flat row per building from the RNB (Référentiel National des Bâtiments), France's public register that gives every building a stable identifier. Built for property, energy and insurance data work, spreadsheets, GIS and AI agents that need "which building is this, and what are its ids?" without handling the API's paging, geocoding or formats. Not affiliated with or endorsed by the RNB, IGN or the French government.

What it does

  • Address → building: the address is matched in the BAN (France's national address base) and the buildings at that address are returned, with the match score.
  • Parcel → buildings: the buildings on a cadastral parcel, largest share first.
  • Point → buildings: the buildings within a radius of a latitude,longitude point, nearest first, with their distance.
  • ID-RNB → building: the full record of a known building; BAN key → buildings: the buildings linked to an address key; commune → buildings: a commune's buildings by INSEE code.
  • Every building row carries its ID-RNB, status (constructed, notUsable, demolished), point, footprint as GeoJSON, its addresses and BAN keys, its ids in IGN's BD TOPO and in the BDNB and, on request, its cadastral parcels.
  • Watch mode (give a watch list name in stateName): remembers every building and returns only:
    • baseline: the first run of the list;
    • new: a building the list did not have (for a commune: a building added to the register);
    • changed: a tracked field changed (status, addresses, footprint, ids or parcels; changedFields and previousValues say what and from what);
    • unchanged buildings are free and left out (includeUnchanged: true returns them as free rows).
    • A watch run with nothing new or changed returns exactly one free no_data row that says so.
  • No personal data: the RNB holds buildings, not owners. The users who validated a building (validated_by in the API) are never read into a row.
  • You are never charged for failed results: failed, no_data and unchanged rows are free.

Quick start

{ "queries": ["9QX7W3BF6RP6", "11 Allee du Garde, 33360 Cénac", "33118000AH0084"] }

A point (nearest buildings within 30 m) and a commune's buildings, with their cadastral parcels:

{ "queries": ["44.7925,-0.4470"], "inseeCodes": ["33118"], "withPlots": true, "maxBuildingsPerQuery": 50 }

Watch a portfolio of buildings for status, address or footprint changes (the first run is the baseline):

{ "queries": ["9QX7W3BF6RP6", "ZVZJBSDMATWR"], "stateName": "my-buildings" }

Input

FieldTypeDefaultDescription
querieslist of strings— (prefilled with an ID-RNB, an address and a parcel)One entry per line: an ID-RNB (12 characters), a French postal address, a cadastral parcel id (14 characters), latitude,longitude, or a BAN address key. Never a URL. A 5-digit code alone is refused (postal code or INSEE code?): use inseeCodes
inseeCodeslist of strings—Communes by INSEE code (not postal code), e.g. 33118, 2A004
withPlotsbooleanfalseAlso return the cadastral parcels each building intersects (ID-RNB, BAN key and commune entries)
radiusMetersinteger 0–1,00030Point entries: the search radius
minScorenumber 0–10.8Address entries: the lowest BAN match score (the RNB's own default)
maxBuildingsPerQueryinteger 1–10,000100Most buildings returned for one entry
modewatch or export—Empty: watch when stateName is given, otherwise export. An explicit mode wins
stateNamestring—Watch list name. Watch mode without a name uses the list default
includeUnchangedbooleanfalseWatch: also return unchanged buildings (free)
maxItemsinteger 1–100,0001000Most charged buildings per run; in watch mode the rest come in the next run

Output

{
"status": "ok",
"attempts": 1,
"error": null,
"input": "16 Avenue de Mons, 33360 Cénac",
"mode": "export",
"watchList": null,
"dropReason": null,
"queryType": "address",
"rnbId": "9QX7W3BF6RP6",
"buildingStatus": "constructed",
"isActive": true,
"latitude": 44.79249603125738,
"longitude": -0.446996046489425,
"shapeType": "MultiPolygon",
"shapeGeoJson": "{\"type\":\"MultiPolygon\",\"coordinates\":[[[[-0.4471,44.7924],[-0.4469,44.7925],[-0.4468,44.7924],[-0.4471,44.7924]]]]}",
"addresses": ["16 Avenue de Mons, 33360 Cénac"],
"banKeys": ["33118_4999_00016"],
"streetNumber": "16",
"street": "Avenue de Mons",
"postalCode": "33360",
"city": "Cénac",
"inseeCode": "33118",
"bdtopoIds": ["BATIMENT0000000255605144"],
"bdnbIds": ["bdnb-bc-51DW-XJQH-TUAX"],
"parcels": null,
"mainParcelId": null,
"distanceMeters": null,
"banScore": 0.9612,
"matchedBanKey": "33118_4999_00016",
"parcelCoverRatio": null,
"changeType": null,
"changedFields": null,
"previousValues": null,
"url": "https://rnb.beta.gouv.fr/carte?q=9QX7W3BF6RP6",
"source": "Référentiel National des Bâtiments (RNB), rnb-api.beta.gouv.fr. Licence Ouverte 2.0 (Etalab): source RNB, retrieved on the scrapedAt date.",
"license": "Licence Ouverte / Open Licence 2.0 (Etalab)",
"licenseUrl": "https://www.etalab.gouv.fr/licence-ouverte-open-licence/",
"scrapedAt": "2026-10-03T10:00:00.000Z"
}
StatusMeaningCharged?
okA building returnedExport: yes. Watch: baseline, new and changed yes; unchanged no
no_dataNo building for the entry (an unknown ID-RNB, an address the BAN didn't match closely, an empty parcel or point), or nothing new since the last run (error says which)No
failedInvalid entry, or no answer after retries (error says why)No

The key-value store holds RUN_REPORT (counts, charged and free rows, requests, stop reason), PROGRESS (the export resume list) and, when something fails, the raw response (SNAPSHOT_*, validators' usernames removed).

Use it from AI agents

One clear main input, queries; every row has status, error, rnbId, url and scrapedAt. Call it through the Apify API, the Apify MCP server (mouadapi/france-buildings) or x402 agentic payments. Copy-paste call (your Apify token in APIFY_TOKEN):

curl -s -X POST "https://api.apify.com/v2/acts/mouadapi~france-buildings/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"queries": ["9QX7W3BF6RP6", "16 Avenue de Mons, 33360 Cénac"]}'
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('mouadapi/france-buildings').call({ queries: ['9QX7W3BF6RP6', '16 Avenue de Mons, 33360 Cénac'] });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);

Output fields

FieldTypeDescription
statusstring (or null)ok = a building returned (charged in export mode and for baseline, new and changed rows; free when unchanged); no_data = no building for the entry, or nothing new since the last run (free); failed = invalid entry or no answer (free)
attemptsinteger (or null)Requests made for this entry's page (retries included)
errorstring (or null)Why a row is no_data or failed; null on ok rows
inputstring (or null)The entry that produced this row (an ID-RNB, an address, a parcel, a point, a BAN key or a commune code)
modestring (or null)watch or export
watchListstring (or null)Watch list name (watch mode); null in export mode
dropReasonstring (or null)Kept for the shared row format; always null here (no record of this source is a person)
queryTypestring (or null)How the entry was read: rnb_id, address, parcel, point, ban_key or commune
rnbIdstring (or null)The building's national identifier in the RNB (12 characters, stable for the building's whole life)
buildingStatusstring (or null)constructed, notUsable or demolished (the RNB's status of the building)
isActiveboolean (or null)true when the ID-RNB is a real building (a demolished building stays active); false when the ID was deactivated as not a building
latitudenumber (or null)The building's point, WGS 84 (EPSG:4326)
longitudenumber (or null)The building's point, WGS 84 (EPSG:4326)
shapeTypestring (or null)The footprint's GeoJSON type: Polygon, MultiPolygon or Point
shapeGeoJsonstring (or null)The RNB's best known outline of the building, as GeoJSON text (WGS 84); not a reference footprint
addressesarray (or null)The building's addresses from the BAN (France's national address base), as text
banKeysarray (or null)The BAN interoperability key of each address (the same order as addresses)
streetNumberstring (or null)First address: the number, with its repetition index (bis, ter…) when there is one
streetstring (or null)First address: the street
postalCodestring (or null)First address: the postal code
citystring (or null)First address: the commune
inseeCodestring (or null)First address: the commune's INSEE code
bdtopoIdsarray (or null)The building's ids in IGN's BD TOPO
bdnbIdsarray (or null)The building's ids in the BDNB (national building database)
parcelsarray (or null)With "Include cadastral parcels": the parcels the building intersects and the share of the building on each (a geometric link, not a fiscal one); null otherwise
mainParcelIdstring (or null)With "Include cadastral parcels": the parcel holding the largest share of the building
distanceMetersnumber (or null)Point entries: the building's distance from the point, in metres
banScorenumber (or null)Address entries: the BAN geocoding score of the address matched (0 to 1)
matchedBanKeystring (or null)Address entries: the BAN address key the address matched
parcelCoverRationumber (or null)Parcel entries: the share of the building on the parcel (0 to 1); buildings come largest share first
changeTypestring (or null)Watch mode: baseline (first run of the list), new, changed or unchanged (free); null in export mode
changedFieldsstring (or null)Watch mode: tracked fields that changed, comma-separated
previousValuesstring (or null)Watch mode: the changed fields' previous values, as JSON
urlstring (or null)The building on the RNB's public map
sourcestring (or null)Source and attribution (Licence Ouverte 2.0 asks reusers to name the source and the date)
licensestring (or null)Licence of the data
licenseUrlstring (or null)Licence URL
scrapedAtstring (or null)When the row was made (ISO 8601); the date to cite with the source

Pricing

Pay per event: one building event per returned building (export: every building; watch: baseline, new and changed rows). no_data, failed and unchanged rows are free.

PlanPrice per 1,000 buildings
Free$1.50
Bronze$1.30
Silver$1.15
Gold (and higher)$1.00

Apify also charges its small per-run start event. There are no usage fees on top.

Limits

  • One request at a time, about 3 a second at most (the RNB publishes a limit of 20 requests a second per IP address). If the RNB answers HTTP 429, the run pauses 60, 120 and 240 seconds on the same connection, then stops with free failed rows. No other IP or proxy is ever tried.
  • At most 1,000 entries per run and 10,000 buildings per entry. For millions of buildings, the RNB's national and departmental export files on data.gouv.fr suit better.

Known issues

  • The RNB API is in alpha: its formats may change. The daily canary checks this Actor against the live API.
  • A parcel's buildings come from a geometric intersection, not a fiscal link: a building that overlaps two parcels is returned for both, with its share on each.
  • An address that the BAN matches with a score under minScore returns a free no_data row with the score.

FAQ

Is this the official RNB API? No: it is an Apify Actor that calls the RNB's public API and returns its records as flat rows. Not affiliated with or endorsed by the RNB, IGN or the French government.

Are owners' names returned? No. The RNB holds buildings and addresses, not owners, and the users who validated a building are never read into a row.

Why was my 5-digit code refused? It can be a postal code or a commune's INSEE code (Cénac is 33360 by post and 33118 by INSEE). Put an INSEE code in inseeCodes, or write the full address in queries.

Data and licence