# Israeli Address Normalizer & Matcher (`refaelsh/il-address-normalizer`) Actor

Clean messy Israeli addresses (Hebrew/English) and match them to official settlement and street codes from data.gov.il open data. Not an official government service.

- **URL**: https://apify.com/refaelsh/il-address-normalizer.md
- **Developed by:** [Refael Sheinker](https://apify.com/refaelsh) (community)
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-usage

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

## Israeli Address Normalizer & Matcher

Turn messy, free-text Israeli addresses into clean, structured records. Each address is matched to its **settlement code (סמל ישוב)** and **street code (סמל רחוב)** from the public street and settlement lists on data.gov.il.

> **This is not an official government service.** It is an independent tool built on open data from data.gov.il. It is not affiliated with, endorsed by or certified by the Israeli government, the Central Bureau of Statistics or the Population and Immigration Authority. Results are best-effort matches, not official address validation.

### What it does

- Accepts addresses in **Hebrew, English or mixed**, in any word order: `הרצל 40 טירת כרמל`, `Tirat Carmel, 40 Herzl St`, `שד' רוטשילד 12 ת"א`.
- Handles common mess:
  - abbreviations (רח', שד', סמ', ת"א, פ"ת, ראשל"צ, י-ם…)
  - full and defective spelling (כתיב מלא/חסר)
  - different quote and gershayim characters, and missing quotes
  - reversed name order in the official list (e.g. "אשכול לוי")
  - apartment, floor and entrance noise, postal codes, and "Israel" at the end
  - numbered streets (רח 3014)
  - known alternative street names, taken from the official synonyms file
- Returns the official Hebrew names, the English settlement name where the source has one, the house number, a **confidence score** and flags for ambiguous, unmatched and low-confidence results.

### Input

```json
{
  "addresses": [
    "הרצל 40 טירת כרמל",
    "רח' דיזנגוף 50 דירה 4, תל-אביב",
    "12 Ben Yehuda St, Jerusalem",
    "קיבוץ יגור"
  ],
  "minConfidence": 0.6,
  "includeAlternatives": true
}
```

| Field | Type | Default | Meaning |
|---|---|---|---|
| `addresses` | string\[] | — | Addresses to match, one per item. |
| `minConfidence` | number 0–1 | 0.6 | Results below this score get `lowConfidence: true`. They are still returned. |
| `includeAlternatives` | boolean | true | Include up to 3 runner-up candidates. |

### Output (one dataset item per address)

```json
{
  "input": "הרצל 40 טירת כרמל",
  "settlementCode": 2100,
  "settlementName": "טירת כרמל",
  "settlementNameEn": "TIRAT KARMEL",
  "streetCode": 434,
  "streetName": "הרצל",
  "streetNameEn": null,
  "houseNumber": "40",
  "normalizedAddress": "הרצל 40, טירת כרמל",
  "confidence": 1,
  "settlementMatchMethod": "name",
  "streetMatchMethod": "exact",
  "unmatchedSettlement": false,
  "unmatchedStreet": false,
  "ambiguous": false,
  "missingHouseNumber": false,
  "poBox": false,
  "lowConfidence": false,
  "alternatives": [],
  "dataSnapshot": "2026-10-28T19:27:27.822Z"
}
```

- `confidence`: 1.0 means an exact match on the official names. Lower scores mean spelling, phonetic or partial matching was needed. An ambiguous match is scored down.
- `ambiguous`: two candidates scored almost the same. Check `alternatives`.
- `unmatchedSettlement` / `unmatchedStreet`: no candidate was good enough. Addresses with only a settlement (e.g. a kibbutz) return the settlement with `unmatchedStreet: true`.
- A run summary (counts, data snapshot date, source IDs) is saved to the key-value store as `SUMMARY`.

### Accuracy (v0.1, snapshot 2026-10-28)

- **Blind hand-written holdout set (35 messy addresses, written before the first run):** 33/35 fully correct (94.3%) on the first run. It reached 35/35 after two general fixes.
- **Synthetic stress test:** 3,000 random real streets written in messy ways (missing or extra yod/vav, "רח'" prefix, city first, no quotes, apartment noise). 99.1% exact settlement+street match, and about half of the misses were flagged.
- **Development set (45 addresses used for tuning):** 45/45.

These numbers come from small test sets. Your data may score differently.

### Limitations

- **No English street names.** The source lists streets in Hebrew only, so `streetNameEn` is always `null`. English street input is matched phonetically (e.g. "Ben Yehuda" → בן יהודה), which can be wrong for unusual spellings.
- English settlement names come from the source, which **cuts them at 20 characters** (e.g. `MODI'IN-MAKKABBIM-RE`).
- No geocoding (no coordinates), and no check that a house number actually exists on the street.
- A street with no settlement cannot be resolved reliably.
- A settlement name that is also a street name can confuse an address with no commas.
- The official list sometimes has several codes with the same street name in one settlement. Check `alternatives` when `ambiguous` is true.

### Data source and attribution

Data: **data.gov.il**, Israel's national open data portal, from these datasets:

- רשימת ישובים בישראל (settlement list): https://data.gov.il/dataset/citiesandsettelments
- רשימת רחובות ישראל (street list): https://data.gov.il/dataset/321
- רשימת רחובות בישראל – קובץ עם סינונימיים (street synonyms): https://data.gov.il/dataset/israel-streets-synom

The data is used under the data.gov.il terms of use: https://data.gov.il/terms-of-use. The Actor bundles a snapshot (the date is shown in every result as `dataSnapshot`), and the maintainer refreshes it from the public CKAN API with `npm run refresh-data`. The data has been processed (normalised and indexed) and is not presented as official. Use of the data does not imply any sponsorship or endorsement by the State of Israel.

### Local development

```bash
npm install
npm run refresh-data   # optional: pull the latest lists from data.gov.il
npm test               # dev set, blind holdout set, synthetic stress test
apify run              # or: node src/main.js, with storage/key_value_stores/default/INPUT.json
```

# Actor input Schema

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

Free-text Israeli addresses, one per item. Hebrew, English or mixed, e.g. "רח' הרצל 40 טירת כרמל" or "12 Rothschild Blvd, Tel Aviv".

## `minConfidence` (type: `number`):

Results below this score get lowConfidence = true (they are still returned).

## `includeAlternatives` (type: `boolean`):

Return the top runner-up matches for each address.

## Actor input object example

```json
{
  "addresses": [
    "הרצל 40 טירת כרמל",
    "שד' רוטשילד 12, ת\"א",
    "12 Ben Yehuda St, Jerusalem"
  ],
  "minConfidence": 0.6,
  "includeAlternatives": true
}
```

# Actor output Schema

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

No description

# 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": [
        "הרצל 40 טירת כרמל",
        "שד' רוטשילד 12, ת\"א",
        "12 Ben Yehuda St, Jerusalem"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("refaelsh/il-address-normalizer").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": [
        "הרצל 40 טירת כרמל",
        "שד' רוטשילד 12, ת\"א",
        "12 Ben Yehuda St, Jerusalem",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("refaelsh/il-address-normalizer").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": [
    "הרצל 40 טירת כרמל",
    "שד'\'' רוטשילד 12, ת\\"א",
    "12 Ben Yehuda St, Jerusalem"
  ]
}' |
apify call refaelsh/il-address-normalizer --silent --output-dataset

```

## MCP server setup

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

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/UAaQQNkhXbgTkIfUt/builds/YEz3UQJcPzVMV5p1w/openapi.json
