# Pannellum: a single-file panorama viewer for the web

> Pannellum renders equirectangular and cube panoramas with WebGL and ships as one 21kB gzipped HTML file. It is a good fit for self-hosted virtual tours and a poor fit for mobile app work, which the README explicitly does not support.

**mpetroff/pannellum** — Pannellum is a lightweight, free, and open source panorama viewer for the web.

- Repository: https://github.com/mpetroff/pannellum
- Website: https://pannellum.org/
- Stars: 4,902 · Forks: 773
- Language: JavaScript
- License: MIT
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/mpetroff-pannellum

## The problem Pannellum solves for self-hosted tours

Displaying a 360 photo on a web page usually means choosing between a hosted service that keeps your images on someone else's servers and a JavaScript library that drags in a build pipeline. Pannellum takes the second path but removes most of the pipeline: the README describes deploying it as a single file, 21kB gzipped, embedded into a page as an iframe. The intended user is someone who has an equirectangular image and a web server, and wants the panorama visible without adopting a framework or signing up for a platform.

The repository shows that scope clearly. There is no server component, no database, and no account system in the top-level entries. What is there is src for the viewer, utils for the multiresolution tile generator and the configuration utility, examples with tour, cube and multires HTML files, and doc with the JSON configuration reference. A virtual tour built with Pannellum is a set of image files plus JSON, which is the whole appeal for anyone who wants to keep the asset hosting under their own control.

## How the viewer, the configuration and the tiles fit together

Pannellum renders through WebGL, with HTML5, CSS3 and JavaScript around it, and the README states it is plug-in free. That matters because it means the rendering path is the browser's own graphics stack rather than a Flash-era plug-in, and the browser support list in the README is expressed in those terms: Firefox 40+, Chrome 41+, Safari 9+, Edge 12+, with the caveat that the list is based on feature support and that only recent browsers are tested, so regressions in older browsers are possible.

The data flow has three layers. The image layer is either a single equirectangular panorama or a set of cube faces, as the example files example-cube.htm and examplepanocube0.jpg through examplepanocube5.jpg suggest. The configuration layer is JSON, documented in doc/json-config-parameters.md and mirrored on pannellum.org, and it can also be supplied through the API for advanced integrations. The embedding layer is either an iframe generated by the configuration utility or a direct call into the library. For the standalone viewer, the README prefers a location hash over a search query, giving pannellum.htm#panorama=... as the example, on the grounds that a hash does not send the parameters to the server unnecessarily. That is a small decision with a real consequence: panorama paths and configuration values stay out of your server logs.

The multiresolution path is the part that costs setup effort. A high-resolution panorama is cut into tiles by utils/multires/generate.py, which depends on the nona program from Hugin plus Python 3 with Pillow and NumPy, and recommends pyshtools. Those are external dependencies, not npm packages, so the tiling step is a Python and command-line exercise rather than part of a JavaScript build.

## Installing Pannellum and viewing your first panorama

There is no package installation step in the README for the viewer itself. The deployment path is to take build/pannellum.htm and a full equirectangular panorama, put both on a web server, and embed the result. For local work the README is explicit that a web server is required even on your own machine, because of browser security restrictions, and it offers Python 3 as one option:

```bash
$ python3 -m http.server
```

Run that from the repository root, not from the examples directory, because the bundled examples load files from src. Navigate to the hosted HTML files in a browser and the example panoramas should render. The README notes that example-minified.htm needs a minified copy built first.

For a tiled panorama, the generator runs from the utils/multires directory. With nona already on the system path:

```bash
$ cd utils/multires
$ python3 generate.py pano_image.jpg
```

If nona is elsewhere, the README gives the -n flag to point at it:

```bash
$ cd utils/multires
$ python3 generate.py -n /path/to/nona pano_image.jpg
```

The output lands in ./output by default, as image tiles plus a config.json. To look at the result, go back to the repository root, start the development server again, and open the standalone viewer pointed at the generated configuration:

```bash
$ cd ../..
$ python3 -m http.server
```

```
http://localhost:8000/src/standalone/pannellum.htm#config=../../utils/multires/output/config.json
```

For a deployment you would use a minified copy rather than the src files. The README recommends downloading the most recent release and using the pre-built pannellum.htm, or pannellum.js and pannellum.css, and says the build tools live in utils and require Python 3.2+ and Java. Note that package.json still declares version 2.5.6 while the releases list shows 2.5.7 dated 2026-02-19, so if you install through npm, check which version you actually receive.

## Where Pannellum is the wrong tool

The README draws its own boundary: mobile, app and web frameworks are not officially supported, may work but are not tested, and are not the targeted platform. If your panorama viewer lives inside a React Native or native mobile shell, that sentence should end the evaluation. It is not a statement about a missing feature that a wrapper will fix; it is a statement about what the project tests.

There are softer limits too. The multiresolution path pulls in nona, Pillow, NumPy and optionally pyshtools, which is a heavier toolchain than the 21kB deployment figure suggests, and it sits outside the JavaScript ecosystem entirely. Browser support is a floor, not a ceiling: the README warns that only recent browsers are tested and that regressions in older ones are possible, so a site that must serve old browsers has no guarantee here. And the API documentation is generated from JSDoc comments in the source, which means the reference and the code move together but the prose around it is thinner than the JSON configuration reference in doc/json-config-parameters.md.

## Pannellum against hosted panorama platforms and Three.js

The realistic alternatives fall into two groups. Hosted panorama platforms take the images and the viewer, and give back an embed code; you do not manage tiles, and you also do not control where the imagery lives. Pannellum inverts that: you keep the files, you run the tiling step, and you own the deployment. For anyone with a privacy requirement or an offline intranet, that inversion is the reason to pick it.

The other group is a general WebGL library such as Three.js. There the difference is not hosting but abstraction. Three.js gives you a scene graph and expects you to build the camera, the sphere geometry, the texture loading and the interaction yourself; Pannellum gives you a viewer with a JSON configuration schema, a documented parameter list, and an API for integrations. If you want a panorama inside a larger 3D scene, the general library is the better base. If the panorama is the whole page, Pannellum's configuration file is less code than the equivalent Three.js setup, and the standalone pannellum.htm needs no build step at all.

## Licence, maintenance and the cost of upgrading

Pannellum is MIT licensed, and the COPYING file sits at the repository root alongside a CITATION.cff and a paper directory, so the project is set up to be cited academically as well as reused commercially. MIT is permissive; it does not impose copyleft obligations on your own code. This is not legal advice, and the licence text in COPYING is what governs.

On maintenance, the last push to the default branch was on 2026-07-12, which is recent. The release history is more uneven: 2.5.5 and 2.5.6 landed days apart in November 2019, and 2.5.7 followed on 2026-02-19. That gap is worth knowing before you plan around a steady release cadence. The upgrade cost itself is low for the standalone file, since replacing one HTML file is the whole operation. It is higher if you depend on the API, because the API documentation is generated from JSDoc comments in src and the changelog.md file at the root is where breaking changes would be recorded. Read changelog.md before moving between 2.5.x versions rather than assuming a patch number means no surface change.

## Conclusion

Adopt Pannellum if you need a self-hosted 360 viewer embedded through an iframe or driven by JSON configuration and you can target the desktop browsers the README lists. Do not adopt it if your product is a mobile app or a framework-based mobile build, since the README states those are not officially supported and are not the targeted platform. Before committing, verify two things: that the tiled output of utils/multires/generate.py loads from your own web server, and that the strings configuration parameter covers every user-facing label you need translated.

## FAQ

### How do I use Pannellum to display a single panorama?

Upload build/pannellum.htm and a full equirectangular panorama to a web server, then embed the viewer as an iframe. The README points to the simple tutorial page and its configuration utility for generating the required embed code.

### What are the alternatives to Pannellum?

The documentation does not name a competing viewer. The practical split described by Pannellum's own documentation is between self-hosting the viewer and images, which Pannellum does, and using a general WebGL library such as Three.js, where you assemble the camera, geometry and interaction yourself.

### Can I install Pannellum with npm?

The README's deployment instructions do not use npm; they describe uploading build/pannellum.htm or using the pre-built pannellum.htm, pannellum.js and pannellum.css from a release. A package.json exists with pannellum as the package name, main set to build/pannellum.js, and version 2.5.6, so check which version you get if you do install that way.

### Does Pannellum support mobile apps and frameworks?

No. The README states that mobile, app and web frameworks are not officially supported, that they may work but are not tested, and that they are not the targeted platform.

### How do I create a multiresolution panorama for Pannellum?

Run python3 generate.py pano_image.jpg in the utils/multires directory. This requires the nona program from Hugin plus Python 3 with Pillow and NumPy, and it writes the tiles and a config.json into ./output by default.

### Which browsers does Pannellum support?

The README lists Firefox 40+, Chrome 41+, Safari 9+ and Edge 12+ as full support with appropriate graphics drivers. It adds that the list is based on feature support and that only recent browsers are tested, so older browsers may show regressions.

## Sources

- [License: MIT](https://github.com/mpetroff/pannellum/blob/master/LICENSE)
- [mpetroff/pannellum on GitHub](https://github.com/mpetroff/pannellum)
- [Project website](https://pannellum.org/)
- [README](https://github.com/mpetroff/pannellum/blob/master/README.md)
- [Releases](https://github.com/mpetroff/pannellum/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/mpetroff-pannellum
