levenshtein-edit-distance, natural, and string-similarity are JavaScript libraries used to measure how similar two strings are, but they serve different architectural needs. levenshtein-edit-distance is a lightweight, focused utility that calculates the exact number of edits required to transform one string into another. natural is a comprehensive natural language processing (NLP) toolkit that includes string distance algorithms alongside features like tokenization and stemming. string-similarity provides a similarity score based on bigram matching rather than edit distance, often used for fuzzy matching suggestions. Choosing between them depends on whether you need a specific algorithm, a full NLP suite, or a quick similarity ratio.
When building features like search autocomplete, spell correction, or data deduplication, you need to measure how close two strings are. levenshtein-edit-distance, natural, and string-similarity all solve this problem, but they use different math and fit different project sizes. Let's look at how they work under the hood.
The most important difference is the math they use. Two packages use Levenshtein distance, while one uses Dice Coefficient.
levenshtein-edit-distance calculates the minimum number of single-character edits (insertions, deletions, or substitutions) required to change one word into the other.
import levenshteinEditDistance from 'levenshtein-edit-distance';
// Returns 2 (k->c, t->g)
const distance = levenshteinEditDistance('cat', 'dog');
natural also supports Levenshtein distance but wraps it inside a larger NLP library. It returns the same integer count.
const natural = require('natural');
// Returns 2
const distance = natural.LevenshteinDistance('cat', 'dog');
string-similarity uses the Dice Coefficient. It compares bigrams (pairs of characters) instead of counting edits. It returns a number between 0 and 1, where 1 is an exact match.
const stringSimilarity = require('string-similarity');
// Returns a ratio like 0.57
const similarity = stringSimilarity.compareTwoStrings('cat', 'dog');
💡 Tip: If you need to know "how many keystrokes to fix this," use Levenshtein. If you need "how related are these words," Dice Coefficient often feels more intuitive for search.
Frontend architecture often cares about bundle size. Adding a heavy library for a single function is usually wasteful.
levenshtein-edit-distance is a standalone module. It has no dependencies and exports a single function. It is the safest choice for minimizing bundle impact.
// Import is tree-shakable and minimal
import levenshteinEditDistance from 'levenshtein-edit-distance';
natural is a heavy dependency. It includes stemmers, spell checkers, and classifiers. If you only need distance, you are importing a lot of unused code.
// Imports the entire NLP toolkit
const natural = require('natural');
string-similarity is lightweight like levenshtein-edit-distance, but it solves a slightly different problem (ratio vs. count).
// Lightweight import
const stringSimilarity = require('string-similarity');
All three packages are easy to use, but their output types differ. This affects how you write your logic.
levenshtein-edit-distance returns an integer. You must decide your own threshold for "similar."
const distance = levenshteinEditDistance('apple', 'aple');
const isSimilar = distance <= 1; // true
natural returns an integer, same as above. It also offers an option to return the actual edit steps, which is useful for diff tools.
// Get detailed edit steps
const steps = natural.LevenshteinDistance('apple', 'aple', { steps: true });
string-similarity returns a float. This is often easier for ranking results (e.g., sorting search suggestions).
const score = stringSimilarity.compareTwoStrings('apple', 'aple');
// Sort by score descending
Sometimes you don't just compare two strings. You have one input and a list of candidates.
levenshtein-edit-distance does not have a built-in "find best match" helper. You must map and reduce manually.
const candidates = ['apple', 'banana', 'apricot'];
const input = 'aple';
const best = candidates.reduce((prev, curr) => {
const prevDist = levenshteinEditDistance(prev, input);
const currDist = levenshteinEditDistance(curr, input);
return currDist < prevDist ? curr : prev;
});
natural also requires manual iteration for basic distance, but it includes a SpellCheck class that handles this logic for you internally.
const spellcheck = new natural.SpellCheck(['apple', 'banana'], levenshteinEditDistance);
const corrections = spellcheck.getCorrections('aple', 1);
string-similarity has a dedicated helper for this exact scenario. It returns ranked matches automatically.
const matches = stringSimilarity.findBestMatch('aple', ['apple', 'banana', 'apricot']);
// Returns { bestMatch: ..., ratings: [...] }
Long-term projects need stable libraries. Check the maintenance history before committing.
levenshtein-edit-distance is part of the unified ecosystem (maintained by wooorm). It is highly stable, well-tested, and follows strict quality standards.
// Reliable for production use
import levenshteinEditDistance from 'levenshtein-edit-distance';
natural is actively maintained with regular updates. It is a standard choice for Node.js NLP tasks.
// Active community and updates
const natural = require('natural');
string-similarity has seen limited updates in recent years. While it works, teams should evaluate if a more actively maintained fork like string-similarity-js is safer for new projects.
// Verify maintenance status before use
const stringSimilarity = require('string-similarity');
| Feature | levenshtein-edit-distance | natural | string-similarity |
|---|---|---|---|
| Algorithm | Levenshtein (Edit Count) | Levenshtein (Edit Count) | Dice Coefficient (Ratio) |
| Output | Integer (0, 1, 2...) | Integer (0, 1, 2...) | Float (0.0 to 1.0) |
| Bundle Size | Tiny | Large | Tiny |
| Best Match Helper | ❌ Manual | ✅ (via SpellCheck) | ✅ (Built-in) |
| Maintenance | ✅ Active | ✅ Active | ⚠️ Legacy |
levenshtein-edit-distance is the precision tool 🔧. Use it when you need exact edit counts, care about bundle size, and want a stable, focused dependency.
natural is the Swiss Army Knife 🇨🇭. Use it when you are already building an NLP pipeline and need distance metrics alongside tokenization or stemming.
string-similarity is the quick fix 🩹. Use it for search suggestions where a similarity score is better than an edit count, but consider newer forks for long-term support.
Final Thought: All three solve string comparison, but they speak different languages. Match the algorithm to your user experience — edit counts for corrections, similarity ratios for search.
Choose levenshtein-edit-distance when you need a precise, lightweight implementation of the Levenshtein algorithm without extra dependencies. It is ideal for performance-critical frontend tasks like spell-checking or diffing where bundle size matters and you only need the edit count.
Choose natural if your project already requires broader NLP capabilities like tokenization, stemming, or classification. It is suitable for complex applications where string distance is just one part of a larger text processing pipeline, despite the larger bundle size.
Choose string-similarity for quick fuzzy matching tasks like search suggestions where a similarity ratio (0 to 1) is more useful than an edit count. However, verify its maintenance status for long-term projects, as it is less actively updated than the others.
Levenshtein distance (by Vladimir Levenshtein).
This package exposes a string similarity algorithm. That means it gets two strings (typically words), and turns it into the minimum number of single-character edits (insertions, deletions or substitutions) needed to turn one string into the other.
You’re probably dealing with natural language, and know you need this, if you’re here!
This package is ESM only. In Node.js (version 14.14+, 16.0+), install with npm:
npm install levenshtein-edit-distance
In Deno with esm.sh:
import {levenshteinEditDistance} from 'https://esm.sh/levenshtein-edit-distance@3'
In browsers with esm.sh:
<script type="module">
import {levenshteinEditDistance} from 'https://esm.sh/levenshtein-edit-distance@3?bundle'
</script>
import {levenshteinEditDistance} from 'levenshtein-edit-distance'
levenshteinEditDistance('levenshtein', 'levenshtein') // => 0
levenshteinEditDistance('sitting', 'kitten') // => 3
levenshteinEditDistance('gumbo', 'gambol') // => 2
levenshteinEditDistance('saturday', 'sunday') // => 3
// Insensitive to order:
levenshteinEditDistance('aarrgh', 'aargh') === levenshtein('aargh', 'aarrgh') // => true
// Sensitive to ASCII casing by default:
levenshteinEditDistance('DwAyNE', 'DUANE') !== levenshtein('dwayne', 'DuAnE') // => true
// Insensitive:
levenshteinEditDistance('DwAyNE', 'DUANE', true) === levenshtein('dwayne', 'DuAnE', true) // => true
This package exports the identifier levenshteinEditDistance.
There is no default export.
levenshteinEditDistance(value, other[, insensitive])Levenshtein edit distance.
valuePrimary value (string, required).
otherOther value (string, required).
insensitiveCompare insensitive to ASCII casing (boolean, default: false).
Distance between value and other (number).
Usage: levenshtein-edit-distance [options] word word
Levenshtein edit distance.
Options:
-h, --help output usage information
-v, --version output version number
-i, --insensitive ignore casing
Usage:
# output distance
$ levenshtein-edit-distance sitting kitten
# 3
# output distance from stdin
$ echo "saturday,sunday" | levenshtein-edit-distance
# 3
This package is fully typed with TypeScript. It exports no additional types.
This package is at least compatible with all maintained versions of Node.js. As of now, that is Node.js 14.14+ and 16.0+. It also works in Deno and modern browsers.
levenshtein.c
— C APIlevenshtein
— C CLIlevenshtein-rs
— Rust APIstemmer
— porter stemming algorithmlancaster-stemmer
— lancaster stemming algorithmdouble-metaphone
— double metaphone algorithmsoundex-code
— soundex algorithmdice-coefficient
— sørensen–dice coefficientsyllable
— syllable count of English wordsYes please! See How to Contribute to Open Source.
This package is safe.