France Address Geocoder API (Géocodage BAN): INSEE, GPS avatar

France Address Geocoder API (Géocodage BAN): INSEE, GPS

Pricing

from $0.26 / 1,000 address founds

Go to Apify Store
France Address Geocoder API (Géocodage BAN): INSEE, GPS

France Address Geocoder API (Géocodage BAN): INSEE, GPS

Geocode French addresses in bulk with the official BAN (IGN Géoplateforme): normalized address, match score, INSEE code, postcode, GPS and Lambert 93. Reverse geocoding too. No API key, no login. MCP-ready for AI agents. Pay per result, not found is free. $0.30 per 1,000 addresses

Pricing

from $0.26 / 1,000 address founds

Rating

0.0

(0)

Developer

ABM

ABM

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Security

Limited permissions

Share

France Address Geocoder API: bulk geocoding with the official BAN (Géocodage d'adresses)

Turn French postal addresses into GPS coordinates, normalized addresses, INSEE municipality codes and postcodes, or turn coordinates back into the nearest address (reverse geocoding). The data comes from the Base Adresse Nationale (BAN), the official French address register, served by the IGN Géoplateforme (data.geopf.fr). When that endpoint is down, the actor switches to api-adresse.data.gouv.fr, which serves the same BAN data.

  • Price: $0.30 per 1,000 addresses found ($0.0003 per address). Not found, invalid and duplicate inputs are free.
  • No API key, no login, no monthly rental.
  • Bulk: thousands of addresses per run, about 1,000 addresses in under a minute.
  • Every result has a match score (0 to 1) so you can tell exact matches from approximate ones.
  • Ready for AI agents (MCP), the Apify API, Make, Zapier, n8n and Google Sheets.

How much does it cost?

You pay one address event ($0.0003) for each input that returns an official address. Nothing else is billed.

VolumeCost
100 addresses found$0.03
1,000 addresses found$0.30
10,000 addresses found$3.00
100,000 addresses found$30.00

If 1,000 inputs give 950 matches and 50 inputs are not found, you pay $0.285. With "Candidates per address" set to 5, you still pay once per input. If you set a maximum cost per run, the actor stops cleanly when it is reached and never delivers unpaid results.

What data do you get?

FieldExampleMeaning
query1 place du Capitole 31000 ToulouseYour input
queryTypeforward / reverseAddress → coordinates, or coordinates → address
statusfound / notFound / errorOutcome (only found is charged)
score0.9765BAN match score, from 0 to 1
label1 Place du Capitole 31000 ToulouseNormalized official address
resultTypehousenumberPrecision: housenumber, street, locality, municipality
houseNumber, street, name1, Place du CapitoleAddress parts
postalCode, city31000, Toulouse
inseeCode31555INSEE municipality code (code commune)
oldInseeCode, oldCityFormer municipality, after a merger
districtNameParis 2e ArrondissementArrondissement (Paris, Lyon, Marseille)
departmentCode, departmentName, region31, Haute-Garonne, Occitanie
latitude, longitude43.603872, 1.444053WGS84 (GPS)
lambert93X, lambert93Y574344.14, 6279551.2Official French projection (EPSG:2154)
distanceMeters38Reverse geocoding: distance to your point
banId, banAddressKey264c0325-…, 31555_1676_00001BAN identifiers, for joins with other datasets
sourcegeoplateformeEndpoint that answered
errorno address with score >= 0.7Reason when not found

Input example

{
"addresses": [
"1 place du Capitole 31000 Toulouse",
"12 rue de la Paix 75002 Paris",
"15 av des champs elysee paris"
],
"coordinates": ["43.604652,1.444209"],
"minScore": 0.7,
"maxResultsPerAddress": 1,
"resultType": "any",
"includeNotFound": true
}
OptionDefaultDescription
addressesOne address per line, free text. A postcode or city improves accuracy.
coordinatesOne latitude,longitude pair per line (WGS84).
minScore0.7Matches below this score are returned as notFound and not charged.
maxResultsPerAddress1Up to 10 candidates per input, still charged once.
resultTypeanyKeep only housenumber, street, locality or municipality results.
postcode, inseeCodeRestrict all forward queries to one postcode or one municipality.
includeNotFoundtrueAdds a free row for each input with no result, so you can match every line back.
servicegeoplateformeOfficial endpoint to try first. The other one is the automatic fallback.
maxConcurrency10Parallel requests. The actor stays under 25 requests per second.

Output example

[
{
"query": "1 place du Capitole 31000 Toulouse",
"queryType": "forward",
"status": "found",
"rank": 1,
"score": 0.9765,
"label": "1 Place du Capitole 31000 Toulouse",
"resultType": "housenumber",
"houseNumber": "1",
"street": "Place du Capitole",
"name": "1 Place du Capitole",
"postalCode": "31000",
"city": "Toulouse",
"inseeCode": "31555",
"oldInseeCode": null,
"oldCity": null,
"districtName": null,
"departmentCode": "31",
"departmentName": "Haute-Garonne",
"region": "Occitanie",
"latitude": 43.603872,
"longitude": 1.444053,
"lambert93X": 574344.14,
"lambert93Y": 6279551.2,
"distanceMeters": null,
"banId": "264c0325-241b-4c4e-a07f-896b6b2c1b03",
"banAddressKey": "31555_1676_00001",
"importance": 0.74128,
"inputLatitude": null,
"inputLongitude": null,
"source": "geoplateforme",
"error": null,
"geocodedAt": "2026-10-19T08:00:00+00:00"
},
{
"query": "43.604652,1.444209",
"queryType": "reverse",
"status": "found",
"score": 0.9962,
"label": "5 Rue Lafayette 31000 Toulouse",
"postalCode": "31000",
"city": "Toulouse",
"inseeCode": "31555",
"latitude": 43.604993,
"longitude": 1.444281,
"distanceMeters": 38,
"banAddressKey": "31555_4920_00005"
},
{
"query": "42 rue des Licornes Volantes 31000 Toulouse",
"queryType": "forward",
"status": "notFound",
"label": null,
"error": "no address with score >= 0.7"
}
]

Results are in the run's dataset: export them as JSON, CSV, Excel or XML, or open the "Overview" table.

Use cases

1. CRM cleanup for a sales operations team

A sales ops manager exports 8,000 B2B customer addresses from the CRM. Many have abbreviations ("bd", "av"), missing postcodes or typos. One run fixes them for $2.40 (8,000 × $0.0003).

Input:

{ "addresses": ["15 av des champs elysee paris", "2 allees jules guesde toulouse"], "minScore": 0.7 }

Output excerpt:

[{ "query": "15 av des champs elysee paris", "score": 0.786, "label": "15 Avenue des Champs Élysées 75008 Paris", "postalCode": "75008", "inseeCode": "75056" }]

Next step: the label, postalCode and inseeCode columns go back into the CRM. Rows below 0.8 are sent to a person for review.

2. Real estate and geomarketing: joining listings with INSEE statistics

A real estate analyst gets 2,500 property addresses in Haute-Garonne every week and needs the INSEE code to join with INSEE income data and DVF sale prices. The analyst schedules the actor every Monday and pays $0.75 per week.

Input:

{ "addresses": ["118 route de Narbonne Toulouse", "20 boulevard Lazare Carnot Toulouse"], "inseeCode": "31555", "resultType": "housenumber" }

Output excerpt:

[{ "label": "118 Route de Narbonne 31400 Toulouse", "inseeCode": "31555", "latitude": 43.561566, "longitude": 1.463029, "lambert93X": 575784.9, "lambert93Y": 6274820.12 }]

Next step: inseeCode joins with INSEE tables. The Lambert 93 coordinates load directly into QGIS with French cadastral layers.

3. Field service and delivery: GPS points back to addresses

A logistics coordinator receives 1,200 GPS points per day from technicians' phones and needs the street address for each intervention report. Cost: $0.36 per day.

Input:

{ "coordinates": ["43.604652,1.444209", "48.858370,2.294481"] }

Output excerpt:

[{ "query": "43.604652,1.444209", "label": "5 Rue Lafayette 31000 Toulouse", "distanceMeters": 38 }]

Next step: the address and the distance (a quality check on the GPS fix) go into the daily report in Google Sheets.

4. Public tenders and local government data

A consultant working for a département geocodes the 3,000 addresses of public facilities (schools, town halls) to map them by municipality. The cost is $0.90. The banId gives a stable identifier for future updates.

Call it from the API

Python

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("<username>/france-address-geocoder").call(run_input={
"addresses": ["1 place du Capitole 31000 Toulouse", "12 rue de la Paix 75002 Paris"],
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item["query"], "→", item["label"], item["inseeCode"], item["latitude"], item["longitude"])

JavaScript

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('<username>/france-address-geocoder').call({
addresses: ['1 place du Capitole 31000 Toulouse', '12 rue de la Paix 75002 Paris'],
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.map((i) => [i.query, i.label, i.inseeCode]));

One HTTP call (synchronous, returns the results directly)

curl -X POST "https://api.apify.com/v2/acts/<username>~france-address-geocoder/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"addresses": ["1 place du Capitole 31000 Toulouse"]}'

Integrations: Make, Zapier, n8n, Google Sheets

n8n example (geocode new rows of a Google Sheet every morning):

  1. Schedule Trigger: every day at 7:00.
  2. Google Sheets → Get rows where the lat column is empty.
  3. Apify → Run actor and get dataset: actor france-address-geocoder, input {"addresses": {{ $json.address }}} (aggregate the rows into one list first, for one run per day).
  4. Google Sheets → Update row, matched on query: write label, postalCode, inseeCode, latitude, longitude, score.

You can build the same flow in Make with the Apify module "Run an Actor", or in Zapier with the "Run Actor" action. Apify also provides a native Google Sheets export and webhooks.

Use with AI agents (MCP)

The actor is available through the Apify MCP server, so Claude, Cursor, ChatGPT and other MCP clients can call it as a tool. Add https://mcp.apify.com/?actors=<username>/france-address-geocoder to your MCP client config. The agent can then ask, for example, "find the INSEE code and GPS coordinates of these 50 addresses". The flat JSON output (one row per input with an explicit status) is easy for an LLM to read, and the label field is a clean one-line address for prompts and RAG documents.

FAQ

Which official service is used? The Géoplateforme geocoding API of IGN (data.geopf.fr/geocodage), which serves the Base Adresse Nationale. When it does not answer, the actor uses api-adresse.data.gouv.fr (same BAN data). The source field shows which one answered.

How do I read the score? A score above 0.9 is an exact match. Between 0.7 and 0.9 the address was corrected (typo, abbreviation, missing postcode). Below 0.7 the match is usually a different address, so it is returned as notFound and not charged. Change minScore to be stricter or more tolerant.

Do I pay for duplicates or invalid lines? No. Duplicates are removed before any request. Lines with no result, invalid coordinates or a server error are free.

Does it work outside France? It covers metropolitan France and the overseas départements (Guadeloupe, Martinique, Guyane, La Réunion, Mayotte), because those are the areas in the BAN. Addresses in other countries return notFound.

Can I geocode POIs or cadastral parcels? No. This actor uses the address index only.

How fast is it? About 25 addresses per second, so roughly 1,000 addresses in under a minute and 100,000 in a bit over an hour.

Limits

  • France only (BAN coverage). New addresses appear once a municipality publishes them to the BAN.
  • Some rural addresses are only located at the street or locality level (resultType = street or locality). Use resultType: "housenumber" if you only want exact points.
  • The score measures how close the text is to the official address, not whether the address exists. Check results between 0.7 and 0.8 before relying on them.
  • The official API allows 50 requests per second per IP. The actor stays at 25 to remain reliable. Very large batches (over 1 million rows) take several hours.
  • Results depend on the availability of the public service. When both official endpoints are down, the run stops with a clear message and nothing is charged.