fuse.js vs fuzzy vs fuzzy-search vs fuzzyset
Client-Side Fuzzy Search Libraries for JavaScript Applications
fuse.jsfuzzyfuzzy-searchfuzzysetSimilar Packages:

Client-Side Fuzzy Search Libraries for JavaScript Applications

fuse.js, fuzzy, fuzzy-search, and fuzzyset are JavaScript libraries designed to implement fuzzy string matching in browser or Node.js environments. They help developers build search features that tolerate typos, partial matches, and varied input formats by calculating similarity between query strings and a dataset. Each library uses different algorithms and data structures under the hood, leading to trade-offs in performance, memory usage, configurability, and ease of integration.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
fuse.js020,234312 kB3a month agoApache-2.0
fuzzy0837-2910 years ago-
fuzzy-search0231-166 years agoISC
fuzzyset01,37635.6 kB14 years agosee LICENSE.md

Fuzzy Search in JavaScript: Fuse.js vs fuzzy vs fuzzy-search vs fuzzyset

When building UIs with search—like type-ahead inputs, filtering dashboards, or command menus—you often can’t rely on exact string matches. Users make typos, abbreviate terms, or expect results from partial input. That’s where fuzzy search libraries come in. But not all are created equal. Let’s break down how fuse.js, fuzzy, fuzzy-search, and fuzzyset differ in real-world usage.

🔍 Core Matching Behavior: How They Find "Close" Matches

fuse.js uses the Bitap algorithm (a variation of the Levenshtein distance approach) with enhancements for speed and relevance. It scores matches based on character proximity, sequence order, and location within the string. You get ranked results with match positions highlighted.

// fuse.js example
const fuse = new Fuse(['apple', 'banana', 'cherry'], {
  includeScore: true,
  threshold: 0.3 // lower = stricter
});

console.log(fuse.search('bana')); 
// → [{ item: 'banana', score: 0.125 }]

fuzzy implements a simpler pattern-matching heuristic: it checks if characters from the query appear in order in the target string, assigning a score based on gaps and case sensitivity. No edit distance—just subsequence alignment.

// fuzzy example
import { filter } from 'fuzzy';

const results = filter('bna', ['apple', 'banana', 'cherry']);
console.log(results[0].string); // 'banana'

fuzzy-search also uses a subsequence-based approach, similar to fuzzy, but adds basic support for searching within object properties. It doesn’t compute detailed scores—just returns matches above a hardcoded similarity bar.

// fuzzy-search example
const searcher = new FuzzySearch(['apple', 'banana'], null, {
  caseSensitive: false
});

console.log(searcher.search('bana')); // ['banana']

fuzzyset takes a different path: it precomputes similarity hashes using n-grams and stores them in a lookup structure. At query time, it finds candidates with overlapping n-grams and falls back to exact matches if nothing is close enough. This works well for static dictionaries but struggles with dynamic data.

// fuzzyset example
const fz = new FuzzySet();
fz.add('banana');

console.log(fz.get('bana')); // [[0.8, 'banana']]

🧱 Data Structure Support: Strings vs Objects vs Nested Fields

Only fuse.js handles nested objects gracefully out of the box:

const books = [
  { title: 'The Great Gatsby', author: { name: 'F. Scott Fitzgerald' } }
];

const fuse = new Fuse(books, { keys: ['title', 'author.name'] });
fuse.search('fitzgerald'); // matches author.name

fuzzy-search supports flat objects via a keys option, but not nesting:

// fuzzy-search with flat objects
const users = [{ name: 'Alice', email: 'alice@example.com' }];
const searcher = new FuzzySearch(users, ['name', 'email']);

fuzzy and fuzzyset work only with strings. To search objects, you must extract or stringify values yourself.

⚙️ Configuration & Control: Tuning Relevance

fuse.js gives you deep control:

  • threshold: how “fuzzy” to allow (0 = exact, 1 = anything)
  • distance: how far apart matching characters can be
  • keys: which fields to search, with optional weights
  • includeMatches: get character-level match positions

This makes it possible to fine-tune for domain-specific needs (e.g., prioritize SKU codes over product names).

fuzzy and fuzzy-search offer minimal knobs—mostly just case sensitivity. You can’t adjust match strictness or field importance.

fuzzyset has almost no runtime configuration. Once built, the index is fixed.

🔄 Dynamic Data Handling: Adding or Updating Items

fuse.js supports .add(), .remove(), and .setCollection() for live updates—critical for apps where data changes after initial load (e.g., chat message filters).

fuzzy and fuzzy-search require rebuilding the entire matcher when data changes, which is fine for small sets but costly at scale.

fuzzyset allows .add() but not removal or updates. If your dataset mutates, you’ll need to recreate the whole structure.

🌐 Internationalization & Edge Cases

fuse.js handles Unicode reasonably well and supports accent folding via plugins. It’s tested across languages.

fuzzy and fuzzy-search work with Unicode strings but don’t normalize accents or diacritics—so “café” won’t match “cafe” without preprocessing.

fuzzyset has known issues with non-ASCII characters and may produce inconsistent results with emojis or CJK text.

🛑 Maintenance & Modern JS Ecosystem Fit

fuse.js is actively maintained, ships with TypeScript definitions, supports ES modules, and works seamlessly in bundlers like Vite or Webpack.

fuzzy is stable but rarely updated. It’s tiny (~2KB) and dependency-free—good for constrained environments.

fuzzy-search hasn’t had significant updates since 2019. It works but lacks modern tooling support.

fuzzyset is effectively deprecated. The last meaningful commit was in 2016, and it fails in strict CSP environments due to eval() usage. Do not use it in new projects.

✅ When to Use Which?

ScenarioRecommended Library
Complex object search with weightingfuse.js
Simple command palette (<50 items)fuzzy
Flat object filtering, moderate sizefuzzy-search
Static dictionary with precomputed lookups❌ Avoid fuzzyset; use fuse.js instead

💡 Final Recommendation

For most professional frontend applications, fuse.js is the clear choice. It balances power, flexibility, and reliability without bloating your bundle. Reserve fuzzy for micro-interactions where every byte counts. Treat fuzzy-search as a legacy option if already in use—but migrate to Fuse.js for new work. And leave fuzzyset in the past; its design doesn’t hold up in modern web apps.

How to Choose: fuse.js vs fuzzy vs fuzzy-search vs fuzzyset

  • fuse.js:

    Choose fuse.js when you need a well-maintained, flexible, and feature-rich fuzzy search solution with strong defaults and fine-grained control over matching behavior. It supports nested object searching, weighted fields, and custom scoring, making it ideal for complex datasets like product catalogs or user directories. Its active maintenance and comprehensive documentation reduce long-term risk in production applications.

  • fuzzy:

    Choose fuzzy if you're working on a lightweight project where simplicity and minimal bundle size matter more than advanced features. It provides basic fuzzy matching using a simple pattern-scoring algorithm and is best suited for small lists (e.g., command palettes or autocomplete with fewer than 100 items). However, it lacks support for objects, weights, or threshold tuning, limiting its use in data-rich contexts.

  • fuzzy-search:

    Choose fuzzy-search when you need straightforward fuzzy matching over arrays of strings or flat objects without complex configuration. It’s easy to integrate and performs adequately for medium-sized datasets, but offers fewer customization options than Fuse.js. Avoid it if you require nested property traversal, relevance scoring, or dynamic reindexing.

  • fuzzyset:

    Choose fuzzyset only for very specific use cases involving precomputed similarity lookups with exact match fallbacks. It builds an internal trie-like structure optimized for repeated queries against a static dataset. However, it hasn’t seen meaningful updates in years, lacks modern TypeScript support, and has known limitations with Unicode and non-English text. Do not use it in new projects unless you’ve validated its behavior against your exact data shape.

README for fuse.js

Fuse.js

Node.js CI Version Downloads code style: prettier Contributors License

Fuse.js is a lightweight, zero-dependency fuzzy-search library written in TypeScript. It works in the browser and on the server, and is designed for searching small-to-medium datasets on the client side where you can't rely on a dedicated search backend.

✨ What's New: Token Search

Multi-word fuzzy search with relevance ranking. Type "javascrpt paterns" and find "JavaScript Patterns" — typo tolerance, multiple words, and smart ranking all at once.

const fuse = new Fuse(docs, {
  useTokenSearch: true,
  keys: ['title', 'author', 'description']
})

fuse.search('javascrpt paterns')
// → [{ item: { title: 'JavaScript Patterns', ... } }]

See Token Search below for details.

Installation

npm install fuse.js
yarn add fuse.js

Or include directly via CDN:

<script src="https://cdn.jsdelivr.net/npm/fuse.js/dist/fuse.min.mjs"></script>

Quick Start

import Fuse from 'fuse.js'

const books = [
  { title: "Old Man's War", author: 'John Scalzi' },
  { title: 'The Lock Artist', author: 'Steve Hamilton' },
  { title: 'HTML5', author: 'Remy Sharp' },
  { title: 'JavaScript: The Good Parts', author: 'Douglas Crockford' }
]

const fuse = new Fuse(books, {
  keys: ['title', 'author']
})

fuse.search('javscript')
// → [{ item: { title: 'JavaScript: The Good Parts', ... }, ... }]

Features

Fuzzy Search

The core of Fuse.js. Uses the Bitap algorithm for approximate string matching — handles typos, misspellings, and partial matches out of the box.

fuse.search('javscript')
// → [{ item: { title: 'JavaScript: The Good Parts', author: 'Douglas Crockford' } }]

Weighted Keys

Search across multiple fields with different importance levels. Title matches can rank higher than description matches.

const fuse = new Fuse(docs, {
  keys: [
    { name: 'title', weight: 2 },
    { name: 'description', weight: 1 }
  ]
})

Extended Search

Use operators for precise control: exact match (=), prefix (^), suffix (!), and more. Enable with useExtendedSearch: true.

const fuse = new Fuse(list, {
  useExtendedSearch: true,
  keys: ['title']
})

fuse.search('=exact match')   // exact match
fuse.search('^prefix')        // starts with
fuse.search('!term')          // does not include

Token Search

Splits multi-word queries into individual terms, fuzzy-matches each independently, and ranks results using BM25-style IDF weighting. Enable with useTokenSearch: true.

const fuse = new Fuse(docs, {
  useTokenSearch: true,
  keys: ['title', 'body']
})

fuse.search('express midleware rout')
// Finds "Express Middleware" and "Express Routing Guide" despite typos
  • Typo tolerance per word — each term is fuzzy-matched independently
  • Relevance ranking — rare terms are weighted higher than common ones
  • Word order independent"patterns javascript" and "javascript patterns" return identical results
  • No query length limit — long multi-word queries work naturally since each term is searched separately

Available in the full build. See TOKEN_SEARCH.md for details and performance benchmarks.

Logical Search

Combine conditions with $and and $or for complex queries. Available in the full build.

fuse.search({
  $and: [
    { title: 'javascript' },
    { author: 'crockford' }
  ]
})

Match Highlighting

Get character-level match indices for highlighting search results in your UI.

const fuse = new Fuse(list, {
  includeMatches: true,
  keys: ['title']
})

const result = fuse.search('javscript')
// result[0].matches[0].indices → [[0, 9]]

Single String Matching

Use Fuse.match() to fuzzy-match a pattern against a single string without creating an index. Useful for one-off comparisons or custom filtering.

const result = Fuse.match('javscript', 'JavaScript: The Good Parts')
// → { isMatch: true, score: 0.04, indices: [[0, 9]] }

Dynamic Collections

Add and remove documents from a live index without rebuilding.

fuse.add({ title: 'New Book', author: 'New Author' })
fuse.remove((doc) => doc.title === 'Old Book')

Builds

Fuse.js ships in two variants:

BuildIncludesMin + gzip
FullFuzzy + Extended + Logical + Token search~8 kB
BasicFuzzy search only~6.5 kB

Use the basic build if you only need fuzzy search and want the smallest bundle size.

Documentation

For the full API reference, configuration options, scoring theory, and interactive demos, visit fusejs.io.

Supporting Fuse.js

Develop

See DEVELOPERS.md for setup, scripts, and project structure.

Contribute

See CONTRIBUTING.md for guidelines on issues and pull requests.