Open-source project
fossasia/visdom avatar
fossasia/visdom

Visdom: a local web dashboard for watching experiments while they run

Tool for real-time visualization, monitoring and collaborative analysis of AI/ML experiments and live data. Supports Python, PyTorch/Torch, NumPy, TensorFlow/Keras https://visdom.dev

10,305 stars1,264 forksPythonApache-2.0

At a glance

What is it?
A Python server and browser front end that broadcasts plots, images and text to a local dashboard over websockets, aimed at researchers who want to watch a training run instead of waiting for it, and revived after a three-and-a-half-year gap by a 0.3.0 release that raised the Python floor to 3.12.
Who is it for?
Visdom fits the specific problem of watching an experiment while it runs on a machine you control, with no hosted service and no per-run cost. It is the wrong tool for storing results durably or for a team that needs a shared experiment record, because the README describes a visualization space rather than a database.
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 20 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

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

Editorial analysis

What Visdom is for, in the project's own framing

The repository describes Visdom as a tool for real-time visualization, monitoring and collaborative analysis of AI and machine learning experiments and live data, with Python as the client language. The README's own framing is narrower and more useful: creating, organizing and sharing visualizations of live, rich data, broadcast for yourself and your collaborators.

The word that matters is live. Visdom is a dashboard you watch while a computation is in progress, not a results store you query afterwards. A training script creates a Visdom object, sends it scalars or images as it goes, and a browser window shows the loss curve updating in real time. That is the whole product, and it is a product with a real use: catching a diverging run at minute two instead of at hour six.

The list of supported clients in the project description names Python, PyTorch and Torch, NumPy, and TensorFlow and Keras. The example directory backs that up with concrete scripts rather than assertions: `train_example.py`, `train_keras_example.py`, `train_lightning_example.py`, `train_sklearn_example.py`, `train_xgboost_example.py`, and `mnist-embeddings.py`.

The package runs as a local server, by default on port 8097, and the browser is the interface. There is no cloud account and no hosted tier described anywhere in the README.

Environments are the unit of organization, and they compare

Visdom partitions its visualization space into environments, and this is the feature that separates it from a logging call that prints to a terminal. By default every user gets an environment called `main`. New environments can be created from the UI or programmatically, the state of each is persistently saved, and environments hold entirely separate pools of plots.

Each environment has a URL, which is what makes sharing work without an account system. The README gives the pattern for the default one, `http://localhost:8097/env/main`, and notes that if your server is hosted you can share that URL so others see the same visualizations.

The organization scheme has a sharp edge worth knowing about. Environments are organized hierarchically by the first `_` in the name, and forward slashes in environment names are escaped to `_`. Both of those characters therefore change how environments appear as a tree in the UI. If you name experiments with dates like `2026_09_17_run3`, that hierarchy is doing something for you. If you name them `run-3`, they land flat.

The feature that earns the most attention is comparison. From the main page you can select multiple environments in the checkboxes and the server queries for plots with the same titles in all of them, then plots them together. That is the workflow the project is actually for: run the same experiment with two hyperparameters, name the plots identically, and overlay the curves.

Callbacks turn the browser into an input device

Most monitoring tools are one-directional: the script sends, the dashboard displays. Visdom supports callbacks, so a Python function can react to something happening in the browser. The demo in the README shows an editable text pad, which is the clearest illustration of what that means.

You register a handler with `viz.register_event_handler(handler, win_id, env=None)`, passing the handler, the window id and an optional environment name. Naming the environment is not decoration: it prevents event handlers firing across different environments that happen to share a window id. Multiple handlers can attach to one window, and `viz.clear_event_handlers(win_id, env=None)` removes them.

When an event fires, the callback receives a dict with `event_type`, `pane_data` holding all stored contents for that window including layout and content, `eid` for the current environment, and `target` for the window id. Four event types are supported. `Close` fires when a window is closed and returns only those base fields. `KeyPress` adds `key` as a string including state modifiers, and `key_code` as the raw javascript event keycode without modifiers. `PropertyUpdate` fires from the property pane and adds `propertyId` and `value`. `Click` fires on an image pane and adds `image_coord` with `x` and `y`.

The `Click` coordinate detail is the one that would catch you out, and the README flags it directly. Those coordinates are in the frame of the possibly zoomed or panned image, not the enclosing pane. Any code mapping a click to a data point has to account for the image transform first.

Windows, editable plots, and exporting the figure

The interface starts as a blank slate. You populate it with plots, images and text, and each lands in a window you can drag, drop, resize and destroy. The README notes that the browser's own zoom adjusts the scale of the UI, which is a small thing that turns out to matter on a laptop with a 13-inch screen.

Plot parameters are editable at runtime. The top-right edit button opens the full list of parameters used for the plot in that window, and changing one alters the plot on the fly rather than requiring a re-send from Python. For a long run where you realise mid-flight that the y-axis is wrong, that saves a restart.

Export is handled as SVG. You can download the content of windows, including your plots, in `svg` format, which is the right choice for a figure headed into a paper since it is vector rather than a screenshot.

The persistence story is thinner than the rest of the documentation and worth flagging. The README says window and environment state is stored across sessions, but it does not describe where that state lives, how to back it up, or whether there is a migration story. For a visualization dashboard that is an acceptable gap. For anything you intend to treat as a record of your experiments, it is not.

Release 0.3.0 and the Python 3.12 requirement

The version history has a strange shape and it matters for how you read the project. Version 0.2.3 shipped in October 2022, 0.2.4 in February 2023, and then nothing until 0.3.0 on 2026-09-11. The release notes describe that gap as roughly three and a half years of accumulated development, and they are unusually honest about what it contains.

The headline features are a pluggable persistence layer, a new experiment-tracking API, eight new visualization types, HTTPS and OpenAPI support, and a broad set of stability and security fixes across the plotting, embeddings and socket layers. Test infrastructure changed too: end-to-end testing is mid-migration from Cypress to Playwright with both suites present, and a Python unit test suite using pytest was added alongside them. The tree reflects that, with four separate Playwright config files for the different suites.

The upgrade warning is the part to read twice. `visdom` now declares `python_requires>=3.12`. On an older interpreter, a current pip will refuse v0.3.0 and keep or select the newest compatible release, typically v0.2.4. An installer that does not enforce `Requires-Python` may install it anyway, and then importing it will fail. The `six` dependency was also dropped. The release notes warn that five areas can affect an existing setup, and the section visible here is the first of them.

The default branch is `dev`, not `main`, which is worth knowing before you clone and pin.

What the dependency list reveals about the runtime

`setup.py` is short and readable, and it tells you what actually runs. The declared requirements are numpy from 1.8 upward, scipy, requests, tornado, jsonpatch, websocket-client, networkx and openTSNE, plus either pillow-simd or plain pillow depending on what is already installed in the environment.

Tornado is the web server and websocket-client is the transport, which is the standard combination for this shape of tool: a long-lived socket from the Python process to the browser rather than polling. networkx and openTSNE are there for the embeddings visualisation, which matches the presence of `mnist-embeddings.py` in the example directory.

PyTorch is optional and handled with care. The setup script attempts to import torch, and if the detected version is below 2.0.0 it prints a warning that PyTorch 2.0.0 or newer is recommended for full support. Any other exception, including torch not being installed at all, is swallowed silently, so the check never blocks installation.

There is also a version-string indirection worth noting. The package does not keep its version in `setup.py`; it reads `py/visdom/VERSION` from disk. That is a small design choice that prevents the two from drifting apart, and it is the kind of detail you only notice when you read the packaging files.

Licensing is Apache-2.0, stated in both `setup.py` and the `LICENSE` file.

Editorial conclusion

Visdom fits the specific problem of watching an experiment while it runs on a machine you control, with no hosted service and no per-run cost. It is the wrong tool for storing results durably or for a team that needs a shared experiment record, because the README describes a visualization space rather than a database. Version 0.3.0 came out on 2026-09-11 and the last push was on 2026-09-17, so the three-and-a-half-year silence after 0.2.4 has just ended. Read the Before You Upgrade section of that release first, because Python 3.12 is now mandatory, then start from `example/demo.py` before wiring a training loop to it.

Frequently asked questions

What is Visdom?

A tool for visualizing live, rich data, described in the project as supporting Python, PyTorch and Torch, NumPy, and TensorFlow and Keras. It runs as a local server, by default on port 8097, and broadcasts plots, images and text to a browser dashboard while an experiment is still running rather than storing results for later.

How do I install Visdom for Python?

The package is on PyPI as `visdom`. Version 0.3.0 declares `python_requires>=3.12`, so a current pip on an older interpreter will refuse it and keep v0.2.4 instead. An installer that ignores `Requires-Python` may install v0.3.0 anyway, and the import will then fail.

What are Visdom environments and how do I share a dashboard?

Environments partition the visualization space, each holding its own pool of plots, with a `main` environment by default. Every environment has its own URL, for example `http://localhost:8097/env/main`, and the README notes that if your server is hosted you can share that URL so others see the same visualizations. Selecting several environments in the checkboxes plots matching titles side by side.

Can a Python script react to clicks in the Visdom dashboard?

Yes. Register a handler with `viz.register_event_handler(handler, win_id, env=None)`, passing an optional environment name so handlers do not fire across environments sharing a window id. Supported events are `Close`, `KeyPress`, `PropertyUpdate` and `Click`, and the click coordinates are relative to the possibly zoomed or panned image rather than the pane.

What license is Visdom released under?

Apache-2.0, declared in `setup.py` and covered by the `LICENSE` file in the repository root. The package metadata in `package.json` for the JavaScript side carries the same licence.

Official sources

  1. fossasia/visdom on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/fossasia-visdom.svg)](https://hysenlabs.com/projects/fossasia-visdom)