mrkeyoor.com_
Tue 22 Sept 22:32 UTC
npmUtilsupdated 22 Sept 2026

fuzzy review

fuzzy 0.1.3 is a synchronous subsequence matcher for short in-memory lists. A query such as `bcn` matches `baconing` because those letters appear in order, then the package scores the match, sorts results, and can wrap the chosen characters for display. Our browser build was 1.4 KB minified and 0.8 KB gzipped. This is a filter and highlighter, with no edit-distance typo correction, index, tokenization, or language-aware search. The current version dates to October 2016 and fixed a React Native blocking bug; it did not change the small `test`, `match`, `filter`, and `simpleFilter` API.

Verdict

fuzzy 0.1.3 installed in 0.4 seconds and produced a 0.8 KB gzipped browser bundle in our sandbox, but its first-subsequence scoring and synchronous full-list scan limit it to small pickers and command menus. Install Fuse.js or fuzzysort when typo handling, several fields, or a large candidate set affects the result quality.

We installed it

Lab card: what happened when we installed fuzzyScreenshot of fuzzy documentation
Install✓ · 0.4s1 package on disk · 1 MB
ImportESM import works · require() works · CommonJS package
Browser0.8 KBgzipped (1.4 KB minified), bundled with esbuild
TypesTypeScript types bundled
Known vulns00 critical · 0 high · 0 moderate · 0 low (npm audit)

Answers from our run

Does fuzzy install cleanly?

Yes. In a fresh container with an empty cache, npm install fuzzy finished in 0.4s, leaving 1 package and 1 MB on disk. npm audit reported no known vulnerabilities.

How much does fuzzy add to a browser bundle?

0.8 KB gzipped (1.4 KB minified) when the whole package is bundled for the browser with esbuild. Importing only part of it is usually smaller.

Does fuzzy work with both ESM and CommonJS?

Yes. Both import 'fuzzy' and require('fuzzy') worked in Node 22 in our run. The package is published as CommonJS.

Does fuzzy include TypeScript types?

Yes, type declarations ship inside the package, so no @types install is needed.

fuzzy or fuzzysort: which should you use?

fuzzysort: Choose it for faster client-side ranking and explicit match indexes. fuzzy 0.1.3 installed in 0.4 seconds and produced a 0.8 KB gzipped browser bundle in our sandbox, but its first-subsequence scoring and synchronous full-list scan limit it to small pickers and command menus.

When should you not use fuzzy?

Users expect misspellings, transpositions, or edit-distance matches. fuzzy only accepts query characters found in order.

API stability4/5Version 0.1.3 still exposes the same four calls documented in 2016: `test`, `match`, `filter`, and `simpleFilter`. That tiny surface has not moved, and both CommonJS require and ESM import worked in our Node 22 check. Stability here comes from a frozen package rather than a compatibility policy, so longstanding scoring quirks are frozen too.
Docs3/5The README gives runnable examples for arrays, object extraction, character wrappers, Node, and direct browser use. It also admits the first-match scoring flaw and lists multi-field search plus async batches as unfinished. There is no maintained API site, complexity guidance, escaping warning, or explanation of how the bundled declarations behave in current TypeScript projects.
Maintenance1/5The latest npm release, 0.1.3, landed in October 2016 to fix a React Native blocking bug. GitHub reports no repository push after December 20, 2021, while the README still lists better occurrence selection, multi-string matching, worker batches, and performance work as TODOs. The repository is unarchived, but the evidence points to dormant code.
Ecosystem3/5npm counted 5,449,804 downloads in the latest completed week and GitHub reports 835 stars, so the package still arrives through many dependency graphs. It has bundled declarations, no runtime dependencies, and working Node interop. Its extension surface stops at one extraction callback and wrapper strings, with no adapters, plugins, index format, or worker API.

Use it if

  • A command menu or picker has a modest array in memory and ordered-character matching is good enough.
  • You need the matched characters returned with custom wrappers for a result label.
  • Each object has one searchable string that a synchronous `extract` callback can return.
  • A 0.8 KB gzipped browser cost matters more than typo correction or a search index.
Skip it if

Setup reality

We installed fuzzy 0.1.3 in 0.4 seconds in a fresh Node 22 Bookworm sandbox. It left 1 package and 1 MB on disk, with 0 direct dependencies, 0 peer dependencies, and 56 KB unpacked. npm audit found 0 known vulnerabilities. The package declares Node 0.6 or newer, and its license field was unknown in our package inspection even though the repository contains an MIT license file.

There are no credentials, config files, native builds, or postinstall steps. The package is CommonJS without an exports map. Both require() and ESM import worked in our check, and TypeScript declarations were bundled. The declaration surface is small because the API itself has only four operations.

Every query walks the supplied values synchronously, and filter sorts the successful matches. simpleFilter skips the ranking result objects and preserves the matching values. A browser bundle that imports the whole package measured 1.4 KB minified and 0.8 KB gzipped, but that small transfer does not prevent a large array from blocking the main thread. Debounce input or move the work outside the UI thread yourself.

The pre and post strings are concatenated into the rendered result. The library does not escape candidate text, so HTML highlighting needs escaped source strings. Matching ignores case by default, failed match calls return null, exact matches score Infinity, and object filtering can inspect only the single string returned by extract.

Patterns

Rank matching strings filter-strings

const fuzzy = require('fuzzy');

const ranked = fuzzy.filter('bcn', ['baconing', 'narwhal', 'a mighty bear canoe']);
console.log(ranked.map((hit) => hit.original));

`filter` returns result objects sorted by score, rather than returning the original strings directly.

Test one candidate test-subsequence

const isMatch = fuzzy.test('cfg', 'config.js');
console.log(isMatch);

The query characters must occur in order. They do not have to be adjacent.

Inspect one scored match inspect-score

const hit = fuzzy.match('abc', 'a-b-c');
if (hit) console.log(hit.score, hit.rendered);

A failed call returns `null`; an exact string match receives an `Infinity` score.

Wrap matched characters highlight-characters

const hit = fuzzy.match('bcn', 'baconing', { pre: '<mark>', post: '</mark>' });
console.log(hit && hit.rendered);

The package inserts wrappers without HTML escaping. Escape untrusted candidate strings before rendering this output.

Search one field in objects search-object-field

const commands = [{ id: 1, label: 'Open file' }, { id: 2, label: 'Close editor' }];
const hits = fuzzy.filter('of', commands, { extract: (command) => command.label });
console.log(hits[0]?.original.id);

`extract` returns one searchable string per item; the package cannot weight or combine several fields.

Turn on case-sensitive matching match-case

const hit = fuzzy.match('Ab', 'Abacus', { caseSensitive: true });
const miss = fuzzy.match('Ab', 'abacus', { caseSensitive: true });

Version 0.1.3 ignores case unless `caseSensitive` is true.

Keep matching values in input order preserve-input-order

const matches = fuzzy.simpleFilter('ab', ['alphabet', 'cab', 'clock']);

`simpleFilter` returns matching values without scores or rendered highlighting and does not rank them.

Cap autocomplete rendering cap-visible-results

function search(query, labels) {
  return fuzzy.filter(query, labels).slice(0, 20);
}

Slicing happens after the package scans and sorts all candidates, so this reduces rendering work rather than matching work.

Debounce browser searches debounce-input

let timer;
input.addEventListener('input', (event) => {
  clearTimeout(timer);
  timer = setTimeout(() => render(fuzzy.filter(event.target.value, labels)), 100);
});

There is no async or worker API. One very large search can still block the browser after the debounce delay.

Import from Node ESM import-from-esm

import fuzzy from 'fuzzy';

const hits = fuzzy.filter('cfg', ['config.js', 'package.json']);

The package is CommonJS and has no exports map; this default import depends on Node's CommonJS interoperability.

Recover the original item keep-original-object

const [hit] = fuzzy.filter('inv', invoices, { extract: (invoice) => invoice.customerName });
if (hit) console.log(hit.original);

Each result keeps the original array member on `original` and its source position on `index`.

Handle an empty search before filtering handle-empty-query

function findLabels(query, labels) {
  if (query.length === 0) return labels;
  return fuzzy.filter(query, labels).map((hit) => hit.original);
}

Handle the empty state in application code so its ordering and result limit are explicit.

Alternatives

PackageRegistryPick it when
fuzzysortnpmChoose it for faster client-side ranking and explicit match indexes.
fuse.jsnpmChoose it for typo tolerance, weighted object keys, and an index.
fast-fuzzynpmChoose it for a maintained TypeScript-oriented matcher with configurable normalization.

More utils guides

lru-cache · ajv · type-fest · p-limit · find-up · js-yaml · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.