npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

money-in-words

v1.0.0

Published

Convert a numeric monetary amount plus an ISO 4217 currency code into natural English words, with correct major/minor unit splitting and per-currency decimal precision.

Readme

money-in-words

Amounts spelled out, in every currency on earth

178 ISO 4217 currencies — split into major and minor units at each currency's own real precision.

npm version types license runtime deps coverage


Printing an invoice, a cheque, or a legal amount-in-words line means knowing that JPY has no cents, that Bahraini dinars have three decimal places, that the plural of loti is maloti and of paisa is paise — and that 1000.1 must never become nine cents. money-in-words knows all of it: one call, one string, every ISO 4217 currency.

Change the currency code and everything else adapts — precision, unit names, plurals, and whether a minor unit exists at all.

toWords(1000.34, 'USD'); // "One thousand US dollars and thirty-four cents"
toWords(1000, 'BDT'); // "One thousand taka only"
toWords(45.5, 'JPY'); // "Forty-five yen"          — 0 decimals, no minor unit
toWords(1.234, 'BHD'); // "One Bahraini dinar and two hundred and thirty-four fils"

Why money-in-words

| | | | ------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | | Every ISO 4217 currency | All 178 codes, vendored from the official SIX/ISO "List One". Nothing is fetched at runtime. | | Real per-currency precision | JPY and KRW take no cents. BHD, KWD and OMR take three decimals. Everything else gets exactly the digits ISO says it gets. | | Float-safe by construction | Amounts are decomposed from their exact decimal representation, never by float arithmetic. 1000.1 is always ten cents. | | Correct unit names | Singular and plural, including the irregulars: penny/pence, paisa/paise, loti/maloti, lilangeni/emalangeni, real/reais. | | Zero runtime deps | Pure TypeScript. Identical on Node 18+, Bun, Deno, and the browser. | | Strict types, no any | Typed error hierarchy, readonly data, 379 tests at 100% coverage. | | Dual ESM + CJS | Ships .js, .cjs, and generated .d.ts / .d.cts. |

English output only — this package deliberately ships no locale infrastructure.


Install

npm install money-in-words
# or
pnpm add money-in-words
# or
bun add money-in-words

Requires Node 18+ (or Bun / Deno). No native modules, no install scripts, no network access.

[!NOTE] The currency table is a static, frozen object compiled into the bundle. This package never makes a network request and never reads the filesystem.


Quick start

import { toWords, numberToWords } from 'money-in-words';

// Currency-aware: major/minor split at the currency's own precision.
toWords(1000.34, 'USD');
// "One thousand US dollars and thirty-four cents"

// Casing, separators, and the trailing word are all configurable.
toWords(2_500_000, 'EUR', { caseStyle: 'upper' });
// "TWO MILLION FIVE HUNDRED THOUSAND EUROS ONLY"

toWords(-1234.56, 'GBP');
// "Negative one thousand two hundred and thirty-four pounds sterling and fifty-six pence"

// Or drop currency entirely and just spell the number.
numberToWords(123_456);
// "one hundred and twenty-three thousand four hundred and fifty-six"

CommonJS works identically:

const { toWords } = require('money-in-words');

Options

Every option is optional; the defaults produce the strings shown above.

| Option | Type | Default | Description | | --------------------- | --------------------------------------------- | ------------ | -------------------------------------------------------------------- | | caseStyle | 'sentence' \| 'title' \| 'upper' \| 'lower' | 'sentence' | Capitalisation of the result. | | includeCurrencyName | boolean | true | Append unit names. false spells only the numerals. | | minorUnitSeparator | string | 'and' | Word joining major and minor parts. '' joins with a plain space. | | zeroMinorUnitsText | string \| null | 'only' | Appended when the currency has a minor unit but the amount has none. | | negativeWord | string | 'negative' | Word placed before a negative amount. | | rounding | 'truncate' \| 'round' \| 'floor' \| 'ceil' | 'truncate' | How extra decimal places are reduced to the currency's precision. | | useAnd | boolean | true | British "one hundred and one" vs American "one hundred one". |

