Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 

Repository files navigation

Awesome Fast Fuzzy Search on the Web

A curated list of the absolute fastest fuzzy search libraries for JavaScript in the browser. Whether you need an ultra-lightweight filter, SublimeText-like search as you type, or WebAssembly-powered speed for massive datasets, this list covers the best options available.

Quick Comparison

Library Bundle Size Approach Best For Stars
uFuzzy ~3KB Multi-phase filtering Maximum speed, autocomplete 3k
fuzzysort ~7KB SublimeText scoring Search-as-you-type 28M+ downloads
FlexSearch ~10KB Contextual index Large full-text search 13.8k
MiniSearch ~12KB Inverted index Full-text with features 6k
FZF for JS ~8KB fzf algorithm Command palettes 2M+ weekly
Fuse.js ~25KB Bitap + index Battle-tested fuzzy 28k+ stars
fast-fuzzy ~5KB Sellers + Damerau-Levenshtein Fast Levenshtein matching 1.3M+ downloads
Orama ~2KB BM25 + vector Hybrid search (keyword + semantic) Active
microfuzzy ~2KB Simple filter Tiny bundle, simple lists 1.4M+ downloads
Lunr.js ~8KB Solr-like inverted index Static site docs Classic
FlashFuzzy WASM Bitap + Bloom filter 100K+ records New
nucleo-matcher-wasm WASM Smith-Waterman Editor-quality matching Helix-backed
rapid-fuzzy WASM Rust-powered 15,000x faster than Fuse New
USearch WASM SIMD-optimized Vector + text search 4.2k

Pure JavaScript (Client-Side)

