# Official Geocoder (France BAN, Netherlands PDOK, US Census) (`darikami/official-geocoder`) Actor

Geocode up to 50,000 addresses per run with the official national geocoders of France (Base Adresse Nationale), the Netherlands (PDOK, BAG) and the US (Census). Latitude, longitude, the official address form, match level and score. No API key. Pay only for matched addresses.

- **URL**: https://apify.com/darikami/official-geocoder.md
- **Developed by:** [DARIKAMI GmbH](https://apify.com/darikami) (community)
- **Categories:** Developer tools, Real estate
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.50 / 1,000 address geocodeds

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?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Official Geocoder (France BAN, Netherlands PDOK, US Census)

**Geocode addresses with the official national geocoders of France (Base Adresse Nationale), the Netherlands (PDOK, BAG) and the US (Census Bureau).**
You get the official address, latitude and longitude, the match level and score, and the source's own address identifier.
**USD 0.0005 per matched address (USD 0.50 per 1,000).** Rows without a match are free. Up to 50,000 addresses per run, mixed countries, no API key.

| Input | Official address | Latitude | Longitude | Level |
|---|---|---|---|---|
| `FR: 20 avenue de Ségur, 75007 Paris` | 20 Avenue de Ségur 75007 Paris | 48.850699 | 2.308628 | address |
| `FR: 8 bd du Port, 95000 Cergy` | 8 Boulevard du Port 95000 Cergy | 49.031624 | 2.062821 | address |
| `NL: Damrak 1, Amsterdam` | Damrak 1, 1012LG Amsterdam | 52.37714446 | 4.89803846 | address |
| `NL: Binnenhof 1A, Den Haag` | Binnenhof 1A, 2513AA 's-Gravenhage | 52.07910612 | 4.31227715 | address |
| `350 Fifth Avenue, New York, NY 10118` | 350 5TH AVE, NEW YORK, NY, 10118 | 40.747850846857 | -73.985075577551 | address |

The rows come from a real cloud run of 2026-11-04 against the three live geocoders (default country US). The full item is under Output.

The sources:

- **France:** the Base Adresse Nationale, through the Géoplateforme geocoding service of the IGN.
- **The Netherlands:** the PDOK Locatieserver, built on the BAG, the national register of addresses and buildings.
- **The United States:** the U.S. Census Bureau Geocoder.

### Who uses it

- **CRM and data teams:** add coordinates and the official address form to customer, supplier or store lists.
- **Logistics and field service:** turn delivery and site addresses into points for routing and territory maps.
- **Real-estate and location analysis:** place listings and properties on the map with the government's own address data.

### What it does not do

- Three countries only: France, the Netherlands and the US. Another country's address gets no match or a wrong one.
- No reverse geocoding (coordinates to address), no autocomplete, no points of interest.
- No owner, resident or cadastral data: the address and its point only.
- The US point is interpolated along the street segment, not the building.

### Input

```json
{
  "addresses": [
    "FR: 20 avenue de Ségur, 75007 Paris",
    "NL: Coolsingel 40, 3011 AD Rotterdam",
    "1600 Pennsylvania Ave NW, Washington, DC 20500"
  ],
  "defaultCountry": "US"
}
```

| Field | Meaning |
|---|---|
| `addresses` | One address per line. Start a line with `FR:`, `NL:` or `US:` to give its country. 3 to 200 characters. |
| `csvUrl` | Optional. A CSV file with a header line. See "CSV files" below. Its rows come after the list. At most 20 MB. |
| `defaultCountry` | `US` (default), `FR` or `NL`: the country of a row that names none. |
| `minMatchLevel` | `street` (default), `address`, `postcode` or `any`. See "Match levels" below. |
| `maxAddresses` | The most rows this run geocodes, the list and the CSV together. Default 1,000, at most 50,000. |

#### CSV files

- The address is in a column `address`.
- Or the address is in several columns: `street`, `housenumber`, `postcode`, `zip`, `city`, `state` and similar names.
  The actor joins them. It sends no other column to a geocoder: a `name` or `email` column stays out.
- A column `country` gives the row's country: `FR`, `NL`, `US`, or the name (`France`, `Netherlands`, `USA`).
- A column `id` comes back in each item as `inputId`.

```csv
id,street,city,postcode,country
a1,20 avenue de Ségur,Paris,75007,FR
a2,Coolsingel 40,Rotterdam,,NL
a3,4600 Silver Hill Rd,Washington,20233,US
```

### Output (one item per input row)

```json
{
  "row": 1,
  "inputId": null,
  "input": "FR: 20 avenue de Ségur, 75007 Paris",
  "country": "FR",
  "matched": true,
  "matchedAddress": "20 Avenue de Ségur 75007 Paris",
  "latitude": 48.850699,
  "longitude": 2.308628,
  "matchLevel": "address",
  "matchScore": 0.9716,
  "sourceMatchType": "housenumber",
  "street": "Avenue de Ségur",
  "houseNumber": "20",
  "postcode": "75007",
  "city": "Paris",
  "region": "Île-de-France",
  "officialId": "75107_8909_00020",
  "error": null,
  "message": null,
  "source": "Géoplateforme geocoding service (IGN), Base Adresse Nationale - data.geopf.fr/geocodage, licence etalab-2.0",
  "geocodedAt": "2026-11-04T22:15:00.000Z"
}
```

- `matchScore`: France gives 0 to 1. The Netherlands gives the search engine's relevance score: higher is better, with
  no fixed top. The US gives no score (`null`); `sourceMatchType` is `Exact` or `Non_Exact` there, or `Match` for an
  address geocoded on its own (see Limits).
- `officialId`: the BAN key of the address (France), the BAG identifier of the address (the Netherlands), or the TIGER
  line of the street segment (the US).
- `region`: the French region, the Dutch province, or the US state.
- The items keep the order of the input. An address that occurs twice is geocoded once, and each row gets its item.
- When there is no match, `matched` is `false`. Then `error` tells why: `no-match`, `below-min-level`, `invalid-input` or
  `not-fetched`. `message` gives the details.

#### Match levels

From best to least precise:

1. `address` - the house number.
2. `street` - the street.
3. `postcode` - the postcode. The Netherlands only; a Dutch postcode covers about one side of a street.
4. `locality` - a named place.
5. `municipality` - a town or city.

`minMatchLevel` sets the lowest level you accept. A match below it comes back free, without coordinates. The default
`street` accepts house numbers and streets. The US Census Geocoder matches house numbers only.

### Pricing (pay per event)

| Event | Price | When |
|---|---|---|
| `address-geocoded` | **USD 0.0005** | one row matched at or above your minimum level |

1,000 matched addresses cost USD 0.50. 50,000 cost USD 25. These rows are free:

- a row without a match;
- a match below your minimum level;
- an invalid row;
- a row that the source did not answer.

### Privacy

- The addresses are your data. The actor sends each address to the geocoder of its country and not elsewhere. The run log holds counts.
- The output contains address data only. It contains no owner, no resident and no person. The actor does not ask for
  cadastral parcels.
- Send addresses only. Do not put names of persons into the address lines: the actor sends the whole line to the
  geocoder.

### Data sources and terms

- **France:** the Géoplateforme geocoding service of the IGN, `https://data.geopf.fr/geocodage`, with the Base Adresse
  Nationale. The site states: "Sauf mention contraire, tous les contenus de ce site sont sous licence etalab-2.0". The
  Licence Ouverte (etalab-2.0) allows reuse, also commercial reuse, with attribution. Each item names its source.
  The service is limited to 50 requests a second per IP address.
- **The Netherlands:** the PDOK Locatieserver (Kadaster, for the Ministry of the Interior),
  `https://api.pdok.nl/bzk/locatieserver/search/v3_1/free`. PDOK states: "De Locatieserver is een gratis zoekservice die
  voor iedereen beschikbaar is" (a free search service for everybody). The addresses come from the BAG and other
  government registers. PDOK states no rate limit.
- **The United States:** the U.S. Census Bureau Geocoder, `https://geocoding.geo.census.gov/geocoder`, benchmark
  `Public_AR_Current`. It is a work of the US federal government. Such works are not under copyright in the US (17
  U.S.C. 105; our assessment, the service states no terms).
- This actor is not affiliated with or endorsed by the IGN, PDOK, the Kadaster or the U.S. Census Bureau.

### Limits

- A geocoder is a search engine. A short or vague address can match the wrong place: "rue de la Paix" alone matches one
  street of that name in France. Give the postcode or the city.
- Each geocoder covers its own country only. An address of another country gets no match or a wrong one: give each row
  its country.
- When several US addresses fit equally well (a "Tie"), the Census gives no coordinates. The row is free; add the city,
  the state or the ZIP code.
- Some addresses make a whole US batch fail. The actor then geocodes that batch again one address at a time, with the
  Census one-line service. The run takes longer. That service does not say `Exact` or `Non_Exact` (`sourceMatchType`
  is `Match`), and when it finds several candidates the row counts as a free Tie, where the batch could have matched.

### Run summary

The run summary is in the default key-value store under `SUMMARY`, the counts under `STATS`.
The data comes as the source publishes it, without warranty.

**More official-data actors by darikami:** [Swiss UID & VAT validator](https://apify.com/darikami/swiss-uid-validator) · [Swiss electricity tariffs](https://apify.com/darikami/swiss-electricity-tariffs) · [Swiss federal law MCP](https://apify.com/darikami/swiss-federal-law-mcp) · [SEC company fundamentals](https://apify.com/darikami/sec-company-fundamentals) · [German public tenders](https://apify.com/darikami/german-public-tenders).
In an AI agent: ask the Apify MCP server (`mcp.apify.com`) for `darikami/official-geocoder`.

# Actor input Schema

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

One address per line. Start a line with FR:, NL: or US: to give its country (for example NL: Damrak 1, Amsterdam); a line without one uses the default country. 3 to 200 characters each.

## `csvUrl` (type: `string`):

Optional. A CSV file with a header line: a column "address" (or the address in several columns, such as street, city, postcode - they are joined), and optionally "country" and "id". Its rows come after the list above. At most 20 MB.

## `defaultCountry` (type: `string`):

The country of a row that names none.

## `minMatchLevel` (type: `string`):

A match below this level is returned free, without coordinates. Street (default) = a house number or a street; address = a house number only; postcode = also a postcode (NL); any = also a locality or a municipality. The US Census matches house numbers only.

## `maxAddresses` (type: `integer`):

The most rows this run geocodes (the list and the CSV together). Rows beyond it are left out. You pay only for matched addresses.

## Actor input object example

```json
{
  "addresses": [
    "FR: 20 avenue de Ségur, 75007 Paris",
    "NL: Coolsingel 40, Rotterdam",
    "US: 1600 Pennsylvania Ave NW, Washington, DC 20500"
  ],
  "defaultCountry": "US",
  "minMatchLevel": "street",
  "maxAddresses": 1000
}
```

# Actor output Schema

## `results` (type: `string`):

One item per input row: the input, whether it matched, the official address, latitude, longitude, match level and score, the source.

## `summary` (type: `string`):

SUMMARY record: pushed, charged, attempts, errors, stoppedByBudget, ok, message; notTried when a source went down.

# 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 = {
    "addresses": [
        "FR: 20 avenue de Ségur, 75007 Paris",
        "NL: Coolsingel 40, Rotterdam",
        "US: 1600 Pennsylvania Ave NW, Washington, DC 20500"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("darikami/official-geocoder").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 = { "addresses": [
        "FR: 20 avenue de Ségur, 75007 Paris",
        "NL: Coolsingel 40, Rotterdam",
        "US: 1600 Pennsylvania Ave NW, Washington, DC 20500",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("darikami/official-geocoder").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 '{
  "addresses": [
    "FR: 20 avenue de Ségur, 75007 Paris",
    "NL: Coolsingel 40, Rotterdam",
    "US: 1600 Pennsylvania Ave NW, Washington, DC 20500"
  ]
}' |
apify call darikami/official-geocoder --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,darikami/official-geocoder"
        }
    }
}
```

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/c3Kdx227uLiPmgNRY/builds/aCSXBjawzM4XODdyf/openapi.json
