Library / SDK
winkjs/wink-nlp avatar
winkjs/wink-nlp

winkNLP: a JavaScript NLP library with no runtime dependencies

Developer friendly Natural Language Processing ✨

1,390 stars64 forksJavaScriptMIT

At a glance

What is it?
winkjs/wink-nlp is an MIT licensed NLP library for JavaScript that runs in Node.js, browsers and Deno with no external dependencies. It trades the accuracy of a neural pipeline for a small bundle, offline operation and a declarative API.
Who is it for?
Adopt winkNLP if you need an NLP pipeline inside JavaScript, especially in a browser or on Deno, where a Python service is not an option and bundle size and offline operation decide the design. It suits tokenization, sentence boundaries, negation-aware sentiment, entity extraction by pattern, BM25 ranking and cosine similarity on English text.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 115 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 19, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

What the pipeline covers

winkNLP is a JavaScript natural language processing library built around a single processing pipeline. The README lists what that pipeline does: tokenization, sentence boundary detection, negation handling, sentiment analysis, part of speech tagging, named entity recognition and custom entity recognition.

Those seven steps cover most of what people reach for an NLP library to do. The interesting entries are the two that are often missing elsewhere. Negation handling means the pipeline tracks when a sentiment-bearing token is negated, so "not good" does not score as positive, which is a common failure in naive sentiment code. Custom entity recognition means you can define entities by pattern rather than retraining anything.

The README also points at a word embedding package, wink-embeddings-sg-100d, described as 100-dimensional English embeddings for over 350,000 English words, which lets you compute sentence or document vectors.

The audience this suits is a JavaScript or TypeScript developer who needs text features inside an existing application, particularly one that runs in a browser, rather than a researcher pushing accuracy numbers.

No runtime dependencies, and why that matters

The package.json lists no dependencies at all. Everything present is a devDependency: mocha, nyc, chai, eslint, dtslint, coveralls, benchmark and docker. That is an uncommon level of discipline, and it is a claimed feature rather than an accident, since the README states the library is built ground up with no external dependency and points at a Snyk report as evidence.

The practical consequences are three. Install size stays small, the README cites roughly 10Kb minified and gzipped via bundlephobia. Supply chain surface stays flat, since there is no tree of transitive packages to audit. And browser bundles stay loadable over a mobile connection, which is why the README claims models from about 1MB minified and gzipped load in roughly a second on 4G.

The library ships TypeScript definitions, with types/index.d.ts declared in package.json, and the repository carries a dtslint script to test them. The README states it runs on Node.js, web browsers and Deno.

The README's own performance claim is over 650,000 tokens per second on an M1 MacBook Pro in both browser and Node.js, and it says the tokenizer alone approaches 4 million tokens per second in that browser. Both are the project's figures, not independent measurements, and the repository includes a benchmark/ directory with a perf script that runs node benchmark/run.js if you want to produce your own.

Installing winkNLP and reading text

The package is published as wink-nlp, and the language model ships separately as wink-eng-lite-web-model. The library is the pipeline and the model is the data, so both are needed, and the README treats the model as a companion install with a size of its own.

The README does not reproduce a full getting started script in the part available here, and it points at the getting started page on winkjs.org and a set of live examples, where it says most examples are 30 to 40 lines of code. The repository also ships a runkit-example.js, declared in package.json as runkitExampleFilename, which is a runnable entry point for trying it without a local install.

For a first exercise, the API shape is visible in the 2.4.0 release notes, which introduced map over tokens. The example there maps over doc.tokens() and returns an object per token built from token.out() and token.out(its.pos), which shows the two ideas the API rests on: collections you map over, and an out() accessor that takes an its.* property to decide what you get back. Everything else in the library follows that pattern.

The README describes markup as a first-class feature too, so tokens, sentences and entities can be marked with an HTML tag for display, which is what the word cloud and key sentence examples on the project site are built from.

Utilities: BM25 and similarity

Beyond the pipeline, the README lists two utility groups that cover retrieval and comparison.

The BM25 Vectorizer is a full utility with its own documentation page. BM25 is the ranking function behind most classical full-text search, so having a vectorizer means you can build a small search index over your documents without adding a search engine.

The similarity methods are named explicitly: Cosine, Tversky, Sorensen-Dice and Otsuka-Ochiai. Cosine is the one everyone knows; the other three are set-similarity measures that behave differently on asymmetric inputs. Having Tversky available matters if your comparison is directional, for example asking how much of a query is covered by a document rather than how similar the two are overall.

There is also a set of its and as helpers for bag of words, frequency tables, lemmas, stems, stop word removal and negation handling, plus utilities for n-grams, normalisation and a Flesch reading ease score.

One caveat visible in the release history: version 2.3.1 was released to fix BM25Vectorizer method types that did not match the implementation. Type definitions and runtime behaviour diverged there once, so treat the TypeScript signatures as a strong hint rather than a guarantee.

Where the ceiling is

The trade this library makes is accuracy for size and portability. A compact model that loads in a second on 4G is not competing with a large neural pipeline on NER or parsing accuracy, and the README makes no such claim. If your task is extracting entities from clean English text and you need it to run offline in a browser, that trade is a good one. If your task is maximum accuracy on messy multilingual input, it is not.

Language coverage is the concrete boundary. The README calls the tokenizer multilingual and shows a mixed Spanish, Hindi, English and French string being split correctly, but the pretrained model in the naming is English, and the word embeddings are described as English for 350,000 English words. Tokenizing Hindi text and analysing Hindi text are different capabilities, and only the first is claimed.

The other constraint is model maintenance. Because accuracy lives in the model package rather than the library, improving results means a new model release, and the model is a separate install with its own version line.

spaCy and compromise as alternatives

The two alternatives sit on either side of winkNLP, and the difference in each case is what you give up.

spaCy is the accuracy-first option. It is Python, it uses trained neural models, and its pipelines are the reference point for production NER and dependency parsing. Choosing it means your text processing is not in JavaScript, which usually means a service boundary between your Node application and the Python process, and it cannot run in a browser at all. If accuracy is the binding constraint, that boundary is worth building.

compromise is the other JavaScript option and sits below winkNLP in weight. It is a compact rule-based library aimed at quick text parsing in the browser, with part of speech and sentence handling but without the pretrained model and word vector machinery. Choose it when you need rough structure from text and want the smallest possible thing; choose winkNLP when you need named entities, sentiment with negation handling, or embeddings.

The deciding question is where the code has to run. If it has to run in a browser or on the edge, winkNLP is one of the few options that brings a real pipeline there.

Maintenance and licence

winkNLP is MIT licensed, which is permissive and carries no copyleft obligation, so embedding it in a commercial product is straightforward.

The release record is short and slow. Version 2.4.0, which added map over tokens, was published on 2025-06-30. Before that, 2.3.2 on 2024-11-30 was an operational update for a new model release, and 2.3.1 on 2024-11-24 fixed some type definitions. The last push to the repository was on 2026-05-27, so the code has moved since the last tag without a release being cut.

That pattern means you should expect to wait for fixes rather than see them shipped promptly, and you should check whether the model package has moved ahead of the library before upgrading one without the other.

On engineering hygiene the signals are good. The repository has CHANGELOG.md, ROADMAP.md, SECURITY.md and CONTRIBUTING.md, tests run under mocha with nyc coverage and a coveralls badge, and the project holds an OpenSSF best practices badge. For a library you would run inside a product, those matter more than release frequency.

Editorial conclusion

Adopt winkNLP if you need an NLP pipeline inside JavaScript, especially in a browser or on Deno, where a Python service is not an option and bundle size and offline operation decide the design. It suits tokenization, sentence boundaries, negation-aware sentiment, entity extraction by pattern, BM25 ranking and cosine similarity on English text. Skip it if you need state of the art accuracy, since the model is deliberately compact, or if the language is not English, because the pretrained model and the word embeddings are English only. Verify the version pairing first: the library is at 2.4.0 from 2025-06-30 while the repository was pushed to on 2026-05-27, so check which model release the current code expects before installing.

Frequently asked questions

Does winkNLP have dependencies?

No runtime dependencies. The package.json lists only devDependencies such as mocha, nyc, chai, eslint and dtslint, and the README states the library is built with no external dependency.

Can winkNLP run in a browser?

Yes. The README states it runs on Node.js, web browsers and Deno, and cites model sizes from about 1MB minified and gzipped loading in roughly a second on 4G.

Does winkNLP support languages other than English?

The README describes the tokenizer as multilingual and shows Spanish, Hindi, English and French text being split correctly, but the pretrained model and the 100-dimensional word embeddings are described as English.

What NLP tasks does winkNLP cover?

The README lists tokenization, sentence boundary detection, negation handling, sentiment analysis, part of speech tagging, named entity recognition and custom entity recognition in one pipeline.

Does winkNLP include word embeddings?

Word embedding support comes from the separate wink-embeddings-sg-100d package, described as 100-dimensional English embeddings for over 350,000 English words, usable in a browser.

Is winkNLP actively released?

Release cadence is slow. Version 2.4.0 was published on 2025-06-30 and the two before that in November 2024, while the repository was last pushed to on 2026-05-27.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. winkjs/wink-nlp on GitHub
Community notes

Community notes