API reference
Everything kanji.js 1.6.2 exports. The default export is the Kanji class, and all of its methods are static.
Kanji.getDetails()#
Returns the dictionary entry whose literal is exactly character, or null if there isn't one.
| Name | Type | Description |
|---|---|---|
| character | string | A single kanji, such as '日'. The match is exact: no trimming, no variant folding, and no lookup by reading or meaning. |
Kanji.getDetails('日') // { literal: '日', meanings: ['day', 'sun', …], … }Kanji.getDetails('日本') // null (only single characters are entries)Kanji.getDetails('ア') // null (kana are not in the dictionary)
The returned object is the dictionary's own entry, not a copy. Don't change it.
Kanji.search()#
Scans every entry in the dictionary. It drops the entries that fail the filters, scores the rest against the ranking hints, and returns them best match first.
| Name | Type | Description |
|---|---|---|
| grade | number | RangeOption | Filter. Keep entries with this school grade, or with a grade inside the range. See grade values. |
| jlpt | number | RangeOption | Filter. Keep entries with this JLPT level, or with a level inside the range. Levels use the old 1–4 scale. |
| meaning | string | Ranking hint. An English word or phrase, fuzzy-matched against each entry's meanings. |
| romaji | string | Ranking hint. A reading in romaji (or kana), fuzzy-matched against the on and kun readings. |
| sort | boolean | Default true. Set it to false to skip sorting and return matches in dictionary order. |
A RangeOption is { min?: number, max?: number }. Both ends are inclusive.
Kanji.search({ grade: 2 }) // grade 2 only (160 characters)Kanji.search({ jlpt: { min: 3 } }) // JLPT 3 and 4 (284 characters)Kanji.search({ grade: 1, meaning: 'water' })[0] // 水Kanji.search({ romaji: 'hi', jlpt: 4 })[0] // 火
Filters#
grade and jlpt are the only options that remove results. Each is checked in one of two ways:
- A number keeps entries whose value is exactly that number. Entries with
nullare always dropped. - A range drops entries below
minor abovemax. Aminalso drops entries withnull, but amaxon its own doesn't, because the library comparesnull > maxand that is false.
Kanji.search({ grade: { max: 6 } }).length // 11117, includes ungradedKanji.search({ grade: { min: 1, max: 6 } }).length // 1006, school kanji only
Ranking#
Every entry that passes the filters gets a score:
- It starts at 1, just for passing the filters.
- If you set
meaning, the library fuzzy-matches it against the entry'smeaningswith fuzzyset.js. A similarity of at least 0.75 adds that similarity (0.75–1) to the score. - If you set
romaji, the library converts it to katakana and matches it againstonyomi. It also converts it to hiragana and matches it againstkunyomi, using WanaKana. Each reading list that matches with a similarity of at least 0.75 adds its similarity, so a romaji match can add up to 2.
With sort on, results are ordered from the highest score down. Entries with the same score stay in dictionary order. Because every entry that passes the filters scores at least 1, ranking hints never remove results. A search with only meaning or romaji returns all 13,108 entries.
// Top five results for a meaningKanji.search({ meaning: 'water' }).slice(0, 5).map(k => k.literal)// ['水', '霑', '氵', '潑', '㴑']// Kana input works too, since WanaKana passes kana throughKanji.search({ romaji: 'みず' })[0].literal // '水'
Scores aren't returned. To keep only real matches, check the fields yourself. See Find characters with an exact reading.
Performance#
search() builds new fuzzy-match sets for every entry on every call, so a search with meaning or romaji takes a noticeable moment: about 0.3 seconds in Node.js 22 on a recent laptop. Searches with only filters are much faster. In a UI, debounce input, or run the search in a Web Worker.
Kanji.random()#
Returns a random entry from the whole dictionary. It takes no options, and the result is mostly rare characters, since about 77% of entries have no grade or JLPT level. It uses Math.random(), so it isn't suitable for anything security-related.
Kanji.random().literal // e.g. '幬'
Kanji.dump()#
Returns the full dictionary: 13,108 entries in KANJIDIC2 order. Every call returns the same array, the library's own copy, so treat it as read-only.
const all = Kanji.dump()all.length // 13108Kanji.dump() === all // trueconst sorted = [...all].sort((a, b) => a.stroke_count - b.stroke_count) // copy first
Instance properties#
You don't need an instance to use the library. Creating one gives you its name and version:
const k = new Kanji()k.name // 'Kanji'k.version // '1.6.2'
Types#
These are the shapes the library actually returns. They differ from the bundled index.d.ts in the fields marked null. Copy them into your project if you want TypeScript to catch the missing values.
export interface Word {literal: string // the character, e.g. '日'meanings: string[] // English meanings, may be emptyonyomi: string[] // on readings in katakana, may be emptykunyomi: string[] // kun readings in hiragana, may be emptystroke_count: numbergrade: number | null // 1–6, 8, 9 or 10, or nulljlpt: number | null // 1–4 (old scale), or nullfreq: number | null // 1–2501, or null}export interface RangeOption {min?: number // inclusivemax?: number // inclusive}export interface SearchOptions {grade?: number | RangeOptionjlpt?: number | RangeOptionmeaning?: stringromaji?: stringsort?: boolean // default true}
The Character data page describes each field and its values.
Known issues#
These are current behaviors of version 1.6.2. They may change in a future release.
- The bundled types don't allow
nullfromgetDetails(), or ingrade,jlptandfreq. random()never returns the last dictionary entry (頻).- A range with only
maxincludes entries with no value. Aminormaxof0is ignored. meaningandromajirank results but don't filter them.