NLTK is the standard Python NLP library — teaching, research, prototyping. It works great, but it's pure Python. Tokenizing a 50K-word document takes ~40 ms in NLTK. That's fine for one-offs, but in a pipeline it adds up fast.
fastNLTK wraps the same API calls in Rust. Change your import, get the same results.
No new dependency tree — the Rust engine lives in a single .pyd/.so file shipped
with the wheel.
# 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
All your NLTK data (corpora, models, pickles) still works. Nothing to re-download.
Benchmarks
366 Python drop-in compatibility tests against NLTK. 6 skipped (chat stdin). 3 expected failures.
Benchmarked on release builds against NLTK 3.10. Full results →
| Operation | NLTK | fastNLTK | Speedup |
|---|---|---|---|
| TextTiling tokenizer | 22237 ms | 32 ms | 704× |
| Maxent classifier training | 31.93 ms | 0.08 ms | 425× |
| edit_distance | 2.48 ms | 0.01 ms | 176× |
| windowdiff | 2.35 ms | 0.01 ms | 172× |
| pk (segmentation) | 2.19 ms | 0.02 ms | 90× |
| Treebank detokenizer | 6.70 ms | 0.12 ms | 55× |
| VADER sentiment | 67.06 ms | 1.75 ms | 38× |
| sentence tokenizer (Punkt) | 14.65 ms | 0.44 ms | 33× |
| S-expression tokenizer | 0.36 ms | 0.01 ms | 30× |
| Expression parser | 16.47 ms | 0.55 ms | 30× |
| Tweet tokenizer | 83.96 ms | 3.31 ms | 25× |
| CFG grammar parser | 0.05 ms | 0.002 ms | 25× |
| Lancaster stemmer | 32.81 ms | 1.41 ms | 23× |
| quadgram collocations | 101.04 ms | 4.94 ms | 21× |
| Earley parser | 6.55 ms | 0.51 ms | 13× |
| Snowball stemmer | 21.84 ms | 1.79 ms | 12× |
| word tokenizer (Treebank) | 42.18 ms | 4.27 ms | 10× |
Geometric mean across 49 benchmarks: 10.1×. Module-level breakdown:
| Module | Geo Mean | Top single |
|---|---|---|
| metrics | 146× | 176× |
| sentiment | 38× | 38× |
| sem | 30× | 30× |
| parse | 18× | 25× |
| tokenize | 18× | 704× |
| collocations | 14× | 21× |
| tree | 11× | 11× |
| translate | 9× | 9× |
| stem | 9× | 23× |
| chunk | 9× | 9× |
| classify | 9× | 425× |
| cluster | 6× | 6× |
| chat | 6× | 6× |
| tag | 4× | 9× |
| probability | 4× | 5× |
| 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, TnT (integer Viterbi), HMM, Default/Unigram/Bigram/Trigram/Regexp/Affix taggers |
classify |
NaiveBayes, Maxent (GIS), TextCat |
probability |
FreqDist, ConditionalFreqDist, 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
pytest tests/ # 375 Python tests (366 pass, 6 skip, 3 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 366 of 375 tests pass (6 skipped — chat bots read stdin), with only 3 expected failures:
- Earley parse tree extraction — Rust Earley finds parses but the tree structure differs from NLTK's chart-printing format (WIP)
- ConditionalFreqDist clone semantics —
freqdist()returns a copy, so mutations don't propagate back the way NLTK's reference-sharing does (design limitation) - 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:
:octopus: Follow me on Github @wyattferguson
:mailbox_with_mail: Email me at wyattxdev@duck.com
:tropical_drink: Follow on BlueSky @wyattf
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fastnltk-0.5.2.tar.gz.
File metadata
- Download URL: fastnltk-0.5.2.tar.gz
- Upload date:
- Size: 266.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9d03f8595acf15be838d4a14c4340dde21bf9e83cb7b981748ac00be29fbb430
|
|
| MD5 |
787a4a42773b0520acd0059a45b82709
|
|
| BLAKE2b-256 |
5afe6921f9a83ef88e0dd82bfcf2649f94efebd7bc4b896726363d948cb27ff4
|
Provenance
The following attestation bundles were made for fastnltk-0.5.2.tar.gz:
Publisher:
release.yml on wyattferguson/fastNLTK
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fastnltk-0.5.2.tar.gz -
Subject digest:
9d03f8595acf15be838d4a14c4340dde21bf9e83cb7b981748ac00be29fbb430 - Sigstore transparency entry: 2188268634
- Sigstore integration time:
-
Permalink:
wyattferguson/fastNLTK@63c1414b3ffb2e0afaf2df479bee4d1ce05c009c -
Branch / Tag:
refs/tags/v0.5.2 - Owner: https://github.com/wyattferguson
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@63c1414b3ffb2e0afaf2df479bee4d1ce05c009c -
Trigger Event:
push
-
Statement type:
File details
Details for the file fastnltk-0.5.2-cp310-abi3-win_amd64.whl.
File metadata
- Download URL: fastnltk-0.5.2-cp310-abi3-win_amd64.whl
- Upload date:
- Size: 1.4 MB
- Tags: CPython 3.10+, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ee7a004d75e8da50bc8bedaff79fa1579deeab962a90080744fb2f648b86c74f
|
|
| MD5 |
85357c04fa4ef80a6eaa820337834cce
|
|
| BLAKE2b-256 |
ff35ab4b486560a3d6180e99d80ed54107717c15ccdbcccb255f49231aaffc66
|
Provenance
The following attestation bundles were made for fastnltk-0.5.2-cp310-abi3-win_amd64.whl:
Publisher:
release.yml on wyattferguson/fastNLTK
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fastnltk-0.5.2-cp310-abi3-win_amd64.whl -
Subject digest:
ee7a004d75e8da50bc8bedaff79fa1579deeab962a90080744fb2f648b86c74f - Sigstore transparency entry: 2188268643
- Sigstore integration time:
-
Permalink:
wyattferguson/fastNLTK@63c1414b3ffb2e0afaf2df479bee4d1ce05c009c -
Branch / Tag:
refs/tags/v0.5.2 - Owner: https://github.com/wyattferguson
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@63c1414b3ffb2e0afaf2df479bee4d1ce05c009c -
Trigger Event:
push
-
Statement type:
File details
Details for the file fastnltk-0.5.2-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: fastnltk-0.5.2-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 1.6 MB
- Tags: CPython 3.10+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
10460183ba0eeb888e56870e5614ca8234ec9b1439dc0dc0d67c016dd038f41d
|
|
| MD5 |
3f9cd5d211f7981c3a7539b887e5fe9b
|
|
| BLAKE2b-256 |
b848f53d7639c2fe952bc802574237111efd480f5ea461f2bd4d1e6c8bbed188
|
Provenance
The following attestation bundles were made for fastnltk-0.5.2-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
release.yml on wyattferguson/fastNLTK
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fastnltk-0.5.2-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
10460183ba0eeb888e56870e5614ca8234ec9b1439dc0dc0d67c016dd038f41d - Sigstore transparency entry: 2188268662
- Sigstore integration time:
-
Permalink:
wyattferguson/fastNLTK@63c1414b3ffb2e0afaf2df479bee4d1ce05c009c -
Branch / Tag:
refs/tags/v0.5.2 - Owner: https://github.com/wyattferguson
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@63c1414b3ffb2e0afaf2df479bee4d1ce05c009c -
Trigger Event:
push
-
Statement type:
File details
Details for the file fastnltk-0.5.2-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: fastnltk-0.5.2-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 1.4 MB
- Tags: CPython 3.10+, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
daa3fbb20c6ed7afa815274a682cb40ef361ae25d5e55d7f473953b75c5faf3b
|
|
| MD5 |
a56273cc9ee4d455aee3f77d03e702a2
|
|
| BLAKE2b-256 |
b28e56bf2dde277a338de2883712745f2f381789af708f40f5127331ae26d716
|
Provenance
The following attestation bundles were made for fastnltk-0.5.2-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:
Publisher:
release.yml on wyattferguson/fastNLTK
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fastnltk-0.5.2-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl -
Subject digest:
daa3fbb20c6ed7afa815274a682cb40ef361ae25d5e55d7f473953b75c5faf3b - Sigstore transparency entry: 2188268648
- Sigstore integration time:
-
Permalink:
wyattferguson/fastNLTK@63c1414b3ffb2e0afaf2df479bee4d1ce05c009c -
Branch / Tag:
refs/tags/v0.5.2 - Owner: https://github.com/wyattferguson
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@63c1414b3ffb2e0afaf2df479bee4d1ce05c009c -
Trigger Event:
push
-
Statement type: