cheat sheet
jupyter
Package-level reference for the jupyter meta-package on PyPI — install variants, what it pulls in, version policy, and alternatives.
jupyter
What it is
jupyter is the historical meta-package on PyPI that pulls in the full Jupyter notebook stack: the IPython kernel, the classic Notebook web interface, nbconvert, qtconsole, and supporting libraries. It is maintained by Project Jupyter, a NumFOCUS-sponsored umbrella organization.
The Jupyter ecosystem has since split into many independently-versioned packages — jupyterlab, notebook, ipykernel, nbclient, nbconvert, jupyter-server — and most modern installs prefer jupyterlab directly. Reach for the jupyter meta-package only when you want the classic Notebook + qtconsole experience bundled together; reach for jupyterlab for the modern IDE-like interface, or just ipykernel if you only need the kernel for an external editor like VS Code.
Install
pip install jupyterlab # recommended modern install
Output: (none — exits 0 on success)
pip install jupyter # legacy meta-package (classic Notebook + qtconsole)
Output: (none — exits 0 on success)
uv add jupyterlab
Output: resolved + added to pyproject.toml
pipx install jupyterlab # global, isolated install for ad-hoc use
Output: installs jupyter-lab on PATH in a dedicated venv
conda install -c conda-forge jupyterlab
Output: preferred for ML/data-science envs where conda solves CUDA + Python + JupyterLab together.
Versioning & Python support
- The
jupytermeta-package itself is on a slow major-release cadence (currently1.x); the components it depends on each have their own faster cycles. jupyterlabis on the4.xseries as of late 2025, with monthly minor releases.notebookwas rewritten on top ofjupyter-serverfor its7.xline — the old5.x/6.x"classic Notebook" is a separate code path.- Python 3.9+ supported across the active component matrix.
- Loose semver, with notable historic ecosystem breaks (the
nbformatv4 schema bump, thenotebook6 → 7 rewrite).
Package metadata
- Maintainer: Project Jupyter (NumFOCUS fiscally sponsored)
- Project home: github.com/jupyter/jupyter (meta-repo)
- Docs: docs.jupyter.org · jupyterlab.readthedocs.io
- PyPI: pypi.org/project/jupyter · pypi.org/project/jupyterlab
- License: BSD-3-Clause
- Governance: Project Jupyter steering council
- First released: 2015 (Project Jupyter); IPython notebook dates to 2011
- Downloads: tens of millions per month across the ecosystem —
jupyterlabandnotebookboth in the PyPI top 100
Optional dependencies & extras
jupyter is itself a thin meta-package — its value is the dependency tree it pulls in. Key components:
ipykernel— the Python kernel; required by every notebooknotebook— the classic web interface (now in7.x, built onjupyter-server)jupyterlab— the modern web IDEnbconvert— convert.ipynbto HTML, PDF, Markdown, slidesnbformat— the on-disk.ipynbschemaqtconsole— Qt-based REPL with rich outputjupyter-console— terminal REPLjupyter-server— the HTTP server shared bynotebook7 andjupyterlab
Common companions (install separately):
ipywidgets— interactive widgets (sliders, dropdowns) inside cellsjupytext— pair.ipynbnotebooks with.py/.mdfor clean git diffsnbstripout— git filter that strips notebook outputs on commitjupyterlab-git,jupyterlab-lsp,jupyterlab-vim— JupyterLab extensionsvoila— turn a notebook into a standalone dashboardpapermill— parameterize and execute notebooks programmatically
Alternatives
| Package | Trade-off |
|---|---|
jupyterlab | The modern interface. Install this directly unless you specifically want the legacy meta-bundle. |
notebook | Classic single-document interface (7.x rebuild). Lighter than JupyterLab. |
marimo | Reactive notebook with a dependency graph; cells re-run automatically. Reproducibility-first design. |
nbterm | Notebook UI inside a terminal — no browser. |
vscode + Python extension | Run .ipynb files in VS Code directly via ipykernel. Skip Jupyter's web UI entirely. |
colab / kaggle | Hosted Jupyter with free GPUs; no local install. |
Common gotchas
jupytervsjupyterlabvsnotebook. Installing the meta-packagejupyterbrings the classic Notebook stack but not JupyterLab. Most users wantpip install jupyterlab. Thejupytercommand (jupyter notebook,jupyter lab,jupyter console) is what's shared.- Kernel-spec leaks across venvs.
ipykernelregisters a kernel by name globally in~/Library/Jupyter/kernels(macOS) or~/.local/share/jupyter/kernels(Linux). If you create a new venv andpip install ipykernel, the kernel namepython3may still point at the old venv. Register explicitly:python -m ipykernel install --user --name myproject --display-name "Py 3.12 (myproject)". - Browser launch fails on remote / headless hosts.
jupyter labtries to open a browser; on a headless server it just hangs. Pass--no-browser --ip=0.0.0.0and copy the token URL from the terminal. - Classic Notebook 6 vs 7 are different code paths. Extensions written for Notebook 6 do not work in Notebook 7. Both pin to incompatible
nbclassic/jupyter-serverranges. If you must stay on 6, pin:pip install "notebook<7". pip install jupyterdoes not install JupyterLab extensions. Extensions are themselves PyPI packages (jupyterlab-git,jupyterlab-lsp); install them separately and restartjupyter labto discover them..ipynbfiles contain output + metadata that pollutes git diffs. Withoutnbstripoutorjupytext, every cell re-run produces a noisy commit. Configure one of them per-repo.- Output cells can contain MBs of base64 PNGs. Notebooks accidentally committed with large embedded images bloat the repo permanently. Add a pre-commit hook with
nbstripoutto strip on commit.
Real-world recipes
These are package-level recipes — install layout, kernel management, deployment. For magic commands, widgets, and notebook-internal API see the companion Python article.
Recipe 1 — one kernel per project virtualenv
The canonical multi-project layout: one venv per project, each registered as its own kernel.
cd ~/projects/analytics
python -m venv .venv
source .venv/bin/activate
pip install ipykernel jupyterlab pandas matplotlib
python -m ipykernel install --user \
--name analytics \
--display-name "Py 3.12 — analytics"
Output: kernel registered at ~/.local/share/jupyter/kernels/analytics/kernel.json (Linux) or ~/Library/Jupyter/kernels/analytics/ (macOS). The kernel JSON points at the venv's python — so any JupyterLab instance can launch this kernel.
List kernels:
jupyter kernelspec list
Output:
Available kernels:
analytics /home/alice/.local/share/jupyter/kernels/analytics
python3 /home/alice/.local/share/jupyter/kernels/python3
Recipe 2 — execute a parametrised notebook from CI with papermill
pip install papermill
papermill report.ipynb out.ipynb -p month "2026-05" -p region us-east
Output: out.ipynb is the notebook executed with month and region cell variables substituted. Combined with nbconvert, this is the canonical "scheduled report" pipeline.
jupyter nbconvert out.ipynb --to html --output report-2026-05.html
Output: standalone HTML — drop into any static-file host.
Recipe 3 — pair .ipynb with .py for clean git diffs
pip install jupytext
jupytext --set-formats ipynb,py:percent notebook.ipynb
Output: every save in JupyterLab writes both notebook.ipynb (full, for execution) and notebook.py (text, for diffing/reviewing). Commit the .py; gitignore the .ipynb if you don't need cached outputs.
Recipe 4 — strip outputs on commit with nbstripout
pip install nbstripout
nbstripout --install # configures git to filter notebooks on commit
Output: every git add of a .ipynb runs the filter and strips outputs, execution_count, and runtime metadata. The on-disk file is unchanged — only the staged copy is clean.
Recipe 5 — turn a notebook into a runtime artifact via nbconvert
# Static HTML (the most useful default)
jupyter nbconvert analysis.ipynb --to html
# Self-contained slides for a talk
jupyter nbconvert talk.ipynb --to slides --post serve
# Convert to a runnable .py
jupyter nbconvert analysis.ipynb --to script
Output: analysis.html, a live RevealJS slide deck on http://localhost:8000, and analysis.py respectively.
Production deployment
The Jupyter ecosystem has three distinct production modes — pick before you start.
Single-user remote server
For one developer's remote box, jupyter lab with a token + reverse proxy:
jupyter lab \
--no-browser \
--ip=127.0.0.1 \
--port=8888 \
--ServerApp.token="$(openssl rand -hex 32)" \
--ServerApp.allow_origin='https://lab.example.com'
Output: server bound to localhost only; expose via SSH tunnel or a reverse proxy that adds TLS. Never expose 0.0.0.0 without TLS and a strong token.
Nginx fragment for proxy + WebSocket upgrade:
location / {
proxy_pass http://127.0.0.1:8888;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
Output: WebSocket-aware proxy; Upgrade header is required — without it kernels can't talk to the browser.
Multi-user — JupyterHub
For shared infrastructure (university lab, research team), use JupyterHub rather than rolling per-user jupyter lab instances. JupyterHub provides:
- Login authentication (PAM, OAuth, LDAP, Shibboleth)
- Per-user notebook server spawning (LocalProcessSpawner, DockerSpawner, KubeSpawner)
- Resource isolation per user (cgroups, container limits)
- A central admin UI
Minimal install:
pip install jupyterhub jupyterlab
npm install -g configurable-http-proxy
Output: jupyterhub on PATH. Generate a default config: jupyterhub --generate-config. Production deployments almost always run JupyterHub in Docker or Kubernetes — the jupyterhub/k8s-hub Helm chart is the standard path.
Containerised single-user — Docker
The community-maintained jupyter/datascience-notebook image is the reference for a containerised JupyterLab:
docker run -p 8888:8888 \
-v "$PWD":/home/jovyan/work \
jupyter/datascience-notebook:latest
Output: JupyterLab on http://localhost:8888?token=<printed-on-stdout>. The jovyan user is the convention (named after Jupiter's moons). The bind mount maps the current directory to the in-container workspace.
For reproducible builds, fork the image, pin Python + library versions in a requirements.txt, and bake the kernel registration into the Dockerfile.
Performance tuning
Auto-reload for iterative development
%load_ext autoreload
%autoreload 2
Output: every imported module is re-imported on every cell execution. Saves the "restart kernel after every edit" loop — at the cost of a small per-cell overhead and occasional stale references.
Kernel startup time
ipykernel's default startup loads matplotlib's font cache and pandas type machinery — ~1-2 s. For a long-lived JupyterLab session this is invisible; for short-lived papermill runs it's ~50% of the total. To shave it:
- Avoid
from pandas import *at notebook top; import lazily inside the cell that needs pandas. - Pre-warm in a Docker base image with a one-time
python -c "import pandas, matplotlib"build step.
Big-output cells
A cell that streams 100 MB of text to stdout will bog down JupyterLab — the frontend keeps the whole output in memory. Use tqdm for progress (one updating line) instead of print per row.
jupyter-cache for notebook re-execution
pip install jupyter-cache
jcache notebook add notebook.ipynb
jcache project execute # only re-executes cells whose inputs changed
Output: cells with unchanged source are skipped on re-execution — the canonical fast path for nbconvert-based publishing pipelines (Quarto, JupyterBook, MyST).
Version migration guide
Classic Notebook 6 → 7
The 7.0 release rewrote the classic Notebook UI on top of jupyter-server and JupyterLab components. The user-facing layout is similar; the extension API is entirely different. Extensions written for 6.x must be ported to 7.x — there is no shim. To stay on 6.x temporarily:
pip install "notebook<7"
Output: classic notebook frozen on the 6.x line; security fixes still backported but no new features.
JupyterLab 3 → 4
JupyterLab 4 (2023) moved the build system from webpack to esbuild and pre-bundled extensions — most extensions no longer require a node build step at install time.
jupyter labextension install <name>(the pre-4.0 path) is gone; usepip install jupyterlab-<name>for the pip-distributed extension.- The CSS variable system was reorganised; custom themes need updating.
- Old "source extension" projects need to be rebuilt as "prebuilt extensions".
nbformat v4 → v4.5
The on-disk schema added cell IDs (so cells can be referenced even after reordering). Tools that emit .ipynb (papermill, jupytext, Jupyter itself) emit v4.5; readers should accept both.
Python floor moves
Each Jupyter ecosystem release tracks the SPEC 0 timeline — Python ~3 years after release, NumPy ~2 years. As of late 2025 the active matrix is Python 3.10+; older Python pins force older Jupyter components.
Security considerations
Jupyter servers are remote-code-execution platforms by design — the threat model is more like SSH than like a CMS.
Authentication
- Token (default) — random 48-char token printed at server start. Sufficient for SSH-tunnelled single-user usage. Never disable the token on a network-reachable port.
- Password —
jupyter server passwordstores a hashed password injupyter_server_config.json. Browser-friendly for single-user remote. - Identity providers — JupyterHub supports OAuth (GitHub, Google), LDAP, SAML, JWT. Production multi-user setups must use one of these, not the token.
Kernel sandboxing
The kernel runs arbitrary Python with the same OS privileges as the server process. A single-user server is therefore "exec as the user that started it". To isolate untrusted users:
- Per-user containers — DockerSpawner / KubeSpawner. Each user gets a fresh container; kernel crash or fork-bomb doesn't affect others.
- Resource limits —
--ResourceUseDisplay.mem_limit=4Gshows a memory bar to the user; combine with cgroups for hard enforcement. - No-network spawners — drop the kernel's outbound network entirely for sensitive data.
Notebook trust
Notebooks store outputs that may include HTML and JavaScript. Jupyter treats notebooks as "untrusted" by default — JS in outputs is stripped on display. The trust state is per-signature; modifications invalidate the signature. Do not flip trust on for notebooks downloaded from the web.
Header hardening
For internet-facing JupyterHub or proxied Jupyter, set CSP and X-Frame-Options:
# jupyter_server_config.py
c.ServerApp.tornado_settings = {
"headers": {
"Content-Security-Policy": "frame-ancestors 'self'",
"X-Content-Type-Options": "nosniff",
}
}
Output: strict CSP; iframe-embedded JupyterLab requires explicit allowlisting.
Compatibility matrix
| Component | Recent stable | Python floor | Notes |
|---|---|---|---|
jupyterlab | 4.x | 3.10 | Prebuilt extensions; esbuild |
notebook | 7.x | 3.10 | Rewritten on top of jupyter-server |
notebook (classic) | 6.5.x | 3.7 | Maintenance-only; pin notebook<7 |
jupyter-server | 2.x | 3.9 | Shared HTTP/WebSocket layer |
ipykernel | 6.x | 3.9 | The Python kernel |
ipython | 9.x | 3.11 | REPL; some Jupyter components still depend on it |
nbformat | 5.x | 3.8 | On-disk schema (v4.5 cell IDs) |
nbconvert | 7.x | 3.8 | Export to HTML/PDF/slides |
Always install the components together — mixing jupyterlab 4.x with notebook 5.x will produce confusing extension-loading errors. pip install -U jupyterlab is usually enough to pull a consistent set.
Ecosystem integrations
- VS Code — the Python extension's "Jupyter" feature runs
.ipynbfiles using onlyipykernel. Skip JupyterLab entirely if you prefer VS Code. - PyCharm Professional — native notebook editor; uses the project's Python interpreter as the kernel.
papermill— parametrised notebook execution. The standard CI-friendly path.jupytext— pair.ipynbwith.py/.md/.Rmdfor diffable source.nbstripout— git filter that strips outputs on commit.jupyter-cache— incremental notebook re-execution for publishing pipelines.nbval—pytestplugin that re-executes a notebook and compares outputs as a test.voila— turn a notebook into a standalone web app (no code cells visible).quarto— scientific publishing tool that ingests.ipynband renders HTML/PDF/EPUB.JupyterBook/MyST— multi-notebook book/site builders.google-colab— Google's hosted Jupyter with free GPU; uses Jupyter's protocols but is a fork of the frontend.kaggle-notebooks— Kaggle's hosted variant; similar protocol-level compatibility.
When NOT to use this
- Production code paths. Notebooks are exploratory tools — not deployment artefacts. Extract the code into a
.pymodule, write tests, and import the module from the notebook for prototyping. Runningpapermillin production is fine for reports, not for services. - Long-lived background jobs. A kernel pinned to a browser tab is not a job runner. Use Airflow, Prefect, or plain cron + a Python script.
- Source-controlled multi-developer collaboration on the same file.
.ipynbmerge conflicts are a recurring source of pain even withjupytextandnbstripout. Pair with a per-feature notebook convention or use a real IDE. - Strict reproducibility. Cells can be executed out of order; "Restart kernel and run all" is the only reproducible mode and is easy to forget. For reproducibility-first workflows, consider
marimo(cells form a DAG and re-run automatically). - Tight performance loops. The kernel's I/O round-trip adds ~1 ms per cell; that's invisible in interactive use but disqualifying for inner loops. Run hot code in
.pyfiles.
See also
- Python: jupyter — keyboard shortcuts, magics, nbconvert workflows
- Packages: pip-matplotlib — the canonical inline-plotting partner
- Packages: pip-tqdm — progress bars that work in both terminal and notebook