# Arabic Text Toolkit: Normalize, Transliterate, Numbers (`firebrick_zamia/arabic-text-toolkit`) Actor

Normalise Arabic text, strip diacritics, transliterate Arabic to Latin, match names across scripts, and write amounts in Arabic words. Pure computation, no web calls.

- **URL**: https://apify.com/firebrick_zamia/arabic-text-toolkit.md
- **Developed by:** [Aadam Ahmed](https://apify.com/firebrick_zamia) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 results

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

## Arabic Transliteration, Normalizer and Amount in Words

**Normalize Arabic text, transliterate Arabic to Latin or Arabizi, build a name-matching key (Mohammed / Muhammad / محمد) and write AED, SAR, QAR, KWD, BHD and OMR amounts in Arabic words. Deterministic, no web calls, no AI.**

### What you get

One result per text or amount: script detection, normalized text, Latin transliteration, a name key, or Arabic amount words with an optional cheque phrase. See the example below.

### Use cases

- Arabic text normalization for search and deduplication (remove tashkeel, unify alef and ya, convert Arabic-Indic digits).
- Arabic transliteration of names and place names for databases and reports (a simplified romanisation, see limitations).
- Matching Arabic and Latin spellings of the same name with a shared key.
- Amount in Arabic words for invoices and cheques (`فقط ... لا غير`).

Details of the operations:

Clean and prepare Arabic text for search, databases, invoices and AI pipelines, without any web calls:

- **Detect** script, diacritics, tatweel and digit style.
- **Normalize**: strip tashkeel and tatweel, fold presentation forms (NFKC), optionally unify alef/ya/taa-marbuta for search matching, convert digits between Western (0-9) and Arabic-Indic (٠-٩), remove invisible direction marks.
- **Transliterate** Arabic to Latin (rule-based romanisation, or chat-style Arabizi with 3, 7, 5). Short vowels are only output when the text carries diacritics; unvoweled words come out consonant-heavy (e.g. "al-'rbya"). It is not a dictionary-based or machine-learning transliterator.
- **Name matching key**: one key for `Mohammed`, `Muhammad`, `Mohamed` and `محمد`, to match names across scripts and spellings.
- **Amounts in Arabic words** for AED, SAR, QAR, KWD, BHD and OMR (including fils / halalas / baisa), with an optional cheque-style phrase `فقط ... لا غير`.

### Why use it

Arabic search and deduplication fail silently when diacritics, alef variants and Arabic-Indic digits differ. Invoicing and payroll systems in the Gulf need amounts in Arabic words. This Actor does these jobs deterministically in one cheap call per text.

### Input

| Field | Meaning |
|---|---|
| `texts` | One text per line (up to 10,000 texts, 20,000 characters each) |
| `operations` | any of `detect`, `normalize`, `transliterate`, `name_key` (default first three) |
| `removeDiacritics`, `removeTatweel` | normalize options, default on |
| `unifyAlef`, `unifyYa`, `unifyTaMarbuta` | aggressive folding for search keys, default off |
| `digits` | `keep`, `western`, `arabic_indic` |
| `arabizi` | chat-style transliteration |
| `amounts`, `currency` | numbers or amounts to write in words; `none` gives a plain whole number |

### Example input and output

Input (bundled `test-input.json`): texts `مُحَمَّد بن عبد الله` and `الإمارات العربية المتحدة ٢٠٢٦` with operations `detect`, `normalize`, `transliterate`. Real output for `مُحَمَّد بن عبد الله` with all four operations, and the amount `1250.5` in AED:

```json
{
  "kind": "text",
  "input": "مُحَمَّد بن عبد الله",
  "detect": { "script": "arabic", "arabic_letters": 13, "has_diacritics": true, "direction": "rtl" },
  "normalized": "محمد بن عبد الله",
  "transliterated": "muhammad bn 'bd allah",
  "name_key": "mhmd bd lh",
  "name_key_compact": "mhmdbdlh"
}
{
  "kind": "amount",
  "input": "1250.5",
  "currency": "AED",
  "words_ar": "ألف ومائتان وخمسون درهماً وخمسون فلساً",
  "words_ar_cheque": "فقط ألف ومائتان وخمسون درهماً وخمسون فلساً لا غير"
}
```

### Limitations (read before relying on it)

- **Transliteration is a simplified romanisation, not ISO 233 or ALA-LC.** Without vowel marks, Arabic text has no short vowels, so `محمد` becomes `mhmd`; with full diacritics `مُحَمَّد` becomes `muhammad`. Names, loanwords and dialect spellings may differ from official passport spellings. Latin to Arabic is not supported.
- **The name key is a fuzzy matching aid, not identity resolution.** It drops vowels and common particles (bin, ibn, al, abu). Different names can collide; always confirm matches.
- **Amounts in words follow standard Arabic number-noun agreement** (singular, dual, plural, accusative tanween) in the nominative style used on invoices. Currency names: dirham/fils (AED), riyal/halala (SAR), riyal/dirham (QAR), dinar/fils (KWD, BHD), rial/baisa (OMR), with 2 or 3 minor digits per ISO 4217 (https://www.iso.org/iso-4217-currency-codes.html). Have a native speaker review the format for legal documents and cheques; banks and regulators may require their own phrasing.
- Amounts are limited to below 1,000,000,000,000 and rounded half-up at the currency's minor precision.
- Letter and diacritic classes follow the Unicode Arabic block (https://www.unicode.org/charts/PDF/U0600.pdf).

### Pricing (pay per result)

Pay-per-event with Apify's built-in dataset-item event: each text or amount is one result. The live price is set in Apify Console and shown on the Store page (see Store). Planning figure in our notes: USD 2.00 per 1,000 results. The closest competitor found (a generic Unicode normaliser, no Arabic-specific features) lists from USD 0.0005 per text (USD 0.50 per 1,000); generic text-cleaning Actors list USD 0.5-3 per 1,000 (checked 21 Oct 2026, see `apify/RESEARCH-2.md`).

### FAQ

**Does it call any website or AI model?** No. Everything is computed locally.

**Can it transliterate Latin to Arabic?** Not in this version.

**Does it handle Persian digits and letters?** Persian digits are read as digits; پ چ گ ڤ are romanised; other Persian-specific behaviour is not tuned.

**Is my text stored?** Only in your run's dataset.

**Is the transliteration good enough for passports or legal names?** No. It is a simplified romanisation; official spellings can differ.

**Can it write amounts in Arabic words for KWD with three decimals?** Yes: KWD, BHD and OMR use three minor digits, the others two.

# Actor input Schema

## `texts` (type: `array`):

Texts to process, one per line (up to 10,000, each up to 20,000 characters). Each text is one billed result.

## `operations` (type: `array`):

What to compute for every text: detect (script and diacritics report), normalize, transliterate (Arabic to Latin), name_key (fuzzy match key for Arabic or Latin names).

## `removeDiacritics` (type: `boolean`):

Normalize: strip tashkeel (fatha, damma, kasra, shadda, sukun, tanween, dagger alef).

## `removeTatweel` (type: `boolean`):

Normalize: remove the elongation character (ـ).

## `unifyAlef` (type: `boolean`):

Normalize: map أ إ آ ٱ to plain ا (useful for search matching).

## `unifyYa` (type: `boolean`):

Normalize: map ى to ي (useful for search matching).

## `unifyTaMarbuta` (type: `boolean`):

Normalize: map ة to ه (aggressive; useful for search matching only).

## `digits` (type: `string`):

Normalize: convert digits to Western (0-9), Arabic-Indic (٠-٩) or leave unchanged. Persian digits are read as input too.

## `arabizi` (type: `boolean`):

Transliterate: use chat digits for letters without a Latin equivalent (ع=3, ح=7, خ=5, ء=2, ط=6).

## `amounts` (type: `array`):

Numbers or amounts such as 1250.50 or ١٢٣٤٫٥٠ (up to 10,000). Each amount is one billed result. Max 999,999,999,999.

## `currency` (type: `string`):

Currency used when writing amounts in words (with minor units). Choose none to write a plain whole number.

## Actor input object example

```json
{
  "texts": [
    "مُحَمَّد بن عبد الله",
    "الإمارات العربية المتحدة ٢٠٢٦"
  ],
  "operations": [
    "detect",
    "normalize",
    "transliterate"
  ],
  "removeDiacritics": true,
  "removeTatweel": true,
  "unifyAlef": false,
  "unifyYa": false,
  "unifyTaMarbuta": false,
  "digits": "keep",
  "arabizi": false,
  "currency": "none"
}
```

# Actor output Schema

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

All result records.

# 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 = {
    "texts": [
        "مُحَمَّد بن عبد الله",
        "الإمارات العربية المتحدة ٢٠٢٦"
    ],
    "operations": [
        "detect",
        "normalize",
        "transliterate"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("firebrick_zamia/arabic-text-toolkit").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 = {
    "texts": [
        "مُحَمَّد بن عبد الله",
        "الإمارات العربية المتحدة ٢٠٢٦",
    ],
    "operations": [
        "detect",
        "normalize",
        "transliterate",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("firebrick_zamia/arabic-text-toolkit").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 '{
  "texts": [
    "مُحَمَّد بن عبد الله",
    "الإمارات العربية المتحدة ٢٠٢٦"
  ],
  "operations": [
    "detect",
    "normalize",
    "transliterate"
  ]
}' |
apify call firebrick_zamia/arabic-text-toolkit --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,firebrick_zamia/arabic-text-toolkit"
        }
    }
}
```

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/Oq8S7iec79FrHdzR6/builds/T7IIRDV92RrNaMxc8/openapi.json