[!IMPORTANT] zeroMinorUnitsText applies only to currencies that actually have a minor unit. toWords(1000, 'JPY') is "One thousand yen" — never "… yen only".


API surface

function toWords(
  amount: number,
  currencyCode: string,
  options?: ToWordsOptions,
): string;

function numberToWords(value: number, options?: NumberToWordsOptions): string;

// Currency lookup
function getCurrency(code: string): CurrencyInfo; // throws on unknown
function findCurrency(code: string): CurrencyInfo | undefined;
function isSupportedCurrency(code: string): boolean;
function listCurrencies(): CurrencyInfo[];

// Data
const CURRENCIES: Readonly<Record<string, CurrencyInfo>>;
const CURRENCY_CODES: readonly string[];
const ISO_4217_PUBLISHED: string;
const MAX_SUPPORTED_AMOUNT: number;
  • currencyCode is matched case-insensitively and trimmed — 'usd', ' USD ' and 'Usd' all resolve.
  • amount accepts any finite number with Math.abs(amount) < 1e15.

No currency involved. A fractional part is read digit by digit after "point", which is how English reads decimals aloud.

numberToWords(0); // "zero"
numberToWords(21); // "twenty-one"
numberToWords(101); // "one hundred and one"
numberToWords(1001); // "one thousand and one"
numberToWords(1_000_101); // "one million one hundred and one"
numberToWords(-1042); // "negative one thousand and forty-two"
numberToWords(3.14); // "three point one four"

| Option | Type | Default | Description | | -------------- | --------- | ------------ | --------------------------------------- | | useAnd | boolean | true | British "and" placement. | | negativeWord | string | 'negative' | Prefix for negative values. | | decimalWord | string | 'point' | Word introducing the fractional digits. |

Grouping is driven by a plain list of scale names — thousand, million, billion, trillion, quadrillion, quintillion, sextillion — so extending the range means adding an entry, not rewriting the algorithm.

import { getCurrency } from 'money-in-words';

getCurrency('INR');
// {
//   code: 'INR', numericCode: '356', name: 'Indian Rupee',
//   decimals: 2, symbol: '₹',
//   major: { one: 'Indian rupee', other: 'Indian rupees' },
//   minor: { one: 'paisa',        other: 'paise' },
//   isFund: false,
// }
interface CurrencyInfo {
  readonly code: string; // ISO 4217 alpha-3
  readonly numericCode: string; // ISO 4217 numeric, zero-padded
  readonly name: string; // official ISO entity name
  readonly decimals: number; // 0 | 2 | 3 | 4
  readonly symbol: string | null;
  readonly major: CurrencyUnitNames; // { one, other }
  readonly minor: CurrencyUnitNames | null; // null when there is no minor unit
  readonly isFund: boolean; // funds, metals, X… reserved codes
}

minor is null for every 0-decimal currency and for the non-tender codes — that null is what drives the "Forty-five yen" vs "… only" behaviour, rather than a hard-coded list of exceptions.

Every failure throws a subclass of MoneyInWordsError, each carrying a machine-readable code — catch broadly or narrowly.

| Class | code | Thrown when | | ----------------------- | --------------------- | ---------------------------------------------------- | | MoneyInWordsError | — | Base class for everything below. | | InvalidAmountError | INVALID_AMOUNT | Amount is NaN, Infinity, or not a number. | | AmountOutOfRangeError | AMOUNT_OUT_OF_RANGE | Math.abs(amount) >= 1e15. | | InvalidCurrencyError | INVALID_CURRENCY | Currency code is not in the ISO 4217 table. | | InvalidOptionError | INVALID_OPTION | caseStyle or rounding is not a recognised value. |

import { InvalidCurrencyError } from 'money-in-words';

try {
  toWords(1, 'XYZ');
} catch (error) {
  if (error instanceof InvalidCurrencyError) {
    console.error(error.code, error.currencyCode); // "INVALID_CURRENCY" "XYZ"
  }
}

Nothing fails silently: an out-of-range amount throws rather than producing a wrong string.


Examples

| Call | Result | | --------------------------------------------------------- | --------------------------------------------------------------------------------------------- | | toWords(1000.34, 'USD') | One thousand US dollars and thirty-four cents | | toWords(1000, 'BDT') | One thousand taka only | | toWords(45.5, 'JPY') | Forty-five yen | | toWords(1.234, 'BHD') | One Bahraini dinar and two hundred and thirty-four fils | | toWords(1234.567, 'KWD') | One thousand two hundred and thirty-four Kuwaiti dinars and five hundred and sixty-seven fils | | toWords(12345.67, 'INR') | Twelve thousand three hundred and forty-five Indian rupees and sixty-seven paise | | toWords(2.5, 'GBP') | Two pounds sterling and fifty pence | | toWords(0.01, 'GBP') | Zero pounds sterling and one penny | | toWords(1, 'USD') | One US dollar only | | toWords(0, 'USD') | Zero US dollars only | | toWords(1000.1, 'USD') | One thousand US dollars and ten cents | | toWords(-1234.56, 'EUR') | Negative one thousand two hundred and thirty-four euros and fifty-six cents | | toWords(999999999999.99, 'USD') | Nine hundred and ninety-nine billion … US dollars and ninety-nine cents | | toWords(2, 'LSL') | Two maloti only | | toWords(1000, 'XOF') | One thousand CFA francs BCEAO | | toWords(45.5, 'JPY', { rounding: 'round' }) | Forty-six yen | | toWords(1000.34, 'USD', { caseStyle: 'title' }) | One Thousand US Dollars And Thirty-Four Cents | | toWords(1000.34, 'USD', { caseStyle: 'upper' }) | ONE THOUSAND US DOLLARS AND THIRTY-FOUR CENTS | | toWords(1000.34, 'USD', { includeCurrencyName: false }) | One thousand and thirty-four | | toWords(1000, 'BDT', { zeroMinorUnitsText: null }) | One thousand taka | | toWords(101.05, 'USD', { useAnd: false }) | One hundred one US dollars and five cents |


Precision, rounding, and floats

Amounts are decomposed from the number's exact shortest decimal representation (Number.prototype.toString), then scaled on digit strings. No float arithmetic ever touches the minor units, so the classic failure mode simply cannot happen:

toWords(1000.1, 'USD'); // "One thousand US dollars and ten cents"   — not nine
toWords(0.1 + 0.2, 'USD'); // "Zero US dollars and thirty cents"

Digits beyond the currency's precision are truncated by default, which is what makes toWords(45.5, 'JPY') read "Forty-five yen". For half-away-from-zero rounding — the usual choice for financial documents — ask for it explicitly:

toWords(45.5, 'JPY', { rounding: 'round' }); // "Forty-six yen"
toWords(9.999, 'USD', { rounding: 'round' }); // "Ten US dollars only"
toWords(999.999, 'USD', { rounding: 'ceil' }); // "One thousand US dollars only"

Carries propagate correctly across the decimal point in every mode.

Range

Supported: Math.abs(amount) < 1e15, i.e. up to 999,999,999,999,999.xxx. That ceiling sits below Number.MAX_SAFE_INTEGER, so every integer this package accepts is exactly representable as an IEEE-754 double. Anything at or beyond it throws AmountOutOfRangeError.


Currency support

decimals is the ISO minor-unit digit count. A blank minor unit means the currency has no subdivision in circulation. Codes marked (fund) are non-tender: precious metals, bond market units, index/fund codes, and the reserved XTS / XXX.

| Code | Name | Dec | Symbol | Major unit (sing. / pl.) | Minor unit (sing. / pl.) | | ----- | -------------------------------------------------------------------------- | --: | ------ | ------------------------------------------------------------------------ | ------------------------ | | AED | UAE Dirham | 2 | د.إ | UAE dirham / UAE dirhams | fils | | AFN | Afghani | 2 | ؋ | afghani / afghanis | pul | | ALL | Lek | 2 | L | lek / lekë | qindarkë / qindarka | | AMD | Armenian Dram | 2 | ֏ | Armenian dram / Armenian drams | luma | | AOA | Kwanza | 2 | Kz | kwanza / kwanzas | cêntimo / cêntimos | | ARS | Argentine Peso | 2 | $ | Argentine peso / Argentine pesos | centavo / centavos | | AUD | Australian Dollar | 2 | $ | Australian dollar / Australian dollars | cent / cents | | AWG | Aruban Florin | 2 | ƒ | Aruban florin / Aruban florins | cent / cents | | AZN | Azerbaijan Manat | 2 | ₼ | Azerbaijani manat | qəpik | | BAM | Convertible Mark | 2 | KM | convertible mark / convertible marks | fening / fenings | | BBD | Barbados Dollar | 2 | $ | Barbados dollar / Barbados dollars | cent / cents | | BDT | Taka | 2 | ৳ | taka | poisha | | BHD | Bahraini Dinar | 3 | .د.ب | Bahraini dinar / Bahraini dinars | fils | | BIF | Burundi Franc | 0 | FBu | Burundi franc / Burundi francs | — | | BMD | Bermudian Dollar | 2 | $ | Bermudian dollar / Bermudian dollars | cent / cents | | BND | Brunei Dollar | 2 | $ | Brunei dollar / Brunei dollars | sen | | BOB | Boliviano | 2 | Bs. | boliviano / bolivianos | centavo / centavos | | BOV | Mvdol (fund) | 2 | — | mvdol | — | | BRL | Brazilian Real | 2 | R$ | Brazilian real / Brazilian reais | centavo / centavos | | BSD | Bahamian Dollar | 2 | $ | Bahamian dollar / Bahamian dollars | cent / cents | | BTN | Ngultrum | 2 | Nu. | ngultrum | chhertum | | BWP | Pula | 2 | P | pula | thebe | | BYN | Belarusian Ruble | 2 | Br | Belarusian ruble / Belarusian rubles | kopeck / kopecks | | BZD | Belize Dollar | 2 | $ | Belize dollar / Belize dollars | cent / cents | | CAD | Canadian Dollar | 2 | $ | Canadian dollar / Canadian dollars | cent / cents | | CDF | Congolese Franc | 2 | FC | Congolese franc / Congolese francs | centime / centimes | | CHE | WIR Euro (fund) | 2 | — | WIR euro / WIR euros | cent / cents | | CHF | Swiss Franc | 2 | CHF | Swiss franc / Swiss francs | rappen | | CHW | WIR Franc (fund) | 2 | — | WIR franc / WIR francs | centime / centimes | | CLF | Unidad de Fomento (fund) | 4 | UF | unidad de fomento / unidades de fomento | — | | CLP | Chilean Peso | 0 | $ | Chilean peso / Chilean pesos | — | | CNY | Yuan Renminbi | 2 | ¥ | yuan | fen | | COP | Colombian Peso | 2 | $ | Colombian peso / Colombian pesos | centavo / centavos | | COU | Unidad de Valor Real (fund) | 2 | — | unidad de valor real / unidades de valor real | — | | CRC | Costa Rican Colon | 2 | ₡ | Costa Rican colón / Costa Rican colones | céntimo / céntimos | | CUP | Cuban Peso | 2 | $ | Cuban peso / Cuban pesos | centavo / centavos | | CVE | Cabo Verde Escudo | 2 | $ | Cabo Verde escudo / Cabo Verde escudos | centavo / centavos | | CZK | Czech Koruna | 2 | Kč | Czech koruna / Czech koruny | haléř / haléřů | | DJF | Djibouti Franc | 0 | Fdj | Djibouti franc / Djibouti francs | — | | DKK | Danish Krone | 2 | kr | Danish krone / Danish kroner | øre | | DOP | Dominican Peso | 2 | RD$ | Dominican peso / Dominican pesos | centavo / centavos | | DZD | Algerian Dinar | 2 | د.ج | Algerian dinar / Algerian dinars | centime / centimes | | EGP | Egyptian Pound | 2 | E£ | Egyptian pound / Egyptian pounds | piastre / piastres | | ERN | Nakfa | 2 | Nfk | nakfa | cent / cents | | ETB | Ethiopian Birr | 2 | Br | Ethiopian birr | santim | | EUR | Euro | 2 | € | euro / euros | cent / cents | | FJD | Fiji Dollar | 2 | $ | Fiji dollar / Fiji dollars | cent / cents | | FKP | Falkland Islands Pound | 2 | £ | Falkland Islands pound / Falkland Islands pounds | penny / pence | | GBP | Pound Sterling | 2 | £ | pound sterling / pounds sterling | penny / pence | | GEL | Lari | 2 | ₾ | lari | tetri | | GHS | Ghana Cedi | 2 | ₵ | Ghana cedi / Ghana cedis | pesewa / pesewas | | GIP | Gibraltar Pound | 2 | £ | Gibraltar pound / Gibraltar pounds | penny / pence | | GMD | Dalasi | 2 | D | dalasi | butut / bututs | | GNF | Guinean Franc | 0 | FG | Guinean franc / Guinean francs | — | | GTQ | Quetzal | 2 | Q | quetzal / quetzales | centavo / centavos | | GYD | Guyana Dollar | 2 | $ | Guyana dollar / Guyana dollars | cent / cents | | HKD | Hong Kong Dollar | 2 | HK$ | Hong Kong dollar / Hong Kong dollars | cent / cents | | HNL | Lempira | 2 | L | lempira / lempiras | centavo / centavos | | HTG | Gourde | 2 | G | gourde / gourdes | centime / centimes | | HUF | Forint | 2 | Ft | forint | fillér | | IDR | Rupiah | 2 | Rp | rupiah | sen | | ILS | New Israeli Sheqel | 2 | ₪ | new Israeli shekel / new Israeli shekels | agora / agorot | | INR | Indian Rupee | 2 | ₹ | Indian rupee / Indian rupees | paisa / paise | | IQD | Iraqi Dinar | 3 | ع.د | Iraqi dinar / Iraqi dinars | fils | | IRR | Iranian Rial | 2 | ﷼ | Iranian rial / Iranian rials | dinar / dinars | | ISK | Iceland Krona | 0 | kr | Iceland króna / Iceland krónur | — | | JMD | Jamaican Dollar | 2 | J$ | Jamaican dollar / Jamaican dollars | cent / cents | | JOD | Jordanian Dinar | 3 | د.ا | Jordanian dinar / Jordanian dinars | fils | | JPY | Yen | 0 | ¥ | yen | — | | KES | Kenyan Shilling | 2 | KSh | Kenyan shilling / Kenyan shillings | cent / cents | | KGS | Som | 2 | с | som | tyiyn | | KHR | Riel | 2 | ៛ | riel | sen | | KMF | Comorian Franc | 0 | CF | Comorian franc / Comorian francs | — | | KPW | North Korean Won | 2 | ₩ | North Korean won | chon | | KRW | Won | 0 | ₩ | won | — | | KWD | Kuwaiti Dinar | 3 | د.ك | Kuwaiti dinar / Kuwaiti dinars | fils | | KYD | Cayman Islands Dollar | 2 | $ | Cayman Islands dollar / Cayman Islands dollars | cent / cents | | KZT | Tenge | 2 | ₸ | tenge | tiyn | | LAK | Lao Kip | 2 | ₭ | Lao kip | att | | LBP | Lebanese Pound | 2 | ل.ل | Lebanese pound / Lebanese pounds | piastre / piastres | | LKR | Sri Lanka Rupee | 2 | Rs | Sri Lanka rupee / Sri Lanka rupees | cent / cents | | LRD | Liberian Dollar | 2 | $ | Liberian dollar / Liberian dollars | cent / cents | | LSL | Loti | 2 | L | loti / maloti | sente / lisente | | LYD | Libyan Dinar | 3 | ل.د | Libyan dinar / Libyan dinars | dirham / dirhams | | MAD | Moroccan Dirham | 2 | د.م. | Moroccan dirham / Moroccan dirhams | centime / centimes | | MDL | Moldovan Leu | 2 | L | Moldovan leu / Moldovan lei | ban / bani | | MGA | Malagasy Ariary | 2 | Ar | Malagasy ariary | iraimbilanja | | MKD | Denar | 2 | ден | denar / denari | deni | | MMK | Kyat | 2 | K | kyat | pya / pyas | | MNT | Tugrik | 2 | ₮ | tugrik / tugriks | möngö | | MOP | Pataca | 2 | MOP$ | pataca / patacas | avo / avos | | MRU | Ouguiya | 2 | UM | ouguiya | khoums | | MUR | Mauritius Rupee | 2 | ₨ | Mauritius rupee / Mauritius rupees | cent / cents | | MVR | Rufiyaa | 2 | ރ. | rufiyaa | laari | | MWK | Malawi Kwacha | 2 | MK | Malawi kwacha | tambala | | MXN | Mexican Peso | 2 | $ | Mexican peso / Mexican pesos | centavo / centavos | | MXV | Mexican Unidad de Inversion (UDI) (fund) | 2 | — | Mexican unidad de inversión / Mexican unidades de inversión | — | | MYR | Malaysian Ringgit | 2 | RM | Malaysian ringgit | sen | | MZN | Mozambique Metical | 2 | MT | Mozambique metical / Mozambique meticais | centavo / centavos | | NAD | Namibia Dollar | 2 | $ | Namibia dollar / Namibia dollars | cent / cents | | NGN | Naira | 2 | ₦ | naira | kobo | | NIO | Cordoba Oro | 2 | C$ | córdoba oro / córdobas oro | centavo / centavos | | NOK | Norwegian Krone | 2 | kr | Norwegian krone / Norwegian kroner | øre | | NPR | Nepalese Rupee | 2 | Rs | Nepalese rupee / Nepalese rupees | paisa / paise | | NZD | New Zealand Dollar | 2 | $ | New Zealand dollar / New Zealand dollars | cent / cents | | OMR | Rial Omani | 3 | ر.ع. | Omani rial / Omani rials | baisa | | PAB | Balboa | 2 | B/. | balboa / balboas | centésimo / centésimos | | PEN | Sol | 2 | S/ | sol / soles | céntimo / céntimos | | PGK | Kina | 2 | K | kina | toea | | PHP | Philippine Peso | 2 | ₱ | Philippine peso / Philippine pesos | sentimo / sentimos | | PKR | Pakistan Rupee | 2 | ₨ | Pakistan rupee / Pakistan rupees | paisa / paise | | PLN | Zloty | 2 | zł | zloty / zlotys | grosz / groszy | | PYG | Guarani | 0 | ₲ | guarani / guaranies | — | | QAR | Qatari Rial | 2 | ر.ق | Qatari riyal / Qatari riyals | dirham / dirhams | | RON | Romanian Leu | 2 | lei | Romanian leu / Romanian lei | ban / bani | | RSD | Serbian Dinar | 2 | дин. | Serbian dinar / Serbian dinars | para | | RUB | Russian Ruble | 2 | ₽ | Russian ruble / Russian rubles | kopeck / kopecks | | RWF | Rwanda Franc | 0 | FRw | Rwanda franc / Rwanda francs | — | | SAR | Saudi Riyal | 2 | ر.س | Saudi riyal / Saudi riyals | halala / halalas | | SBD | Solomon Islands Dollar | 2 | $ | Solomon Islands dollar / Solomon Islands dollars | cent / cents | | SCR | Seychelles Rupee | 2 | ₨ | Seychelles rupee / Seychelles rupees | cent / cents | | SDG | Sudanese Pound | 2 | ج.س. | Sudanese pound / Sudanese pounds | piastre / piastres | | SEK | Swedish Krona | 2 | kr | Swedish krona / Swedish kronor | öre | | SGD | Singapore Dollar | 2 | S$ | Singapore dollar / Singapore dollars | cent / cents | | SHP | Saint Helena Pound | 2 | £ | Saint Helena pound / Saint Helena pounds | penny / pence | | SLE | Leone | 2 | Le | leone / leones | cent / cents | | SOS | Somali Shilling | 2 | Sh | Somali shilling / Somali shillings | cent / cents | | SRD | Surinam Dollar | 2 | $ | Surinam dollar / Surinam dollars | cent / cents | | SSP | South Sudanese Pound | 2 | £ | South Sudanese pound / South Sudanese pounds | piastre / piastres | | STN | Dobra | 2 | Db | dobra / dobras | cêntimo / cêntimos | | SVC | El Salvador Colon | 2 | ₡ | El Salvador colón / El Salvador colones | centavo / centavos | | SYP | Syrian Pound | 2 | ل.س | Syrian pound / Syrian pounds | piastre / piastres | | SZL | Lilangeni | 2 | L | lilangeni / emalangeni | cent / cents | | THB | Baht | 2 | ฿ | baht | satang | | TJS | Somoni | 2 | ЅМ | somoni | diram / dirams | | TMT | Turkmenistan New Manat | 2 | m | Turkmenistan new manat | tenge | | TND | Tunisian Dinar | 3 | د.ت | Tunisian dinar / Tunisian dinars | millime / millimes | | TOP | Pa’anga | 2 | T$ | paʻanga | seniti | | TRY | Turkish Lira | 2 | ₺ | Turkish lira | kuruş | | TTD | Trinidad and Tobago Dollar | 2 | TT$ | Trinidad and Tobago dollar / Trinidad and Tobago dollars | cent / cents | | TWD | New Taiwan Dollar | 2 | NT$ | New Taiwan dollar / New Taiwan dollars | cent / cents | | TZS | Tanzanian Shilling | 2 | TSh | Tanzanian shilling / Tanzanian shillings | cent / cents | | UAH | Hryvnia | 2 | ₴ | hryvnia / hryvnias | kopiyka / kopiykas | | UGX | Uganda Shilling | 0 | USh | Uganda shilling / Uganda shillings | — | | USD | US Dollar | 2 | $ | US dollar / US dollars | cent / cents | | USN | US Dollar (Next day) (fund) | 2 | — | US dollar (next day) / US dollars (next day) | cent / cents | | UYI | Uruguay Peso en Unidades Indexadas (UI) (fund) | 0 | — | Uruguay peso en unidades indexadas / Uruguay pesos en unidades indexadas | — | | UYU | Peso Uruguayo | 2 | $U | Uruguayan peso / Uruguayan pesos | centésimo / centésimos | | UYW | Unidad Previsional (fund) | 4 | — | unidad previsional / unidades previsionales | — | | UZS | Uzbekistan Sum | 2 | so'm | Uzbekistan sum | tiyin | | VED | Bolívar Soberano | 2 | Bs. | bolívar soberano / bolívares soberanos | céntimo / céntimos | | VES | Bolívar Soberano | 2 | Bs. | bolívar soberano / bolívares soberanos | céntimo / céntimos | | VND | Dong | 0 | ₫ | dong | — | | VUV | Vatu | 0 | VT | vatu | — | | WST | Tala | 2 | WS$ | tala | sene | | XAD | Arab Accounting Dinar (fund) | 2 | — | Arab accounting dinar / Arab accounting dinars | — | | XAF | CFA Franc BEAC | 0 | FCFA | CFA franc BEAC / CFA francs BEAC | — | | XAG | Silver (fund) | 0 | — | troy ounce of silver / troy ounces of silver | — | | XAU | Gold (fund) | 0 | — | troy ounce of gold / troy ounces of gold | — | | XBA | Bond Markets Unit European Composite Unit (EURCO) (fund) | 0 | — | European composite unit / European composite units | — | | XBB | Bond Markets Unit European Monetary Unit (E.M.U.-6) (fund) | 0 | — | European monetary unit / European monetary units | — | | XBC | Bond Markets Unit European Unit of Account 9 (E.U.A.-9) (fund) | 0 | — | European unit of account 9 / European units of account 9 | — | | XBD | Bond Markets Unit European Unit of Account 17 (E.U.A.-17) (fund) | 0 | — | European unit of account 17 / European units of account 17 | — | | XCD | East Caribbean Dollar | 2 | $ | East Caribbean dollar / East Caribbean dollars | cent / cents | | XCG | Caribbean Guilder | 2 | Cg | Caribbean guilder / Caribbean guilders | cent / cents | | XDR | SDR (Special Drawing Right) (fund) | 0 | SDR | special drawing right / special drawing rights | — | | XOF | CFA Franc BCEAO | 0 | CFA | CFA franc BCEAO / CFA francs BCEAO | — | | XPD | Palladium (fund) | 0 | — | troy ounce of palladium / troy ounces of palladium | — | | XPF | CFP Franc | 0 | ₣ | CFP franc / CFP francs | — | | XPT | Platinum (fund) | 0 | — | troy ounce of platinum / troy ounces of platinum | — | | XSU | Sucre (fund) | 0 | — | sucre / sucres | — | | XTS | Codes specifically reserved for testing purposes (fund) | 0 | — | testing unit / testing units | — | | XUA | ADB Unit of Account (fund) | 0 | — | ADB unit of account / ADB units of account | — | | XXX | The codes assigned for transactions where no currency is involved (fund) | 0 | — | no currency unit / no currency units | — | | YER | Yemeni Rial | 2 | ﷼ | Yemeni rial / Yemeni rials | fils | | ZAR | Rand | 2 | R | rand | cent / cents | | ZMW | Zambian Kwacha | 2 | ZK | Zambian kwacha | ngwee | | ZWG | Zimbabwe Gold | 2 | ZiG | Zimbabwe gold | cent / cents |


Regenerating the currency table

src/data/currencies.ts is generated, never hand-edited:

pnpm run gen:currencies

It merges the vendored scripts/data/iso-4217-list-one.xml (official ISO List One) with the curated English unit names in scripts/unit-names.mjs, then rewrites the table above.

[!NOTE] ISO 4217 publishes the code, numeric code, entity name and minor-unit digits — it does not publish minor-unit names, plurals, or symbols. Those are curated. The generator fails loudly if the two sources ever drift apart, and CI re-runs it on every push to prove the committed table still matches its source.


Development

pnpm install
pnpm run lint       # ESLint, type-aware and strict
pnpm run typecheck  # tsc --noEmit
pnpm test           # vitest — 379 tests
pnpm run coverage   # + v8 coverage, gated at 95% lines / 90% branches
pnpm run build      # tsup → dual ESM + CJS + .d.ts in dist/
pnpm run smoke      # exercise the built bundles on bare Node

CI runs all of the above on Node 22, then smoke-tests the built ESM and CJS bundles on Node 18, 20, 22 and 24.


License

MIT © Pranta Das