Model or dataset
huggingface/tokenizers avatar
huggingface/tokenizers

Hugging Face tokenizers: training a BPE, WordPiece or Unigram vocabulary in Python

💥 Fast State-of-the-Art Tokenizers optimized for Research and Production

11,036 stars1,197 forksRustApache-2.0

At a glance

What is it?
The Rust implementation behind Hugging Face tokenizers trains vocabularies and encodes text from Python, Node.js and Rust. This covers how the pipeline works, how to install it, and where it stops being the right tool.
Who is it for?
Adopt huggingface/tokenizers when you need to train a vocabulary on your own corpus, or when you want tokenization to run outside a training script. Skip it if you only ever call a pretrained model and never define special tokens, truncation or padding yourself, because the Transformers tokenizer wrappers already cover that path.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

What huggingface/tokenizers actually does that a plain split() does not

The project provides implementations of the tokenizers used by current language models, and the README states the focus is performance and versatility. It is aimed at two audiences at once: researchers who want to train a new vocabulary on their own corpus, and production teams who need the same tokenization to run fast on a server CPU. The README claims less than 20 seconds to tokenize a GB of text on a server's CPU, and points at a benchmark script under bindings/python/benches/test_tiktoken.py rather than publishing a table of numbers.

The work it takes over is the part that sits between raw text and a model. Normalization, pre-tokenization, the model itself, and post-processing are all configurable stages, and the README notes that normalization comes with alignment tracking, so it is always possible to get the part of the original sentence that corresponds to a given token. That alignment is the feature that distinguishes it from a regex split: if you need character offsets back, you need a tokenizer that tracks them. It also does the pre-processing the README lists as truncation, padding, and adding the special tokens a model needs.

The four-stage pipeline and where your configuration lands

A tokenizer built with this library is a chain. A normalizer cleans the text, a pre-tokenizer splits it into word-like units, a model maps those units to token IDs, and a post-processor adds whatever the model expects around the sequence. The quick example in the README shows the two pieces you choose explicitly: the model class and the pre-tokenizer.

python
from tokenizers import Tokenizer
from tokenizers.models import BPE

tokenizer = Tokenizer(BPE())

The README offers Byte-Pair Encoding, WordPiece or Unigram as the model choices. Pre-tokenization is set separately, and the README uses Whitespace as the example. That separation matters because the two are not coupled: you can change how text is split before the model sees it without retraining the vocabulary, and you can swap the model without touching the pre-tokenizer. The default construction is empty, so a tokenizer you instantiate this way knows nothing until you either train it or load a saved one.

The Rust crate under tokenizers/ is the original implementation; the bindings/ directory holds the Python and Node.js layers, and the Ruby binding lives in a separate repository contributed by an outside maintainer. That layout means the Python package is a wrapper over the same core the Rust users get, not a reimplementation, which is the reason the README can make one performance claim for both.

Installing tokenizers with pip and training a first vocabulary

The README gives two install paths. Released versions come from PyPI:

bash
pip install tokenizers

If you need the current main branch instead, the README shows installing from source with the subdirectory flag pointing at the Python binding:

bash
pip install git+https://github.com/huggingface/tokenizers.git#subdirectory=bindings/python

That second form requires a Rust toolchain on the machine, since the binding is compiled. The first form does not, assuming a wheel exists for your platform.

Training is two lines past the setup. You declare the special tokens you want reserved, then hand the trainer a list of files:

python
from tokenizers.trainers import BpeTrainer

trainer = BpeTrainer(special_tokens=["[UNK]", "[CLS]", "[SEP]", "[PAD]", "[MASK]"])
tokenizer.train(files=["wiki.train.raw", "wiki.valid.raw", "wiki.test.raw"], trainer=trainer)

The special_tokens list is where [UNK] comes from. The README's encode example prints [UNK] for the emoji in the input string, which tells you the vocabulary learned from those three wiki files has no entry for it. If you expect emoji to survive tokenization intact, that is a property of your training data and your pre-tokenizer, not something the library fixes for you.

Encoding is one call, and the README prints the token list rather than the IDs:

python
output = tokenizer.encode("Hello, y'all! How are you 😁 ?")
print(output.tokens)

The commented output in the README is ["Hello", ",", "y", "'", "all", "!", "How", "are", "you", "[UNK]", "?"]. Notice that y'all is split into y, ', and all by the Whitespace pre-tokenizer, and that the surrounding punctuation is its own token. If your downstream code assumes apostrophes stay attached, this example is the signal that they do not.

The Python binding is a compiled extension, and that shapes deployment

Because the Python package wraps Rust, the failure modes are the ones you get with any compiled extension. The README does not document what happens when no wheel matches your interpreter and platform, and it does not document a pure-Python fallback. The install-from-source command it gives assumes pip can build the crate, which means a working Rust toolchain and a build step in your image or CI job.

