Skip to content

SuzumeJapanese tokenization, right in the browser

A lightweight tokenizer compiled to WebAssembly. Under 227KiB gzipped, it runs entirely client-side — no server, no multi-megabyte dictionary.

v0.9.9BetaApache-2.0 · open source
227KiB
gzipped bundle
555KiB raw
100%
client-side
no server or API
6
runtimes
Browser · Node · Deno · Bun · Python · C/C++
Live

Tokenized as you read

From "I Am a Cat" by Natsume Soseki
Why Suzume

Designed for the frontend

Client-side Japanese tokenization, without the usual server, dictionary, and privacy trade-offs.

Tiny footprint

The WASM module and its built-in dictionary total under 227KiB gzipped — no multi-megabyte dictionary to fetch or host.

Client-side by design

Runs entirely in the browser or your runtime. No tokenization server, no API round-trip, no CORS setup.

Text stays local

Analysis happens on-device, so user input never leaves the browser and sensitive text stays out of your infrastructure.

Robust to unknown words

Boundaries come from character patterns rather than a fixed dictionary, so brand names, slang, and technical terms stay intact.

Synchronous and instant

Near-native WASM speed with a synchronous API. Tokenize on every keystroke without network latency.

Typed, multi-runtime

A C++ core with first-class TypeScript types, plus Python and native C/C++ bindings for backend, batch, and embedded use.

Playground

Try it on your own text

Choose an everyday, colloquial, dialectal, or classical example, or paste your own text. Processing stays in your browser.

Loading...
Compare

Where Suzume fits

TinySegmenter's light footprint, closer to MeCab's detail — Suzume sits between them.

FeatureIntl.Segmenter Built-inTinySegmenter LightSuzume kuromoji MeCab Accurate
Browser
External Dictionary SetupNot requiredNot requiredBundledRequiredRequired
Bundle Size0KB~10KB227KiB~20MBN/A
Server-free
POS Tagging
Lemmatization
Compound Nouns
Custom Dictionary
Unknown Words
There is more to the difference than this tableSee concrete examples of token boundaries, dictionary dependence, and unknown-word handling.Read the MeCab comparison How fast, and how accurate?Per-call latency, initialization cost, and what the accuracy figures do and do not cover.Read speed and accuracy

Installation

bash
npm install @libraz/suzume
bash
yarn add @libraz/suzume
bash
pnpm add @libraz/suzume
bash
bun add @libraz/suzume
bash
pip install suzume
bash
git clone https://github.com/libraz/go-suzume.git
cd go-suzume && make lib
cd /path/to/your/module
go mod edit -replace github.com/libraz/go-suzume=/path/to/go-suzume
go get github.com/libraz/go-suzume
bash
git clone https://github.com/libraz/suzume.git
cd suzume && make install

For Python services and data pipelines, see the Python bindings guide. Suzume is also available through the Go binding and as a C / C++ library.

Usage

The bindings expose the same analysis model with names adapted to each language:

typescript
import { Suzume } from '@libraz/suzume'

const suzume = await Suzume.create()

try {
  for (const m of suzume.analyze('東京都に住んでいます')) {
    console.log(m.surface, m.pos, m.baseForm)
  }
} finally {
  suzume.destroy()
}
python
from suzume import Suzume

with Suzume() as sz:
    for m in sz.analyze("東京都に住んでいます"):
        print(m.surface, m.pos, m.base_form)
go
package main

import (
  "fmt"
  "log"

  "github.com/libraz/go-suzume"
)

func main() {
  analyzer, err := suzume.New()
  if err != nil {
    log.Fatal(err)
  }
  defer analyzer.Close()

  for _, m := range analyzer.Analyze("東京都に住んでいます") {
    fmt.Println(m.Surface, m.POS, m.BaseForm)
  }
}
cpp
#include "suzume/suzume.hpp"
#include <cstdio>

int main() {
  suzume::Tokenizer tokenizer;
  for (const suzume::Morpheme& m : tokenizer.analyze("東京都に住んでいます"))
    std::printf("%s\t%s\t%s\n", m.surface.c_str(), m.pos.c_str(), m.base_form.c_str());
}

Each token carries a surface form, POS, base form, offsets, and more. See the JavaScript/WASM, Python, Go, or C / C++ reference for binding-specific names.