These libraries are written in JavaScript/TypeScript and are optimized for fast client-side searching.

  • Focus: Maximum speed and efficiency with high-quality matching.
  • Why it's awesome: Often cited as the fastest JS fuzzy matcher. It employs a multi-phase strategy (filtering, scoring, sorting) to handle large datasets instantly. It is tiny and extremely performant.
  • Best for: Scenarios where performance is the absolute highest priority and you want precise, fast filtering.
  • Focus: Speed and "SublimeText-like" fuzzy search.
  • Why it's awesome: Extremely fast and heavily optimized for the specific use case of search-as-you-type filtering (like command palettes or dropdowns). Single-purpose, zero-config.
  • Best for: Narrow, list-based filtering where users expect instantaneous feedback as they type.
  • Focus: Maximum raw throughput for full-text search.
  • Why it's awesome: Benchmarks show it performing queries up to 1,000,000x faster than competing libraries. Uses a "contextual index" scoring algorithm based on a pre-scored lexical dictionary. Supports Web Workers, persistent indexes (IndexedDB, Redis, SQLite, Postgres), and multi-language (CJK, Arabic, Cyrillic).
  • Best for: Large-document full-text search where raw query speed is the top priority.
  • Focus: Feature-rich, in-memory full-text search.
  • Why it's awesome: While slightly heavier than uFuzzy, it offers a great balance of speed and professional search features (like field boosting, exact match vs. fuzzy match, and prefix matching).
  • Best for: Documentation, static sites, or complex client-side search requirements.
  • Focus: Port of the legendary CLI fzf algorithm to the browser.
  • Why it's awesome: Brings the exact same scoring and ranking system from the command-line fzf into JavaScript. Supports case sensitivity, tiebreakers, async finder, and backward matching. 2M+ weekly downloads on npm.
  • Best for: Command palettes, file finders, and any UI that needs fzf-quality matching.
  • Focus: Feature-complete, robust industry standard.
  • Why it's awesome: While not always the top in raw speed benchmarks for massive datasets, it supports Web Workers (FuseWorker), allowing you to offload the search to a background thread to prevent UI freezing. Latest v7.x adds token search, extended search, and logical queries.
  • Best for: Applications requiring a battle-tested library with complex configuration and good performance.
  • Focus: Fast Damerau-Levenshtein distance with Sellers substring matching.
  • Why it's awesome: Uses a modified Levenshtein algorithm (Peter Sellers' method) with Damerau-Levenshtein by default (transposition-friendly). Internally builds a Trie with subtree pruning — skips entire branches that can't possibly score above threshold. Scores 0-1 with excellent normalization (unicode, symbols, whitespace, graphemes).
  • Best for: When you need Levenshtein-style edit distance with substring matching and good Unicode support. 1.3M+ weekly downloads.
  • Focus: Full-text, vector, and hybrid search in one tiny library (<2KB).
  • Why it's awesome: Zero-dependency TypeScript search engine with typo tolerance, BM25 ranking, facets, filters, geosearch, and an Answer Engine (RAG) API. Runs in browser, server, or edge. Actively maintained by a dedicated team.
  • Best for: Modern web apps that need both keyword and semantic/vector search without external infrastructure.
  • Focus: Tiny bundle size (2KB gzipped) and simplicity.
  • Why it's awesome: When you don't need the complexity of Levenshtein distances and just want a simple, blazing-fast array filter, microfuzz does the job without bloating your bundle.
  • Best for: Simple UI components where bundle size matters as much as speed.
  • Focus: Server-like full-text search on the client.
  • Why it's awesome: A classic in the space — inspired by Solr, but running entirely in the browser. Supports field-scoped search, boosting, and pre-built indexes. Well-documented with a mature API.
  • Best for: Static site documentation search and traditional full-text use cases.
  • Focus: Improved SublimeText-like fuzzy search, fork of fuzzysort.
  • Why it's awesome: An actively maintained fork of fuzzysort with bug fixes, improved scoring, and better TypeScript support. Drop-in replacement if fuzzysort's last update (2 years ago) concerns you.
  • Best for: Projects that want fuzzysort's approach with more recent maintenance.
  • Focus: Fast, accurate, and multilingual fuzzy search.
  • Why it's awesome: Built specifically for multilingual accuracy — handles accented characters, CJK, and complex Unicode properly. Uses a custom scoring algorithm optimized for real-world text.
  • Best for: International applications where multilingual accuracy matters.
  • Focus: Search, sort, and filter for existing HTML lists/tables.
  • Why it's awesome: Drop-in library that adds fuzzy search to existing HTML elements without rewriting your markup. 11.2k stars. Handles pagination, sorting, and filtering together.
  • Best for: Adding search to existing tables, lists, or directories without a framework rewrite.
  • Focus: Lightweight fuzzy search from the LVCE (formerly Tabby) editor project.
  • Why it's awesome: Minimal, dependency-free fuzzy search implementation from a real editor project. Actively maintained with recent updates.
  • Best for: Editor-like UIs and minimal dependency requirements.

System-Level & WebAssembly (WASM)

For datasets that are simply too large for JavaScript's V8 engine to iterate over quickly, we can bring system-level languages into the browser via WebAssembly.

1. FlashFuzzy (Rust + WASM)

  • Why it's awesome: Built in Rust and compiled to WASM. Combines Bloom Filters with the Bitap algorithm to achieve sub-millisecond searches on datasets of 100K+ records. Zero-allocation memory architecture — no GC pauses.
  • Status: Available on npm as flashfuzzy. Live demo available.

2. nucleo-matcher-wasm (Rust + WASM)

  • Why it's awesome: Compiles nucleo-matcher (the same fuzzy matcher used in the Helix editor) to WebAssembly. Claims ~6x faster than skim's matcher with more faithful Smith-Waterman scoring. Supports fzf-like syntax (^prefix, $postfix, 'substring, !negation).
  • Status: Available on npm as nucleo-matcher-wasm. Ready for browser use.

3. Fuzzr (Rust + WASM)

  • Why it's awesome: Written in Rust, compiled to WASM, using the popular skim algorithm. Designed specifically for browser use from the ground up.
  • Status: Open source on GitHub. Good starting point for Rust->WASM fuzzy search.

4. docfind (Rust + WASM)

  • Why it's awesome: A Microsoft-built document search engine combining FST (Finite State Transducers) with FSST compression and RAKE keyword extraction. Sub-millisecond search on 50K+ documents. Index can be embedded directly in the WASM binary for zero network requests. Powers the VS Code documentation site search.
  • Status: Production use on code.visualstudio.com. Open source with an interactive live demo.

5. @stll/fuzzy-search-wasm (Rust + WASM)

  • Why it's awesome: Approximate substring matching for browsers via WebAssembly. Provides Levenshtein edit distance with same API as @stll/fuzzy-search. Built with napi-rs.
  • Status: Available on npm. Lightweight and focused on the WASM boundary.

6. rapid-fuzzy (Rust + WASM)

  • Why it's awesome: Rust-powered fuzzy search and string distance for JavaScript/TypeScript. Claims up to 15,000x faster than Fuse.js in indexed mode.
  • Status: Published on npm. Good for high-performance string distance and fuzzy matching.

7. USearch (C++ + WASM)

  • Why it's awesome: SIMD-optimized search engine with JavaScript bindings. Supports both vector (ANN) and text fuzzy search. Available in 10+ languages (C++, Python, JS, Rust, Go, etc.). Uses custom SIMD-optimized single-threaded and multi-threaded indexes.
  • Status: 4.2k stars. Production-ready with npm packages for browser use.

8. Stork Search (Rust + WASM)

  • Why it's awesome: A full-featured static-site search engine compiled to WASM. Index your documents with the Stork CLI, then serve a single .wasm + .st index file. TypeScript bindings included.
  • Status: Mature project with documentation, theming support, and GitHub Actions for CI indexing.

9. Tinysearch (Rust + WASM)

  • Why it's awesome: Minimalist WASM-based search engine inspired by Stork, but even simpler. Generates a tiny WASM blob with a built-in index. Ideal for blogs and documentation sites where bundle size matters.
  • Status: Lightweight, well-suited for static site generators like Zola and Hugo.

Server-Side Search Engines with WASM/Browser Support

These are primarily server-side search engines that offer WASM builds or client-side JavaScript SDKs, bringing server-grade search into the browser.

1. Meilisearch (Rust)

  • Why it's awesome: 58.6k stars. Lightning-fast search engine with typo tolerance, faceting, filtering, and geosearch. Offers a browser-compatible WASM client via meilisearch-js that can work with an embedded search index. Supports hybrid search (keyword + vector/semantic).
  • Browser path: Use the JS client, or embed the index via WASM for offline-first search.

2. Typesense (C++)

  • Why it's awesome: 26.3k stars. Open-source alternative to Algolia with typo tolerance, synonyms, geosearch, and vector search. Offers typesense-js client SDK and typesense-instantsearch-adapter for Algolia InstantSearch compatibility.
  • Browser path: Use the JS client against a Typesense server, or embed via WASM for self-contained search.

3. Tantivy (Rust)

  • Why it's awesome: A Rust full-text search library similar to Lucene. Can be compiled to WASM via wasm-pack. Extremely fast inverted index with BM25 ranking, tokenizer pipeline, and segment-based architecture.
  • Browser path: Compile to WASM for a full Lucene-grade search engine in the browser. See tantivy-wasm experiments.

4. SymSpell (C# / multiple ports)

  • Why it's awesome: 3.4k stars. Claims 1 million times faster spelling correction and fuzzy search through Symmetric Delete spelling correction algorithm. Available in C#, Java, Python, and JavaScript ports.
  • Browser path: Use the JavaScript port directly, or compile the C# version to WASM via Blazor.

Bring Your Own System Library (DIY WASM)

If none of the above fit your exact needs, you can compile any of these high-performance fuzzy matchers to WASM yourself.

Rust crates (via wasm-pack)

  • nucleo — The fastest Rust fuzzy matcher, used in Helix editor. ~6x faster than skim. Already has a WASM wrapper to model after.
  • skim / fuzzy-matcher — Smith-Waterman based matcher used by the sk CLI tool. Well-documented SkimMatcherV2 API.
  • bitap — Pure Rust Bitap algorithm implementation. Compiles cleanly to WASM with no-std support.
  • flash-fuzzy-core — The core Bitap + Bloom filter engine behind FlashFuzzy. Zero dependencies, no_std compatible.
  • fuzzy-matcher — The core matching algorithm used by skim. Supports multiple scoring strategies (Smith-Waterman, Skim, consecutive bonus).

C/C++ (via Emscripten)

  • fzy — A fast, simple fuzzy text selector. The C implementation is compact and compiles easily to WASM. The algorithm is used by many editors and tools.
  • lib_fts — Forrest Smith's reverse-engineered Sublime Text fuzzy matching algorithm in C++. The original reference implementation for many JS ports.
  • Teg — A fast fuzzy finder written in C with an emphasis on simplicity.
  • fzf — The original CLI fuzzy finder written in Go. While primarily Go, C bindings exist and it compiles to WASM via various toolchains. The scoring algorithm is the gold standard for command-palette UX.

Go (via tinygo / gopherjs)

  • fzf — The original CLI fuzzy finder written in Go. Can be compiled to WASM via TinyGo, though the JS port (fzf-for-js) is usually more practical.
  • skim — A fuzzy finder in Rust (not Go), but worth noting as an alternative fzf implementation with similar WASM potential.

Algorithm Reference

Understanding the core algorithms helps pick the right library:

Algorithm Used By Strengths Weaknesses
Levenshtein Distance fast-fuzzy, FlashFuzzy Edit distance, intuitive Slow on large datasets
Damerau-Levenshtein fast-fuzzy Handles transpositions Still O(n*m)
Bitap (Shift-OR) FlashFuzzy, Fuse.js Fast substring, bit-parallel Limited edit distance
Smith-Waterman nucleo, skim Local alignment, accurate Computationally expensive
BM25 Orama, Tantivy Ranking relevance, industry standard Requires inverted index
SublimeText Scoring fuzzysort, fuzziersort Great UX for search-as-you-type Heuristic, not edit-distance
Sellers' Method fast-fuzzy Fast substring with edit distance Niche algorithm
FST (Finite State Transducer) docfind Sub-ms lookup, compressed index Complex to build
Symmetric Delete SymSpell 1Mx faster spelling correction Pre-computation required

Benchmark Results

All benchmarks run on Bun 24.3.0 (Linux x64) for JS and Zig 0.16.0 ReleaseFast for native. Each algorithm scores every candidate in the corpus against queries (exact + typos + partial). QPS = queries per second (higher is better). q = average match quality (0..1, higher is better).

Zig Native vs JavaScript — Same Algorithm, Different Language

Direct comparison of the same algorithm implemented in both Zig (ReleaseFast native) and JavaScript. Measures raw compute performance without WASM overhead.

Algorithm JS QPS (50 items) Zig QPS (50 items) Speedup JS QPS (425 items) Zig QPS (425 items) Speedup
SublimeScore 11.6K 45.5K 3.9x 3.4K 4.9K 1.4x
Dice (2-gram) 3.5K 20.3K 5.8x 616 3.2K 5.2x
LCS Ratio 5.9K 14.8K 2.5x 2.3K 2.1K 0.9x
Jaro-Winkler 6.6K 12.7K 1.9x 2.0K 2.4K 1.2x
Levenshtein 4.1K 5.8K 1.4x 1.2K 2.2K 1.8x
Smith-Waterman 4.5K 10.0K 2.2x 1.2K 1.6K 1.3x
Damerau-Lev. 3.7K 8.4K 2.3x 526 1.7K 3.2x
Bitap (k=1) 341 7.4K 21.7x 45 1.5K 33x

Key finding: Zig is 1.4–33x faster than JS for the same algorithms. The biggest wins are on algorithms with heavy inner loops (Bitap: 21-33x, Dice: 5-6x, Damerau: 2-3x). Simpler algorithms (Levenshtein, LCS) show smaller 1.2-2.5x gains. Quality scores are identical — confirming correct porting.

Homemade Algorithms (Pure JavaScript)

Algorithm 50 items 250 items 425 items 330 items 2180 items
SublimeScore 11.6K q/s (q=0.899) 11.3K q/s (q=0.751) 3.4K q/s (q=0.760) 5.5K q/s (q=0.986) 583 q/s (q=0.889)
LCS Ratio 5.9K q/s (q=0.872) 4.0K q/s (q=0.882) 2.3K q/s (q=0.891) 1.1K q/s (q=0.915) 283 q/s (q=0.868)
Jaro-Winkler 6.6K q/s (q=0.963) 4.5K q/s (q=0.951) 2.0K q/s (q=0.953) 1.5K q/s (q=0.968) 277 q/s (q=0.964)
Levenshtein 4.1K q/s (q=0.808) 3.2K q/s (q=0.800) 1.2K q/s (q=0.818) 762 q/s (q=0.862) 295 q/s (q=0.802)
Smith-Waterman 4.5K q/s (q=0.801) 2.2K q/s (q=0.805) 1.2K q/s (q=0.819) 451 q/s (q=0.861) 169 q/s (q=0.795)
Dice (2-gram) 3.5K q/s (q=0.788) 1.7K q/s (q=0.781) 616 q/s (q=0.791) 539 q/s (q=0.869) 111 q/s (q=0.768)
Jaccard (2-gram) 3.3K q/s (q=0.680) 819 q/s (q=0.693) 473 q/s (q=0.701) 259 q/s (q=0.792) 53 q/s (q=0.655)
Damerau-Lev. 3.7K q/s (q=0.818) 971 q/s (q=0.827) 526 q/s (q=0.835) 174 q/s (q=0.871) 79 q/s (q=0.818)
Bitap (k=1) 341 q/s (q=0.901) 86 q/s (q=0.905) 45 q/s (q=0.924) 25 q/s (q=0.960) 5 q/s (q=0.895)

Zig Native Benchmarks (ReleaseFast)

Same algorithms compiled with Zig ReleaseFast optimization.

Algorithm 50 items 85 items Speedup vs JS
SublimeScore 45.5K q/s (q=0.899) 4.9K q/s (q=0.760) 1.4–3.9x
LCS Ratio 14.8K q/s (q=0.902) 2.1K q/s (q=0.891) 0.9–2.5x
Dice (2-gram) 20.3K q/s (q=0.829) 3.2K q/s (q=0.791) 3.2–5.8x
Jaro-Winkler 12.7K q/s (q=0.963) 2.4K q/s (q=0.953) 1.2–1.9x
Smith-Waterman 10.0K q/s (q=0.832) 1.6K q/s (q=0.819) 1.3–2.2x
Damerau-Lev. 8.4K q/s (q=0.848) 1.7K q/s (q=0.835) 1.7–3.2x
Levenshtein 5.8K q/s (q=0.838) 2.2K q/s (q=0.818) 1.4–1.8x

Library Benchmarks

Library 50 items 250 items 425 items 330 items 2180 items
FlexSearch 23.9K q/s 136.5K q/s 118.4K q/s 35.5K q/s 35.4K q/s
fuzzysort 8.5K q/s (q=0.991) 8.4K q/s (q=0.991) 8.9K q/s (q=0.991) 21.5K q/s (q=0.991) 3.9K q/s (q=0.991)
MiniSearch 3.0K q/s 24.2K q/s 13.5K q/s 15.5K q/s 6.8K q/s
uFuzzy 3.4K q/s 5.2K q/s 4.1K q/s 3.9K q/s 1.7K q/s
Fuse.js 1.1K q/s 721 q/s 336 q/s 199 q/s 68 q/s
fast-fuzzy 390 q/s 345 q/s 215 q/s 231 q/s 33 q/s

Winners by Dataset

Dataset Fastest Library Fastest Algo (JS) Fastest Algo (Zig) Best Quality
50 cities FlexSearch (23.9K) SublimeScore (11.6K) SublimeScore (45.5K) Jaro-Winkler (q=0.963)
250 fruits FlexSearch (136.5K) SublimeScore (11.3K) SublimeScore (8.6K) Jaro-Winkler (q=0.951)
425 tech FlexSearch (118.4K) SublimeScore (3.4K) SublimeScore (4.9K) Jaro-Winkler (q=0.953)
330 words FlexSearch (35.5K) SublimeScore (5.5K) SublimeScore (5.6K) SublimeScore (q=0.986)
2180 mixed FlexSearch (35.4K) SublimeScore (583) SublimeScore (590) Jaro-Winkler (q=0.964)

Key Takeaways

  1. FlexSearch dominates raw throughput — up to 136K q/s. Its contextual index makes it 10-100x faster than linear-scan libraries.

  2. fuzzysort hits the quality sweet spot — 0.991 quality across ALL datasets. Best overall library for search-as-you-type.

  3. SublimeScore is the fastest algorithm in both languages — 11.6K q/s in JS, 45.5K q/s in Zig. Best speed/quality tradeoff for custom search engines.

  4. Zig gives 1.4–33x speedup over identical JS algorithms. Bitap benefits most (33x — JS BigInt overhead eliminated). Dice (5.8x), Damerau (3.2x), and SublimeScore (3.9x) also see major gains.

  5. Jaro-Winkler has the highest quality — consistently 0.95-0.96. Best for name matching and deduplication.

  6. Bitap is slow at raw scan (5-341 q/s in JS) but shines with pre-filtering (Bloom filters, inverted indexes) as FlashFuzzy does.

  7. For large datasets (>2000 items): FlexSearch (35K q/s) or MiniSearch (6.8K q/s). Libraries with proper indexing scale far better than raw algorithms.

  8. Writing hot-path search in Zig and compiling to WASM is a practical way to get near-C performance in the browser. The WASM boundary adds ~2-5x overhead vs native, but the algorithms themselves are still 1.4-33x faster than JS equivalents.

Running the Benchmarks

cd benchmarks
bun install

# Run JS benchmarks
bun run bench              # full (all algorithms + libraries)
bun run bench --quick      # skip huge dataset
bun run bench --lib-only   # only test libraries
bun run bench --algo-only  # only test algorithms (JS + Zig native)

# Build & run Zig native benchmark
cd zig
zig build -Doptimize=ReleaseFast
./zig-out/bin/fuzzy_bench

Zig Implementation

All benchmarked algorithms are implemented in Zig (benchmarks/zig/). Currently builds as a native binary for direct JS vs Zig comparison. WASM build is planned once Zig 0.16.0's WASM linker issues are resolved.

Files

File Purpose
benchmarks/zig/src/levenshtein.zig Levenshtein distance + score
benchmarks/zig/src/damerau.zig Damerau-Levenshtein with transpositions
benchmarks/zig/src/bitap.zig Bitap (Shift-OR) approximate matching
benchmarks/zig/src/smith_waterman.zig Smith-Waterman local alignment
benchmarks/zig/src/jaro_winkler.zig Jaro-Winkler similarity
benchmarks/zig/src/ngram.zig Dice coefficient + LCS ratio
benchmarks/zig/src/main.zig WASM exports (for future WASM build)
benchmarks/zig/src/bench.zig Native benchmark runner
benchmarks/zig/build.zig Build configuration

Key Design

  • Zero heap allocation — all algorithms use stack-allocated buffers (512-2048 bytes). No malloc, no GC.
  • No std library imports in algorithm files — pure computation only, maximum portability.
  • Scores 0..1 — every function returns a normalized score identical to the JS version.
  • ReleaseFast optimized — aggressive compiler optimizations for maximum throughput.

Build

cd benchmarks/zig

# Native binary (for benchmarking)
zig build -Doptimize=ReleaseFast
./zig-out/bin/fuzzy_bench

# WASM (when Zig 0.16.0 WASM support stabilizes)
# zig build-lib src/main.zig -target wasm32-wasi -dynamic -O ReleaseFast

Contributions to this list are welcome!

About

A curated list of the absolute fastest fuzzy search libraries for JavaScript in the browser. Whether you need an ultra-lightweight filter, SublimeText-like search as you type, or WebAssembly-powered speed for massive datasets, this list covers the best options available.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages