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

Client-Side Fuzzy Search Libraries for JavaScript

fuse.js, fuzzy-search, and fuzzyset are JavaScript libraries designed to perform approximate string matching directly in the browser. They allow users to find relevant results even when typos occur or when the search term does not exactly match the data. fuse.js is a lightweight fuzzy-search module that supports weighted searching across object properties. fuzzy-search provides a simple interface for filtering arrays of objects based on multiple keys. fuzzyset focuses on creating a set of strings for fast lookup and scoring, often used for deduplication or simple matching tasks.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
fuse.js020,410417 kB09 days agoApache-2.0
fuzzy-search0229-166 years agoISC
fuzzyset01,37635.6 kB15 years agosee LICENSE.md

Client-Side Fuzzy Search: fuse.js vs fuzzy-search vs fuzzyset

When building search features in web applications, exact matching often frustrates users. A single typo can yield zero results. Fuzzy search libraries solve this by finding matches based on similarity rather than exact equality. fuse.js, fuzzy-search, and fuzzyset are three popular choices, but they differ significantly in algorithm, data handling, and flexibility. Let's examine how they perform in real engineering scenarios.

🔍 Algorithm and Accuracy

The core difference lies in how each library calculates similarity. This affects both performance and result relevance.

fuse.js uses the Bitap algorithm. It supports location-based scoring, meaning matches closer to the start of the text rank higher. It also allows threshold tuning to filter out weak matches.

// fuse.js: Configurable threshold and location bias
import Fuse from 'fuse.js';

const fuse = new Fuse(items, {
  keys: ['title', 'author'],
  threshold: 0.3,
  location: 0
});

const results = fuse.search('harry potter');
// Returns items with score and match details

fuzzy-search uses a simpler fuzzy matching approach optimized for speed on lists. It ranks results but offers less control over the scoring algorithm itself.

// fuzzy-search: Simple key-based matching
import FuzzySearch from 'fuzzy-search';

const searcher = new FuzzySearch(items, ['title', 'author'], {
  caseSensitive: false
});

const results = searcher.search('harry potter');
// Returns filtered array of items directly

fuzzyset relies on Levenshtein distance for string sets. It is designed for matching against a set of unique strings rather than weighted object properties.

// fuzzyset: String set matching
import fuzzyset from 'fuzzyset';

const set = fuzzyset(['harry potter', 'harry porter', 'lord of the rings']);

const results = set.get('harry potter');
// Returns array of [score, string] tuples

🗂️ Data Structure Support

Your data shape dictates which library fits best. Some handle objects natively, while others expect plain strings.

fuse.js excels with nested objects. You can search deep properties without flattening your data first. It returns the original item along with match metadata.

// fuse.js: Nested object support
const fuse = new Fuse(users, {
  keys: ['profile.name', 'profile.bio']
});

const results = fuse.search('developer');
// results[0].item contains the full user object

fuzzy-search works with arrays of objects but expects flat keys. It returns the matching items directly, which simplifies rendering but hides scoring data.

// fuzzy-search: Flat key support
const searcher = new FuzzySearch(users, ['name', 'bio']);

const results = searcher.search('developer');
// results is an array of user objects

fuzzyset is built for arrays of strings. If you have objects, you must extract the searchable text manually before indexing.

// fuzzyset: String array only
const titles = users.map(u => u.name);
const set = fuzzyset(titles);

const results = set.get('dev');
// results contains [score, name] tuples, not full objects

⚙️ Configuration and Control

Complex applications often require fine-tuning to balance performance and relevance. The level of control varies widely.

fuse.js offers extensive options. You can weight keys, ignore tokens, and adjust distance limits. This is crucial for large datasets where noise is a problem.

// fuse.js: Advanced weighting
const fuse = new Fuse(items, {
  keys: [
    { name: 'title', weight: 0.8 },
    { name: 'tags', weight: 0.2 }
  ],
  ignoreLocation: true,
  minMatchCharLength: 2
});

fuzzy-search keeps configuration minimal. You can toggle case sensitivity and sort results, but deep tuning is not available. This reduces setup time but limits optimization.

// fuzzy-search: Basic options
const searcher = new FuzzySearch(items, ['name'], {
  caseSensitive: false,
  sort: true
});

fuzzyset has very few options. It focuses on speed and simplicity for string sets. You can adjust the default exact match threshold, but little else.

// fuzzyset: Minimal config
const set = fuzzyset(null, true); // useLevenshtein = true

set.add('example string');

📦 Return Values and Integration

How the results are returned affects how you write your UI logic. Some return scores, others return items.

fuse.js returns an array of result objects containing the item, score, and match indices. This allows you to highlight matched text or sort by relevance manually.

// fuse.js: Rich result object
const results = fuse.search('query');

results.forEach(result => {
  console.log(result.item); // The data
  console.log(result.score); // The relevance
});

fuzzy-search returns the filtered array of items directly. This is convenient for simple lists but makes highlighting or custom sorting harder.

// fuzzy-search: Direct items
const results = searcher.search('query');

results.forEach(item => {
  console.log(item); // The data only
});

fuzzyset returns tuples of score and string. You must map these back to your original data if you stored only strings in the set.

// fuzzyset: Score tuples
const results = set.get('query');

results.forEach(([score, string]) => {
  console.log(string); // The matched string
  console.log(score); // The relevance
});

🛠️ Maintenance and Ecosystem

Long-term projects require libraries that are kept up to date with modern JavaScript standards.

fuse.js is actively maintained with regular updates. It supports ES modules, TypeScript definitions, and server-side rendering environments. It is the safest choice for new projects.

// fuse.js: Modern import
import Fuse from 'fuse.js';
// Fully typed with TypeScript

fuzzy-search is stable but sees fewer updates. It works well for standard use cases but may lack features for edge cases. It is suitable for internal tools or simple interfaces.

// fuzzy-search: Standard import
import FuzzySearch from 'fuzzy-search';
// CommonJS and ES module support available

fuzzyset has seen less activity in recent years. While functional, it may not align with modern build tools without extra configuration. Use with caution in large-scale applications.

// fuzzyset: Legacy-style import
import fuzzyset from 'fuzzyset';
// Check for modern module compatibility

📊 Summary: Key Differences

Featurefuse.jsfuzzy-searchfuzzyset
AlgorithmBitap with scoringSimple fuzzy matchLevenshtein distance
Data InputObjects or StringsObjectsStrings only
OutputItem + Score + IndicesItems onlyScore + String tuples
ConfigurationExtensiveMinimalVery Limited
Best UseComplex search UISimple filteringString deduplication

💡 Final Recommendation

fuse.js is the robust choice for most professional applications. It handles objects natively, provides detailed match data for UI enhancements, and offers the control needed for tuning relevance. Use it for customer-facing search bars, documentation sites, or large datasets.

fuzzy-search is ideal for quick implementations where speed of development matters more than fine-tuning. It works well for admin panels, internal dashboards, or small lists where default behavior is acceptable.

fuzzyset serves a niche role for string sets and deduplication tasks. Unless you have a specific need for its string-set architecture, prefer fuse.js for general searching needs to ensure long-term maintainability.

Final Thought: All three libraries solve the typo problem, but fuse.js provides the engineering depth required for scalable, user-friendly search experiences.

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

  • fuse.js:

    Choose fuse.js if you need advanced configuration options like weighting specific fields, setting threshold scores, or handling complex nested objects. It is the industry standard for production-grade fuzzy search where accuracy and flexibility matter most. This library is actively maintained and supports modern JavaScript environments without heavy dependencies.

  • fuzzy-search:

    Choose fuzzy-search if you want a straightforward solution for filtering lists of objects with minimal setup. It works well for simple UI components like dropdowns or command palettes where deep customization is not required. The API is concise, making it easy to integrate quickly without learning complex configuration options.

  • fuzzyset:

    Choose fuzzyset if you are working primarily with flat arrays of strings rather than complex objects. It is suitable for tasks like deduplication or checking membership with approximate matching. However, evaluate its maintenance status carefully as it offers fewer features for object-based searching compared to modern alternatives.

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.

Web Workers

Search large datasets without freezing the UI. FuseWorker splits your data across multiple Web Workers and searches in parallel — ~5x faster on 100K documents.

import { FuseWorker } from 'fuse.js/worker'

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

const results = await fuse.search('query')
fuse.terminate()

Same options and results as Fuse — just async. Function-valued options (sortFn, getFn, keys[].getFn) aren't supported because functions can't be transferred to a worker; everything else carries over. See the Web Workers docs for the interactive demo and full API.

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
  • AND or ORtokenMatch: 'all' returns only records matching every word (filtering); the default 'any' matches any word
  • Custom tokenizer — pass a regex or function via tokenize for tokens with internal punctuation (node.js, c++), or use Intl.Segmenter for CJK / Thai word segmentation. Unicode-aware by default

Available in the full build. See the Token Search docs 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]] }

Fuse.match() does not support useTokenSearch — token search requires corpus-level statistics (df, fieldCount) that a one-off string comparison can't provide. Passing useTokenSearch: true throws an explicit error. Use new Fuse(docs, { useTokenSearch: true }).search(query) for token-search behavior.

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.6 kB
BasicFuzzy search only~6.8 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.

Official ports

  • fuse-swift: Swift port for iOS, macOS, tvOS, watchOS, visionOS, and Linux. Byte-equivalent results, idiomatic Swift API, syncs with each upstream release. Currently in 2.0.0-rc.1.

Supporting Fuse.js

Develop

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

Contribute

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