NLTK is fantastic. The API is clean, and it does just about everything you'd want from an NLP library. The only drawback being it's pure Python, and on large inputs that starts to show. A single call is fine. A million calls in a data pipeline is a different story.
fastNLTK is NLTK with the hot path rewritten in Rust. Same API, same data, same results. Just faster — 5× to 455× depending on what you're doing. No new dependencies, no YAML files, no config. Simply change your import and watch your code fly.
# Before
import nltk
tokens = nltk.word_tokenize("The quick brown fox.")
# After
import fastnltk as nltk
tokens = nltk.word_tokenize("The quick brown fox.") # same call, 5–50× faster
Your NLTK data (corpora, models, pickles, all of it) still works. Nothing to re-download, nothing to migrate.
Benchmarks
368 Python drop-in compatibility tests against NLTK. 6 skipped (chat stdin). 1 expected failure.
Benchmarked on release builds against NLTK 3.10. Full results →
| Operation | NLTK | fastNLTK | Speedup |
|---|---|---|---|
| TextTiling tokenizer | 22043 ms | 32 ms | 698× |
| Maxent train | 33 ms | 0.08 ms | 431× |
| windowdiff | 2.38 ms | 0.01 ms | 174× |
| edit_distance | 2.44 ms | 0.02 ms | 144× |
| HMM tagger | 8.58 ms | 0.10 ms | 88× |
| pk | 2.23 ms | 0.03 ms | 83× |
| Treebank detokenizer | 6.69 ms | 0.12 ms | 54× |
| Sentiment (VADER) | 67.54 ms | 1.79 ms | 38× |
| Punkt sentence tokenizer | 14.28 ms | 0.43 ms | 33× |
| Expression.fromstring | 16.06 ms | 0.54 ms | 30× |
| Tweet tokenizer | 83.00 ms | 3.26 ms | 25× |
| CFG grammar parser | 0.05 ms | 0.00 ms | 23× |
| Quadgram collocations | 98.74 ms | 5.11 ms | 19× |
| Lancaster stemmer | 31.50 ms | 1.42 ms | 22× |
| Snowball stemmer | 21.60 ms | 1.77 ms | 12× |
Geometric mean across 51 benchmarks: 9.5×. Module-level breakdown:
| Module | Geo Mean | Top single |
|---|---|---|
| metrics | 128× | 174× |
| sentiment | 38× | 38× |
| sem | 30× | 30× |
| classify | 25× | 431× |
| collocations | 14× | 19× |
| tree | 11× | 11× |
| translate | 10× | 10× |
| stem | 9× | 22× |
| chunk | 9× | 9× |
| tokenize | 8× | 698× |
| cluster | 6× | 6× |
| tag | 5× | 88× |
| parse | 4× | 23× |
| probability | 4× | 4× |
| chat | 3× | 3× |
| ccg | 3× | 3× |
What's accelerated
Every module that has a Rust-backed engine:
| Module | What's in Rust |
|---|---|
tokenize |
Treebank, Toktok, Tweet, Regexp, Space, MWE, TextTiling, Punkt, SExpr, Logos DFA |
stem |
Porter, Lancaster (full 124 rules), Snowball, Regexp, WordNet, ARLSTem, Cistem, ISRI, RSLP |
tag |
PerceptronTagger, HMM (integer Viterbi), TnT, Default/Unigram/Bigram/Trigram/Regexp/Affix |
classify |
NaiveBayes, Maxent (GIS), TextCat |
corpus |
PlaintextCorpusReader, TaggedCorpusReader, CategorizedPlaintextCorpusReader |
probability |
FreqDist, ConditionalFreqDist (shared references), MLE/Laplace/Lidstone prob dists |
lm |
MLE, Lidstone, Laplace, Kneser-Ney interpolated, Witten-Bell, StupidBackoff |
collocations |
Bigram/Trigram/Quadgram finders |
metrics |
edit_distance, jaccard, windowdiff, pk, BLEU, association, agreement, Spearman |
parse |
CFG, Earley chart parser |
tree |
Tree (bracket parse, subtrees, productions, leaves) |
chunk |
RegexpParser (NP/VP IOB extraction) |
sentiment |
VADER |
sem |
FOL expression parser, model evaluation |
inference |
Tableau prover, Resolution prover, Discourse |
cluster |
K-means |
chat |
Eliza-style chatbot |
translate |
BLEU score |
Not in Rust yet? Those calls fall through to NLTK automatically. Your code still works.
Install
pip install fastnltk
Pre-built wheels for Linux (x86_64, aarch64), macOS (x86_64, arm64), Windows (x64). Python 3.10–3.13.
Make sure you have the NLTK data you need:
python -m nltk.downloader punkt averaged_perceptron_tagger wordnet
Usage
Everything lives under fastnltk with the same names and signatures as nltk.
from fastnltk import word_tokenize, pos_tag, sent_tokenize
# Sentence segmentation (Punkt, Rust)
sents = sent_tokenize("Dr. Smith left at 5 p.m. He went home.")
# → ['Dr. Smith left at 5 p.m.', 'He went home.']
# Word tokenization (Treebank, Rust)
tokens = word_tokenize("The quick brown fox jumps over the lazy dog.")
# → ['The', 'quick', 'brown', 'fox', 'jumps', 'over', 'the', 'lazy', 'dog', '.']
# POS tagging (Perceptron, Rust)
tagged = pos_tag(tokens)
# → [('The', 'DT'), ('quick', 'JJ'), ...]
Drop it in as a direct NLTK replacement:
import fastnltk as nltk
# All your existing nltk.* calls now run through Rust
nltk.word_tokenize("Hello, world!")
nltk.pos_tag(["Hello", "world"])
nltk.ne_chunk(nltk.pos_tag(["John", "lives", "in", "Boston"]))
For module-level imports:
from fastnltk.stem import PorterStemmer, LancasterStemmer
from fastnltk.tag import PerceptronTagger
from fastnltk.parse import CFG, EarleyChartParser
from fastnltk.probability import FreqDist, ConditionalFreqDist
from fastnltk.lm import MLE, KneserNeyInterpolated
from fastnltk.metrics import edit_distance, jaccard_distance
from fastnltk.collocations import BigramCollocationFinder
from fastnltk.tree import Tree
# Same API as NLTK everywhere
stemmer = LancasterStemmer()
stemmer.stem("maximum") # → 'maxim'
stemmer.stem("presumably") # → 'presum'
fd = FreqDist("hello world")
fd["l"] # → 3
fd.max() # → 'l'
tagger = PerceptronTagger()
tagger.tag(["I", "love", "NLP"]) # → [('I', 'PRP'), ('love', 'VBP'), ('NLP', 'NNP')]
tree = Tree.from_string("(S (NP I/PRP) (VP love/VBP NLP/NNP))")
tree.leaves() # → ['I/PRP', 'love/VBP', 'NLP/NNP']
tree.productions() # → ['S -> NP VP', 'NP -> I/PRP', 'VP -> love/VBP NLP/NNP']
From source
git clone https://github.com/wyattferguson/fastnltk
cd fastnltk
pip install maturin
maturin develop --release
Development
pip install -e ".[dev]"
maturin develop --release
cargo test # Rust unit tests (309 pass)
pytest tests/ # 375 Python tests (368 pass, 6 skip, 1 xfail)
cargo fmt --all -- --check
cargo clippy --lib
ruff check fastnltk/ tests/
See CONTRIBUTING.md for full setup and PR workflow.
Compatibility
The goal is 100% drop-in. Right now 368 of 375 tests pass (6 skipped — chat bots read stdin), with only 1 expected failure:
- CCG
fromstring— NLTK 3.10'sccg.chart.fromstringis broken (upstream bug)
Every critical-path API (tokenize, tag, stem, metrics, prob, parse, chunk, sentiment, classify, collocations, tree, cluster, translate, chat) is verified byte-identical to NLTK across all tested inputs.
Platform
| Platform | Arch | Wheel |
|---|---|---|
| Linux | x86_64, aarch64 | ✅ |
| macOS | x86_64, arm64 | ✅ |
| Windows | x64 | ✅ |
License
Apache 2.0. Not affiliated with NLTK or its maintainers.
Contact + Support
Created by Wyatt Ferguson
For any questions or comments heres how you can reach me:
🐙 Follow me on Github @wyattferguson
📬 Email me at wyattxdev@duck.com
🍹 Follow on BlueSky @wyattf
Metadata
Release files for fastnltk 0.5.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| fastnltk-0.5.5.tar.gz | 270.3 kB | With provenance | Details for fastnltk-0.5.5.tar.gz |
Built distributions (wheels)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| fastnltk-0.5.5-cp310-abi3-win_amd64.whl | CPython 3.10 | abi3 | Windows x86-64 | Details for fastnltk-0.5.5-cp310-abi3-win_amd64.whl |
| fastnltk-0.5.5-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl | CPython 3.10 | abi3 | Linux glibc 2.17+ x86-64 | Details for fastnltk-0.5.5-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
| fastnltk-0.5.5-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl | CPython 3.10 | abi3 | Linux glibc 2.17+ ARM64 | Details for fastnltk-0.5.5-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
Total release size: 4.8 MB
Release files / fastnltk-0.5.5.tar.gz
| Download URL | fastnltk-0.5.5.tar.gz |
|---|---|
| Size | 270.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e138a10fc7445eb6a5f19aebb3203243233d3f51dec233f1682f766b97c77ae2
|
|
BLAKE2b-256 checksum How to use checksums |
448433b757e8caa95f9a4be3886093840be01f514ff0343561469ef55c6739d6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 5, 2026.
Transparency logRelease files / fastnltk-0.5.5-cp310-abi3-win_amd64.whl
| Download URL | fastnltk-0.5.5-cp310-abi3-win_amd64.whl |
|---|---|
| Size | 1.4 MB |
| Tags | CPython 3.10 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
7b8cd3736750f0a657446ef81ab6adbf96715646c540604cadfff0d033903acc
|
|
BLAKE2b-256 checksum How to use checksums |
0e14ec211594bf1c6ee7fdd3046632946bc0be7ed7d2af7671edc5a20d1ade81
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 5, 2026.
Transparency logRelease files / fastnltk-0.5.5-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | fastnltk-0.5.5-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 1.6 MB |
| Tags | CPython 3.10 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
97d186c570aadb8cd505d952d8f56f5da0adfb2a46052742e3054b51af5eae7f
|
|
BLAKE2b-256 checksum How to use checksums |
0bb58cf75c87d66392b06bb7f12ef8132e0a2629132f0965d1457b5dc92e9009
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 5, 2026.
Transparency logRelease files / fastnltk-0.5.5-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | fastnltk-0.5.5-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 1.5 MB |
| Tags | CPython 3.10 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
0896d0cb529faea7dd3d3f300d04d2fedf43116a943609121c3027bbaf80c029
|
|
BLAKE2b-256 checksum How to use checksums |
e7ea053f5ccf529781e997ae447b327c0682364e11f4726dd4471fdec7ee82b4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 5, 2026.
Transparency logSecurity for fastnltk 0.5.5
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 4 files in this release have been uploaded with provenance metadata.
Attestation for fastnltk-0.5.5.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 5, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.