Open-source project
barrust/pyspellchecker avatar
barrust/pyspellchecker

pyspellchecker suggests corrections from a word frequency list

Pure Python Spell Checking http://pyspellchecker.readthedocs.io/en/latest/

792 stars163 forksPythonMIT

At a glance

What is it?
pyspellchecker is a pure Python spell checker that finds words within a Levenshtein distance of two of its dictionary and ranks the candidates by frequency in a bundled word list. It suits spell checking of short text with a custom vocabulary, and it is not a language model and does not know your jargon until you tell it.
Who is it for?
Adopt pyspellchecker when you need a dependency-light spell checker for short user input, when you can supply your own vocabulary and frequency list, and when a pure Python implementation with no model download is a requirement. Do not adopt it for long documents, for prose where context decides the right word, or as a grammar or style checker.
Can I use it commercially?
Yes. MIT 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 13 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

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

Editorial analysis

Edit distance against a frequency ranked dictionary

The project describes itself as pure Python spell checking based on Peter Norvig's blog post on setting up a simple spell checking algorithm, and the mechanism is easy to follow. It uses a Levenshtein Distance algorithm to find permutations within an edit distance of two of the original word, then compares all of those permutations, insertions, deletions, replacements and transpositions, against known words in a word frequency list. The tie breaker is frequency: words that appear more often in the list are more likely to be the correct result. That design has one direct consequence. The tool does not understand the sentence a word came from, so it corrects the token, not the meaning. Two different misspellings that map to the same candidate set get the same answer. For a form field or a search box, where the intended word is usually a common one, that is enough. For a paragraph of prose, the missing context is what makes corrections read as wrong. The implementation is pure Python with no compiled extension and no model to download, which is the other half of why it is still in use.

The unknown, correction and candidates split the work in three

The API is small enough to learn in a minute, and the division of labour between three calls is the design worth remembering. unknown takes a list of words and returns the ones that are not in the dictionary. correction takes a single misspelled word and returns the single most probable result. candidates takes the same word and returns a set of possible candidates instead. That ordering lets a caller decide how much latitude to give the user. An interface that wants one suggestion asks for a correction, while an interface that wants to offer a dropdown asks for candidates and lets the person choose. The documented quickstart shows the pattern, checking a list of four words and then printing both the most likely answer and the list of likely options for each one that comes back:

python
from spellchecker import SpellChecker

spell = SpellChecker()

# find those words that may be misspelled
misspelled = spell.unknown(['something', 'is', 'hapenning', 'here'])

for word in misspelled:
    # Get the one `most likely` answer
    print(spell.correction(word))

    # Get a list of `likely` options
    print(spell.candidates(word))

The class is imported from the spellchecker package, and the on-line documentation at pyspellchecker.readthedocs.io carries the full method list beyond this summary.

Twelve bundled dictionaries, English by default

The package ships default dictionaries for several languages, and choosing one is a constructor argument. The documentation gives English, Spanish, Russian and Arabic as the examples:

python
from spellchecker import SpellChecker

english = SpellChecker()  # the default is English (language='en')
spanish = SpellChecker(language='es')  # use the Spanish Dictionary
russian = SpellChecker(language='ru')  # use the Russian Dictionary
arabic = SpellChecker(language='ar')   # use the Arabic Dictionary

The complete list in the documentation is longer than the examples suggest, and it includes English en, Spanish es, French fr, Portuguese pt, German de, Italian it, Russian ru, Arabic ar, Basque eu, Latvian lv, Dutch nl and Persian fa. English is the default, so a call with no arguments loads it. Two things are worth noting. First, a language identifier that is not in that list has no dictionary to load, so multilingual applications need to check that the variant they want actually ships. Second, all of these dictionaries are frequency lists built from subtitles rather than curated word lists, which shapes what they contain and what they miss.

Teaching it your own vocabulary is a first class feature

If the frequency list does not fit your domain, the documentation shows two ways to change it without patching the package. You can load a text file into the word frequency object, which is how you build a list appropriate to your own corpus:

python
from spellchecker import SpellChecker

spell = SpellChecker()  # loads default word frequency list
spell.word_frequency.load_text_file('./my_free_text_doc.txt')

Or you can add specific words outright, which is the fix for product names and internal jargon:

python
from spellchecker import SpellChecker

spell = SpellChecker()  # loads default word frequency list
spell.word_frequency.load_words(['microsoft', 'apple', 'google'])
spell.known(['microsoft', 'google'])  # will return both now!

This is the strongest argument for the library in an application context. A spell checker that flags your own product names on every keystroke is unusable, and here the fix is a list, not a fork. The same mechanism works in the other direction, since the frequency list is writable, so a deployment can subtract terms that should never be suggested.

Edit distance is the knob that decides whether corrections help

The default edit distance is two, and the package lets you change it at initialization or afterwards:

python
from spellchecker import SpellChecker

spell = SpellChecker(distance=1)  # set at initialization

# do some work on longer words

spell.distance = 2  # set the distance parameter back to the default

The guidance in the documentation is specific: for longer words it is highly recommended to use a distance of one and not the default two. The reasoning is about the candidate set. A distance of two on a long word generates a large number of permutations, and the frequency list then picks whichever of them happens to be common, which on long words is often a different word rather than the intended one. Reducing to one narrows the candidate set and makes the frequency ranking meaningful again. This is the single most common tuning decision in this library, and the fix is one line either at construction or on the instance.

The dictionaries are generated from subtitles and maintained by script

The dictionaries have a documented provenance and a documented maintenance path, which is unusual and useful to know. The project provides a script that, given a text file of sentences taken from OpenSubtitles, generates a word frequency list from the words found in the text. The script then attempts to clean up the frequency list, for example by removing words with invalid characters, usually ones from other languages, by removing low count terms that are likely misspellings, and by enforcing rules where they are available, such as no more than one accent per word in Spanish. It then removes words from a list of known words that are to be removed, and adds words that are known to be missing or were removed for being too low frequency. The script lives at scripts/build_dictionary.py, and the original frequency list parsed from OpenSubtitles sits in the scripts/data/ folder alongside each language's include and exclude text files. The documentation is upfront that this is not an exact science, and it asks for help maintaining the dictionaries through a GitHub discussion or pull requests against the include and exclude files. The practical upshot for a user is that a dictionary can be regenerated and adjusted, and the include and exclude lists are the lever for changing what it contains.

Packaging, versions and the cost of upgrading

Installation is a pip install of the package name, and a source build uses the standard build frontend:

bash
pip install pyspellchecker
bash
git clone https://github.com/barrust/pyspellchecker.git
cd pyspellchecker
python -m build

The build configuration in pyproject.toml requires Python 3.10 or newer and the classifiers cover 3.10 through 3.14, so the package is tracking current interpreter versions rather than carrying legacy ones. The version number is read dynamically from the spellchecker package attribute rather than written twice, which avoids the drift that plagues hardcoded versions. The licence is MIT, which is the simplest possible answer for a library you might embed in a commercial product. The release history shows v0.9.1 on 2026-10-10, v0.9.0 on 2026-03-07 and v0.8.4 on 2025-11-30, and the repository is not archived with the last push on 2026-10-10. One piece of history matters if you are on an old interpreter: Python 2.7 support lives in release 0.5.6, installed with a version pin, and the documentation states plainly that no future updates will support Python 2. A CHANGELOG.md at the repository root is where to look before a version bump.

Where a frequency list is the wrong tool

The alternative approaches differ in what they know. A language model based checker reads the sentence and resolves meaning, so it handles homophones, technical prose and context dependent words, at the cost of a model to download and inference to run. A dictionary backed checker like this one is fast, tiny and deterministic, and it fails exactly where context is required. A third option, using a platform or browser built in spell checking, gives you nothing to configure but also nothing to control, and it usually checks nothing outside a text field. The difference in approach between this library and a model based checker is the reason to choose it: it is pure Python with no network calls and no weights, so it runs inside a restricted environment and its behaviour is reproducible, and it can be taught a specific vocabulary in two lines. Its cost is that it corrects tokens, and on text where the right word depends on the sentence around it, a candidate list is as far as it can go.

Editorial conclusion

Adopt pyspellchecker when you need a dependency-light spell checker for short user input, when you can supply your own vocabulary and frequency list, and when a pure Python implementation with no model download is a requirement. Do not adopt it for long documents, for prose where context decides the right word, or as a grammar or style checker. Verify first that the edit distance you choose is appropriate for the length of the words you are checking, since the documentation recommends a distance of one for longer words, and confirm that the language variant you need is one of the twelve dictionaries the package ships.

Frequently asked questions

How do I install pyspellchecker and check a word?

Install it with pip install pyspellchecker, then create a SpellChecker instance, pass a list of words to spell.unknown to find the misspelled ones, and use spell.correction for the single most likely result or spell.candidates for the set of options.

Which languages does pyspellchecker support?

The bundled dictionaries cover English en, Spanish es, French fr, Portuguese pt, German de, Italian it, Russian ru, Arabic ar, Basque eu, Latvian lv, Dutch nl and Persian fa. English is the default when you construct SpellChecker with no argument.

How do I stop pyspellchecker from flagging my product names?

Use spell.word_frequency.load_words with the terms you want recognised, or spell.word_frequency.load_text_file to build a frequency list from your own text. The documentation shows that words added this way are then returned by spell.known.

When should I change the edit distance in pyspellchecker?

The default distance is two, and the documentation recommends a distance of one for longer words because a wide candidate set makes the frequency ranking pick the wrong word. You can set it at construction with SpellChecker(distance=1) or change it later with spell.distance.

Where do the pyspellchecker dictionaries come from?

They are generated by a script from OpenSubtitles text using scripts/build_dictionary.py, with the original frequency list and each language's include and exclude files under scripts/data/. The documentation describes the cleanup the script performs and invites pull requests against those include and exclude files.

Official sources

  1. barrust/pyspellchecker on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/barrust-pyspellchecker.svg)](https://hysenlabs.com/projects/barrust-pyspellchecker)