---
title: "HDBSCAN in JavaScript with @kanaries/ml"
description: "Learn what HDBSCAN does, when to use it, and how to run HDBScan in JavaScript or TypeScript with @kanaries/ml for browser and Node.js applications."
canonical_url: "https://ml.kanaries.net/docs/apis/clusters/hdbscan"
markdown_url: "https://ml.kanaries.net/docs/apis/clusters/hdbscan.md"
---
# HDBSCAN in JavaScript

## Algorithm overview

HDBSCAN (Hierarchical Density-Based Spatial Clustering of Applications with Noise) finds clusters of **varying density** and identifies noise points without forcing every observation into a cluster. Unlike DBSCAN, it does not depend on a single global `eps` radius: it builds a density hierarchy and extracts the most stable clusters from it, so a tight cluster and a sparse cluster can be recovered in the same run. Choose it when:

- Your clusters have significantly different densities (the classic DBSCAN failure mode).
- You do not know an exact cluster count in advance.
- Outlier/noise detection is important for your downstream workflow.

The `HDBScan` class in @kanaries/ml is a full implementation aligned with scikit-learn's `sklearn.cluster.HDBSCAN`:

1. **Core distances** — the distance from each point to its `min_samples`-th nearest neighbor (counting the point itself, as scikit-learn does).
2. **Mutual reachability** — pairwise distances `max(core_a, core_b, d(a, b))`.
3. **Minimum spanning tree** — Prim's algorithm on the mutual reachability graph.
4. **Condensed tree and stability extraction** — the single linkage hierarchy is condensed by `min_cluster_size`, and flat clusters are selected with the Excess of Mass (EOM) stability criterion.

## Interactive HDBSCAN playground

Change the minimum cluster size, neighborhood size, dataset, and noise level. This browser-side `Clusters.HDBScan` fit uses point opacity to show membership strength and gray to show observations left as noise.

> The HTML version includes a live clustering playground powered by @kanaries/ml. You can change the dataset and algorithm parameters, add observations, and inspect fitted clusters, noise labels, centers, or exemplars. The runnable guide and API reference continue below. [Open the HTML page](https://ml.kanaries.net/docs/apis/clusters/hdbscan).

## Quick start

### HDBScan: Python and JavaScript / TypeScript

The Python example uses scikit-learn; the TypeScript example uses @kanaries/ml in browser or Node.js runtimes.

#### Python (scikit-learn)

```python
from sklearn.cluster import HDBSCAN

X = [[0, 0], [0.1, 0.2], [5, 5], [5.2, 5.1], [9, 0]]

model = HDBSCAN(min_cluster_size=2)
labels = model.fit_predict(X)
```

#### JavaScript / TypeScript (@kanaries/ml)

```ts
import { Clusters } from '@kanaries/ml';

const X = [[0, 0], [0.1, 0.2], [5, 5], [5.2, 5.1], [9, 0]];

const model = new Clusters.HDBScan(2);
const labels = model.fitPredict(X);
```

### Quick JavaScript example

```ts
import { Clusters } from '@kanaries/ml';

const X = [[0, 0], [0.1, 0.2], [5, 5], [5.2, 5.1], [9, 0]];

const model = new Clusters.HDBScan(2);
const labels = model.fitPredict(X);
console.log(labels);
```

## Detailed API reference

```ts
constructor(
    min_cluster_size: number = 5,
    min_samples: number | null = null,
    cluster_selection_epsilon: number = 0.0,
    metric: Distance.IDistanceType = 'euclidean',
    allow_single_cluster: boolean = false
)
```

- `min_cluster_size` — the smallest group of points that counts as a cluster. Splits producing a side smaller than this are treated as points falling out of the parent cluster. This is the main tuning knob.
- `min_samples` — controls how conservative the density estimate is (the `k` used for core distances, counting the point itself). Defaults to `min_cluster_size`. Larger values declare more points noise.
- `cluster_selection_epsilon` — an extraction threshold (not a DBSCAN `eps`): selected clusters born below this distance are merged upward until their parent's birth distance exceeds it. Leave at `0.0` (the default, matching scikit-learn) unless you want to prevent micro-clusters from splitting.
- `metric` — any distance supported by the `Distance` module.
- `allow_single_cluster` — when `true`, the hierarchy root may be selected, allowing the whole dataset to form one cluster.

`fitPredict(samplesX: number[][]): number[]` returns cluster labels. Noise points are marked as `-1`.

`getLabels(): number[]` returns the labels from the last `fitPredict` call.

`getProbabilities(): number[]` returns the cluster membership strength of each sample in `[0, 1]`; noise points have probability `0`.

```ts
const hdb = new Clusters.HDBScan(8);
const labels = hdb.fitPredict(X);
const probabilities = hdb.getProbabilities();
```

### Implementation workflow

1. Scale features so distance comparisons are meaningful.
2. Fit the model and inspect cluster labels plus noise assignments.
3. Tune `min_cluster_size` first; use `min_samples` to adjust how aggressively sparse points are declared noise.

### JavaScript deployment notes

- Use this class when cluster count is unknown, densities vary across clusters, and you expect some observations to remain noise.
- The implementation builds a dense pairwise distance matrix (O(n²) memory and time), so it is suited to datasets up to a few thousand points. In browser workflows, run it off the main thread for larger inputs.
- Results match Python `sklearn.cluster.HDBSCAN` labels on the same data and parameters.