Parallelism is the other operational detail the README leaves to the documentation. Tokenizing in a process that already uses multiple threads, or in a service that forks after import, is where the interaction between the library's own thread pool and your runtime shows up. The search terms people use around this project include tokenizers_parallelism, which suggests it is a setting people go looking for rather than one they find in the README. Treat it as something to verify against your own deployment shape instead of assuming the default suits a forking server.

On Windows, the same compiled-extension story produces a different symptom: the search data includes people looking for what a tokenizers DLL is. That is a loading problem, not a tokenization problem, and it points back at how the extension was built or installed rather than at anything in the API.

When you should use the Transformers tokenizer instead

The most direct alternative for most Python users is the tokenizer that ships with the transformers library. The difference is scope, not speed. Transformers tokenizers are wrappers that load a pretrained vocabulary and its configuration together with the model, so you get the exact tokenization the checkpoint was trained with, plus the model-specific special tokens, without assembling a pipeline yourself. The tokenizers library is the lower layer: you choose the model class, the pre-tokenizer and the trainer, and you are responsible for keeping the resulting vocabulary consistent with whatever model consumes it.

That makes the choice fairly clean. If you are fine-tuning or running an existing checkpoint, the Transformers wrapper saves you from reimplementing a configuration that already exists. If you are training a vocabulary from scratch on domain text, or you need tokenization as a standalone step with offsets, or you want the same tokenizer callable from Rust or Node.js, then the extra control is the point. Using this library to reproduce a checkpoint's tokenization by hand is possible but it is work you did not need to do.

The README also links a benchmark script that compares against tiktoken, and states the results are hardware dependent. That comparison is about throughput on a specific instance type, not about output equivalence. Two tokenizers can be equally fast and still produce different token sequences, and if your model was trained with one of them, the other is wrong regardless of speed.

Licence, releases and the cost of tracking main

The repository is licensed Apache-2.0, and the LICENSE file sits at the top level. Apache-2.0 includes an explicit patent grant and requires that you preserve notices and state changes you make. If you vendor the code or ship a modified binding, that obligation follows the code. This is a description of the licence text, not legal advice; check it against your own distribution model.

The release cadence visible in the repository is uneven. v0.23.2 was tagged on 2026-09-03, v0.23.1 on 2026-04-27, and v0.22.2 on 2025-12-02. The last push to the repository was on 2026-09-15. The gap between v0.23.1 and v0.23.2 is roughly four months, and the gap before that is roughly five. If you install from PyPI you inherit whatever cadence that produces. If you install from the git URL in the README, you inherit every commit on main, including ones that have not appeared in a release, and you take on the Rust build step each time you upgrade. For a production service, pinning the PyPI version and reading RELEASE.md before moving is the cheaper path; the README does not describe a rollback procedure, so your pin is the rollback.

Editorial conclusion

Adopt huggingface/tokenizers when you need to train a vocabulary on your own corpus, or when you want tokenization to run outside a training script. Skip it if you only ever call a pretrained model and never define special tokens, truncation or padding yourself, because the Transformers tokenizer wrappers already cover that path. Before committing, verify that the wheel for your platform loads, that tokenizers_parallelism behaves the way your workload expects, and that the alignment offsets you get back are the ones your downstream code indexes into.

Frequently asked questions

How do I install huggingface/tokenizers?

The README gives two options. Run pip install tokenizers for a released version, or pip install git+https://github.com/huggingface/tokenizers.git#subdirectory=bindings/python to build the current main branch from source, which requires a Rust toolchain.

What is huggingface/tokenizers?

It is an implementation of commonly used tokenizers, written in Rust, with bindings for Python, Node.js and Rust. The README states the focus is performance and versatility, and that it is designed for research and production.

What are tokenizers in Python and what are they used for?

In this project the Python binding exposes the same core as the Rust crate, so you can train a vocabulary on your own files and encode text with it. The README's example trains a BPE tokenizer with a BpeTrainer and then prints the tokens for a sample sentence.

What are the different types of tokenizers?

The README names three model choices: Byte-Pair Encoding, WordPiece and Unigram. The model is set separately from the pre-tokenizer, so you can change how text is split into words without changing the model class.

What is tokenizers_parallelism in huggingface/tokenizers?

The README does not document it. It appears in search data around this project, but the only parallelism claim in the README is the performance statement about tokenizing a GB of text on a server CPU. Check the linked documentation before relying on a specific setting.

What is the tokenizers DLL on Windows?

The README does not mention a DLL. The Python package is a compiled extension over the Rust core, so a missing or mismatched binary on Windows is an installation or build issue rather than a documented feature of the library.

Official sources

  1. huggingface/tokenizers on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
Community notes

Community notes