# International Postal Address Parser & Normalizer (`datascraperes/international-address-parser`) Actor

Parse and normalize international postal addresses in bulk with libpostal. Get structured JSON components and expansion variants. No API key required.

- **URL**: https://apify.com/datascraperes/international-address-parser.md
- **Developed by:** [DataScraperES](https://apify.com/datascraperes) (community)
- **Categories:** Developer tools, Automation, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.60 / 1,000 address processeds

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

Turn raw international postal addresses into structured components and normalized alternatives. Submit a list of address strings and receive **one ordered Dataset item per input**, ready for data cleaning, matching, CRM enrichment, or geocoding preparation.

### What this Actor does

The Actor parses free-form addresses into labeled parts such as road, house number, city, postcode, state, and country. It can also generate normalized expansion variants that remove formatting differences and expand common address forms across languages.

Choose parsing, normalization, or both. The Actor preserves repeated component labels as arrays, retains the input position in `inputIndex`, and reports when normalization variants were capped. Processing is self-contained and does not send the submitted addresses to a geocoding service.

### Use cases

- Standardize addresses before CRM, database, or spreadsheet imports.
- Prepare inconsistent address text for matching and duplicate-candidate workflows.
- Split free-form international addresses into structured fields.
- Normalize address variants before geocoding or search indexing.
- Process address columns exported by business or property data Actors.

### How to use

1. Open the Actor in Apify Console.
2. Add one or more raw postal addresses.
3. Choose whether to parse, normalize, or do both.
4. Optionally add language hints and adjust the variant cap.
5. Click **Start** and open the Dataset when the run finishes.

For a first run, use a few representative addresses in `parse_and_normalize` mode and leave language hints empty for automatic detection.

### Input

| Field | Type | Required | Default | Description |
|---|---|---:|---|---|
| `addresses` | `string[]` | Yes | — | From 1 to 10,000 address strings, each up to 500 characters. Whitespace around each value is trimmed. |
| `mode` | `string` | No | `parse_and_normalize` | `parse`, `normalize`, or `parse_and_normalize`. |
| `languages` | `string[]` | No | `[]` | Up to four unique lowercase ISO language hints for normalization. Empty uses automatic language detection. |
| `maxExpansions` | `integer` | No | `20` | Maximum variants saved per address, from 1 to 100. |

Language hints affect normalization only. They do not force parser labels, verify a country, or restrict an address to a geographic area.

This is the exact input used for the real output example below:

```json
{
  "addresses": [
    "Calle de Alcalá 45, 28014 Madrid, España"
  ],
  "mode": "parse_and_normalize",
  "languages": [
    "es"
  ],
  "maxExpansions": 20
}
```

### Output

Results are stored in the default Dataset in the same order as the submitted addresses. Each item contains the ordered parser components, a grouped `parsed` object, normalized variants, counts, truncation status, and an item-level error field. Results can be exported in JSON, JSONL, CSV, Excel, XML, and other formats supported by Apify.

This is the complete Dataset item from a real successful run:

```json
{
  "inputIndex": 0,
  "status": "succeeded",
  "inputAddress": "Calle de Alcalá 45, 28014 Madrid, España",
  "mode": "parse_and_normalize",
  "languageHints": [
    "es"
  ],
  "components": [
    {
      "label": "road",
      "value": "calle de alcalá"
    },
    {
      "label": "house_number",
      "value": "45"
    },
    {
      "label": "postcode",
      "value": "28014"
    },
    {
      "label": "city",
      "value": "madrid"
    },
    {
      "label": "country",
      "value": "españa"
    }
  ],
  "parsed": {
    "road": [
      "calle de alcalá"
    ],
    "house_number": [
      "45"
    ],
    "postcode": [
      "28014"
    ],
    "city": [
      "madrid"
    ],
    "country": [
      "españa"
    ]
  },
  "componentCount": 5,
  "primaryExpansion": "calle de alcala 45 28014 madrid espana",
  "expansions": [
    "calle de alcala 45 28014 madrid espana"
  ],
  "expansionCount": 1,
  "expansionsReturned": 1,
  "expansionsTruncated": false,
  "errorMessage": null
}
```

`components` preserves parser order and repeated labels. In `parsed`, every label maps to an array, even when only one value exists. `primaryExpansion` is the first returned normalization candidate; it is not a verified canonical address.

If one address cannot be processed, its row has `status: "failed"`, empty result arrays, and a safe `errorMessage`. Other addresses continue processing. Invalid run-level input, such as an empty address or unsupported mode, fails before Dataset processing begins.

### Pricing

The Actor costs **$0.60 per 1,000 successful addresses** ($0.0006 each). A charge occurs only when an address is successfully parsed or normalized and its result is saved to the default Dataset.

There is no Actor start charge. Failed address items are saved without an `address-result` charge, and addresses skipped because the run reached the user's maximum charge limit are neither saved nor charged. Platform usage during the run is included in the event price. Post-run storage operations may still follow the user's Apify plan.

### API and integrations

Run the Actor through Apify Console, REST API, CLI, Tasks, Schedules, or webhooks. Use the default Dataset API to feed parsed addresses into databases, spreadsheets, geocoders, matching jobs, or automation platforms. The `SUMMARY` record in the default key-value store reports requested, processed, remaining, succeeded, failed, charged, charge-limit status, charged event name, and mode values for monitoring.

### Related Actors

| Actor | Best for |
|---|---|
| [Google Maps Business Scraper | $1 per 1,000](https://apify.com/datascraperes/actor-google-maps) | Collecting business address strings and public place details before address normalization or matching. |
| [Fotocasa Spain Property Listings Scraper](https://apify.com/datascraperes/fotocasa-property-search-scraper) | Collecting Spanish property locations that can be standardized for analysis. |
| [Realtor.com US Property Listings Scraper](https://apify.com/datascraperes/realtor-property-search) | Collecting structured US listing addresses for cross-source cleanup and comparison. |

### Limits and data quality

- Each run accepts up to 10,000 addresses; each address is limited to 500 characters.
- A maximum of 100 normalization variants can be retained per address. `expansionCount` shows how many were produced and `expansionsTruncated` identifies capped output.
- Address parsing is statistical. Ambiguous, incomplete, non-postal, or unusual input can produce missing or incorrect labels.
- Normalization generates possible equivalent forms. It does not choose a legally preferred or postal-authority-approved format.
- The Actor does not verify existence, occupancy, deliverability, ownership, or geographic coordinates.
- Component availability varies by address. Never assume every result contains road, house number, city, postcode, state, and country.
- Repeated labels remain separate values in `components` and arrays in `parsed`; downstream systems should not flatten them without a rule appropriate to their data.

### Frequently asked questions

#### Does this Actor validate or geocode an address?

No. It parses and normalizes text. It does not confirm that an address exists, determine whether mail can be delivered there, or return latitude and longitude. Send the cleaned result to a suitable geocoder or postal validation service when those checks are required.

#### Should I provide language hints?

Usually, start with an empty `languages` array so language detection is automatic. Add hints when you know the intended language and want normalization to prefer it. Hints do not constrain the parser to a country.

#### Which normalized variant should I store?

Treat every expansion as a candidate. `primaryExpansion` is convenient for inspection, but it is not guaranteed to be uniquely correct. For duplicate detection, compare overlapping variants and retain the original address for provenance.

#### Why are some components missing or labeled unexpectedly?

Free-form addresses can be incomplete or ambiguous, and local conventions vary. Include locality and country context when available, inspect representative samples, and keep the original string alongside parsed output.

### Responsible use

This Actor uses the open-source [libpostal](https://github.com/openvenues/libpostal) project, whose models are derived from open geographic data. Users are responsible for complying with applicable licenses, laws, privacy obligations, and data-source terms.

Postal addresses can identify people or sensitive locations. Process only data you are authorized to use, protect exported Datasets, limit retention, and avoid using probabilistic parser output as proof of identity, residence, or deliverability.

### Support

If a run does not behave as expected, open an issue in the Actor's **Issues** tab. Include the run ID, a sanitized reproducible input, the expected result, and the observed result. Do not post personal addresses, API tokens, credentials, or confidential information.

# Actor input Schema

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

Raw postal address strings. Each entry produces one Dataset item and input order is preserved.

## `mode` (type: `string`):

Parse address components, return normalized expansion variants, or return both.

## `languages` (type: `array`):

Optional lowercase ISO language codes for normalization, such as en, es, de, or fr. Leave empty for automatic language detection.

## `maxExpansions` (type: `integer`):

Caps variants saved for each address. The Actor reports whether additional variants were omitted.

## Actor input object example

```json
{
  "addresses": [
    "Calle de Alcalá 45, 28014 Madrid, España",
    "1600 Pennsylvania Ave NW, Washington, DC 20500, USA"
  ],
  "mode": "parse_and_normalize",
  "languages": [],
  "maxExpansions": 20
}
```

# Actor output Schema

## `dataset` (type: `string`):

One Dataset item per input address, in input order.

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

Counts of successful and failed address items.

# 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": [
        "Calle de Alcalá 45, 28014 Madrid, España",
        "1600 Pennsylvania Ave NW, Washington, DC 20500, USA"
    ],
    "mode": "parse_and_normalize",
    "languages": [],
    "maxExpansions": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("datascraperes/international-address-parser").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": [
        "Calle de Alcalá 45, 28014 Madrid, España",
        "1600 Pennsylvania Ave NW, Washington, DC 20500, USA",
    ],
    "mode": "parse_and_normalize",
    "languages": [],
    "maxExpansions": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("datascraperes/international-address-parser").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": [
    "Calle de Alcalá 45, 28014 Madrid, España",
    "1600 Pennsylvania Ave NW, Washington, DC 20500, USA"
  ],
  "mode": "parse_and_normalize",
  "languages": [],
  "maxExpansions": 20
}' |
apify call datascraperes/international-address-parser --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,datascraperes/international-address-parser"
        }
    }
}

```

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/j0hLBRVGbmC6swuUU/builds/PjNgDYkygNacsmOs0/openapi.json
