opencv-js: the OpenCV wasm build packaged for Node and the browser
OpenCV JavaScript version for node.js or browser
At a glance
- What is it?
- This package ships the official OpenCV.js build as an npm module, with TypeScript declarations and a CLI tool that reformats help output from other packages. The interesting part is the loading dance, because the module resolves differently depending on whether the wasm is already instantiated.
- Who is it for?
- Adopt opencv-js if you want computer vision in JavaScript without running a Python service, and you can live with the constraints of the upstream OpenCV.js build. Do not adopt it expecting the type declarations to be complete, because the README says they may not be up to date with the latest OpenCV.js and points you at doc/cvKeys.json for the runtime truth.
- Can I use it commercially?
- Yes. Apache-2.0 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 83 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
It is the official wasm build, packaged
opencv-js is the OpenCV JavaScript version for node.js or browser, and the repository makes its provenance explicit: the file opencv.js was downloaded from the OpenCV documentation site for version 5.0.0. That matters for how you evaluate it. This is not a reimplementation of OpenCV in JavaScript, it is the Emscripten build of the C++ library with TypeScript declarations and npm packaging around it. The consequences follow from that. You inherit the upstream build's size and its start-up behaviour, you inherit whatever subset of the OpenCV API the upstream build exposes, and you inherit its version cadence, which is the OpenCV.js build numbering rather than the C++ library's. The package is published as @techstark/opencv-js, with the main entry at dist/opencv.js and the type declarations at src/index.d.ts, and the published files are dist/ and src/.
The loading dance handles three shapes of the same module
The basic usage example is really a load-time negotiation, and it is the part of this package you will copy verbatim. You import the default export, then check what you actually got. If the module is a Promise you await it. If it is not a Promise but already has a Mat property, the wasm is instantiated and you use it directly. Otherwise you assign an onRuntimeInitialized callback that resolves a promise, and the module is instantiated as a side effect of the assignment. Only after one of those three paths do you have a usable cv:
import cvModule from "@techstark/opencv-js";
async function getOpenCv() {
let cv;
if (cvModule instanceof Promise) {
cv = await cvModule;
} else {
if (cvModule.Mat) {
cv = cvModule;
} else {
await new Promise((resolve) => {
cvModule.onRuntimeInitialized = () => resolve();
});
cv = cvModule;
}
}
return { cv };
}The reason there are three paths is that the module format varies with the bundler and the runtime, and the check for a Mat property is the cheapest reliable signal that the wasm is ready. That detection is what people copy from the README, and it is also what people get wrong when they skip it, because calling into cv before it is ready fails in a way that looks like a missing function.
Installing is one package, and the import style is your choice
The How to Use section gives the options plainly. The package installs with npm install @techstark/opencv-js or yarn add @techstark/opencv-js. Then you either import the default export, import cv from "@techstark/opencv-js", in which case for TypeScript you need to set "esModuleInterop": true in your tsconfig.json, or you import the namespace, import * as cv from "@techstark/opencv-js". TypeScript is supported, thanks to the mirada project according to the README. The two import styles are not interchangeable in every setup, and the esModuleInterop requirement is the one detail that catches people out when they follow the default import path in a strict TypeScript project.
Browser use needs three webpack fallbacks
If you use this package for browsers, you need to set some polyfills in your webpack.config.js, and the fix is small enough to quote in full:
module.exports = {
resolve: {
modules: [...],
fallback: {
fs: false,
path: false,
crypto: false
}
}
};The three modules are Node built-ins that the Emscripten build references but a browser does not have, and setting them to false tells webpack not to try to polyfill them. This is a symptom of the packaging approach rather than of the project. Because the same file has to serve Node and the browser, the Node-only paths are still present in the bundle, and the browser build has to be told to ignore them. The README documents the webpack case; if you are on another bundler, you will need to work out the equivalent yourself, which is the sort of small piece of friction that a package built for the browser from the start would not have.
The type declarations lag, and there is a file that tells you the truth
The one caveat the README states is worth quoting in substance: the TypeScript type declarations may not be up to date with the latest OpenCV.js, and you are referred to doc/cvKeys.json to check the available methods and properties at runtime. That is an honest limitation of wrapping a generated C++ API. OpenCV has thousands of symbols, and the declaration file in src/ has to be maintained by hand against a build that changes shape. The cvKeys.json file in the doc/ directory is the generated inventory of what the runtime actually exposes, so the workflow when a method appears missing is to check that file rather than to assume the API is not there. The repository has a jest.config.js, a tsconfig.test.json and a test directory, and a separate test:compat script that runs node test/compat/run-all.mjs, which is the shape you would expect for checking the wrapper against several upstream builds.
Releases ship as numbered builds, not a final tag
The release history explains the versioning. The most recent artefacts are opencv-js-5.0.0-build9 on 2026-06-26, opencv-js-5.0.0-build8 the same day, and opencv-js-5.0.0-build6 on 2026-06-25, and the package version in the manifest is 5.0.0-release.1. So during the 5.0.0 line the npm releases are numbered builds of the upstream OpenCV.js release rather than a single final tag, and the manifest has moved on to a release candidate suffix. The practical instruction is to install the exact build you tested rather than a floating latest, because the API surface can change between builds and the type declarations may not track it. The licence is Apache-2.0 with the LICENSE file at the root, the repository is not archived and the last push was on 2026-08-01.
Editorial conclusion
Adopt opencv-js if you want computer vision in JavaScript without running a Python service, and you can live with the constraints of the upstream OpenCV.js build. Do not adopt it expecting the type declarations to be complete, because the README says they may not be up to date with the latest OpenCV.js and points you at doc/cvKeys.json for the runtime truth. Before you commit, check the release tags you are installing, since the 5.0.0 line ships as numbered builds rather than a single final release, and decide between the default import and the namespace import based on how your bundler handles the module.
Frequently asked questions
What is opencv-js?
It is an Apache-2.0 licensed npm package providing the OpenCV JavaScript version for node.js or the browser, built by taking the official opencv.js file from the OpenCV documentation site for version 5.0.0 and packaging it with TypeScript declarations. The package is published as @techstark/opencv-js.
How do I install and import opencv-js?
Run npm install @techstark/opencv-js or yarn add @techstark/opencv-js, then either import the default export, which for TypeScript needs "esModuleInterop": true in tsconfig.json, or import the namespace with import * as cv. The module may resolve as a promise, as an already instantiated object with a Mat property, or need an onRuntimeInitialized callback.
What do I need to configure to use opencv-js in a browser?
With webpack you need to set resolve.fallback for fs, path and crypto to false, because the Emscripten build references Node built-ins that a browser does not have. The README documents the webpack case specifically.
Are the opencv-js TypeScript definitions up to date?
Not always. The README states that the type declarations may not be up to date with the latest OpenCV.js, and points to doc/cvKeys.json to check the available methods and properties at runtime. The releases during the 5.0.0 line are numbered builds, so the newest tag is opencv-js-5.0.0-build9 from 2026-06-26.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/techstark-opencv-js)Was this useful?