huggingface.js: A Monorepo of JavaScript Clients for the Hugging Face Hub
Use Hugging Face with JavaScript
At a glance
- What is it?
- The repository ships a set of small TypeScript packages that talk to huggingface.co and to hosted Inference Providers. It is a thin client layer, not a runtime, and the README itself says the libraries are still young.
- Who is it for?
- Adopt it if you are writing a browser or Node script that needs to create a repo, commit a file, or call a hosted model, and you would rather not hand-roll fetch calls against the Hub API. Do not adopt it as an inference runtime: it is a client, so it does nothing when the network is down and nothing for local weights.
- 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 received new commits within the last day.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem is that the Hub is an HTTP API and most JavaScript projects do not want to speak it directly
Every operation against huggingface.co is an HTTP request with a token attached: create a repository, upload a file, list what is in a repo, delete files. The README shows exactly this shape in its opening snippet, with createRepo taking a repo object of type and name plus an accessToken, and uploadFile taking a repo, a token, and a file described by path and content. Writing that by hand means tracking endpoint paths, auth header formats, and the multipart handling for file uploads. The @huggingface/hub package exists to absorb that work and to ship TypeScript types alongside it, so a RepoId is a typed value rather than a string you hope is spelled correctly. The audience is JavaScript and TypeScript developers who already treat the Hub as their artifact store and want to drive it from a script, a build step, or a browser page. It is not aimed at people who want to run models locally; nothing in the listed packages loads weights for you.
Ten packages, each owning one slice of the Hub surface
The repository is a collection rather than a single library, and the README lists the members plainly. @huggingface/hub handles repository and file operations. @huggingface/inference is the model-calling client, covering serverless Inference Providers and dedicated Inference Endpoints. @huggingface/mcp-client is a Model Context Protocol client with a small agent library built on top of InferenceClient. @huggingface/gguf parses GGUF files that live on a remote host, and @huggingface/dduf does the equivalent for the DDUF Diffusers Unified Format. @huggingface/tasks is described as the definition files and source of truth for Hub primitives such as pipeline tasks and model libraries, which means it is a data package rather than a client. @huggingface/jinja is a minimal JS implementation of the Jinja templating engine intended for ML chat templates. @huggingface/space-header exposes the Space mini_header outside Hugging Face. @huggingface/ollama-utils carries utilities for keeping Ollama compatibility with Hub models. @huggingface/tiny-agents is a model-agnostic agent library that can use tools. That split matters in practice: the parser packages are useful even if you never call a model, and the tasks package is useful even if you never call the Hub.
Inference routing: one client, many providers, and an endpoint escape hatch
The inference package centers on an InferenceClient constructed with a token. Calls pass a model identifier and, optionally, a provider string. The README names sambanova, together, fal-ai, replicate and cohere as examples, and notes that you can omit the model entirely to use the recommended model for a task, which it demonstrates with a translation call that supplies only inputs and parameters for src_lang and tgt_lang. Streaming is handled by a separate method, chatCompletionStream, which the README consumes with for await over chunks and reads chunk.choices[0].delta.content. Multimodal input is supported by passing a Blob as data, shown with an imageToText call that fetches a picture first. For dedicated deployments there is client.endpoint(url), which returns a scoped client bound to that base URL; the README uses it once against an AWS endpoints.huggingface.cloud host for textGeneration and once against a router.huggingface.co path for chatCompletion. That endpoint method is the interesting part of the design, because it means the same call signatures work against serverless routing and against a dedicated deployment you pay for, without swapping libraries.
Installation is per package, and there is no bundler requirement
The README gives three installation paths. From npm, you install only what you need: npm install @huggingface/hub, npm install @huggingface/inference, npm install @huggingface/mcp-client. From a CDN, you import an ES module URL directly inside a script tag with type="module", for example https://cdn.jsdelivr.net/npm/@huggingface/inference@4.13.28/+esm and https://cdn.jsdelivr.net/npm/@huggingface/hub@2.17.1/+esm. Under Deno, the README shows both esm.sh URLs and npm: specifiers such as npm:@huggingface/inference. Runtime requirements are stated explicitly: modern browsers, Node.js 18 or newer, Bun, or Deno, chosen so the libraries can avoid polyfills and dependencies. The token comes from the account settings page at huggingface.co/settings/tokens, and the examples pass it as the string argument to the InferenceClient constructor or as an accessToken field on hub calls. The README does not document a config file, environment variable fallback, or retry policy, so token plumbing is left to your application.
The README's own warning about youth is the honest part
The line "The libraries are still very young, please help us by opening issues!" is the strongest signal in the material, and it should be read as a statement about API stability rather than modesty. The release list supports the reading: hub-v2.17.1 and hub-v2.17.0 landed three days apart in September 2026, and jinja is still on a v0.5.x line. A package that ships patch releases that frequently is one where you should pin versions, especially for the hub package, whose function signatures are what your scripts compile against. The second limitation is structural. These are clients. Everything depends on a reachable Hugging Face endpoint and a valid token, so there is no offline mode, no local caching layer described in the README, and no fallback when a provider is unavailable. If your requirement is to run a model without network access, or to keep inference inside your own infrastructure without the router in the path, this collection does not address that. Third, the ten-package split means the top-level README is a directory, not a guide; the per-package READMEs are referenced by relative path and are where the actual API detail lives.
Compared with calling the REST API or the Python client directly
The obvious alternative is to skip the library and call the Hub's REST endpoints with fetch yourself. That gives you full control over headers, retries, and request shape, and it adds no dependency to your bundle. The cost is that you reimplement file upload encoding, repo creation payloads, and pagination for listing, and you lose the TypeScript types that the README highlights as a feature. The second alternative is huggingface_hub, the Python client, which is the reference implementation for this surface area and is where new Hub features typically land first. If your pipeline is already Python, or if you need the widest coverage of Hub features, the Python client is the more complete route. The difference in approach is not quality but placement: huggingface.js exists so that a browser page or a Node service can do the same work without a Python process in the loop, and its CDN import path makes that concrete. A third option, for teams that only need model calls, is to talk to a provider SDK directly. That removes the router abstraction but also removes the ability to switch provider by changing one string, which is the trade the provider parameter is buying you.
Maintenance cost, licence, and what to check before you depend on it
The repository is MIT licensed and not archived, with the last push dated 2026-09-10 and hub-v2.17.1 published the same day. MIT is permissive and imposes no source-disclosure obligation on your own code, but it also provides no warranty, and you should read the actual LICENSE file rather than this summary, which is not legal advice. Upgrade cost is the real consideration. Because the packages are versioned independently (hub at 2.17.1, jinja at 0.5.10), you can upgrade the inference client without touching the hub client, which limits blast radius. The counterweight is that the README describes the libraries as young, so minor and patch bumps may still change call signatures. Pinning exact versions in package.json and reading the release notes for hub-v2.17.0 and hub-v2.17.1 before bumping is the cheap insurance. Note also that the CDN examples hardcode versions in the URL, so a browser page pinned to @huggingface/hub@2.17.1 will not move until you edit the import string. Finally, confirm the runtime floor yourself: if your build targets an older Node version or a browser without the modern features the README relies on, no polyfill is shipped to save you.
Editorial conclusion
Adopt it if you are writing a browser or Node script that needs to create a repo, commit a file, or call a hosted model, and you would rather not hand-roll fetch calls against the Hub API. Do not adopt it as an inference runtime: it is a client, so it does nothing when the network is down and nothing for local weights. Before committing, check that your target runtime is Node.js 18 or newer, Bun, or Deno, since the README states the libraries rely on modern features to avoid polyfills; then confirm which @huggingface/* package actually owns the function you need, because the split across hub, inference, gguf and dduf is not obvious from the top-level README alone.
Community notes