At a glance
from tqdm.auto import tqdmdraws a widget in a notebook and a text bar in a terminal.- Runpeek's
from tqdm_live import tqdmdraws the text bar in the cell and shows it live on your phone, with no ipywidgets needed. IProgress not foundmeans ipywidgets is missing from the kernel's environment: run%pip install ipywidgets, then restart the kernel.tqdm.notebookalways builds a widget; in a plain terminal it prints one static 0% line.- Text bars nest badly in notebook output; widget bars nest cleanly.
Use tqdm.auto in notebooks
Import tqdm from tqdm.auto instead of the base package. In Jupyter Notebook, JupyterLab and VS Code notebooks, tqdm.auto gives you the ipywidgets bar, and when you run the same script in a terminal it gives you the normal text bar, so you don't have to change your imports when moving code between a notebook and a .py file.
from time import sleep
from tqdm.auto import tqdm
for row in tqdm(range(200), desc="rows"):
sleep(0.01)You'll also see from tqdm.notebook import tqdm and from tqdm.autonotebook import tqdm in older code. tqdm.notebook always builds the widget, so in a plain terminal it prints a single static 0% line instead of a live bar. tqdm.autonotebook works like tqdm.auto but prints a TqdmExperimentalWarning in notebooks; tqdm.auto avoids that warning.
The widget bar changes colour to show its state:
- Blue while the loop is running.
- Green when the loop finishes.
- Red if the loop stops on an exception or keyboard interrupt. The notebook bar doesn't close itself when that happens, so it stays red in the cell output.
- Light blue when there's no
totaland no ETA.
To change the width of the widget bar, pass an integer: ncols=480 makes it 480 pixels wide. tqdm's README also shows strings such as ncols="100%", but in tqdm 4.70.1 those raise a TypeError (open tqdm issue #1533).
Follow a notebook run from your phone
Runpeek streams a notebook's progress bar to a link you can open anywhere, so you can walk away from a long run. In our test on 2026-10-30, from tqdm_live import tqdm drew the text bar in the cell and printed a runpeek ▶ https://runpeek.app/b/<uuid> link showing the live bar in a browser, no account needed.
The kernel stays alive after a cell finishes, so a few things work differently than in a script:
- Call
tqdm_live.start_run("name")to group every bar under a single/r/link. The run stays open until you shut the kernel down, which marks it finished. - An exception inside a cell doesn't mark the run as failed on its own: in our test the run kept going after the traceback and later ended as finished. Catch the error and call
tqdm_live.end_run("failed", exit_code=1)if you want failures reported right away. - After
start_run,tqdm_live.notify(url, stall_after_minutes=10)sends an alert to a Discord, Slack or other webhook URL when no update arrives for 10 minutes while the run is open. An idle kernel after the loop counts too, so shut the kernel down when the work is done.
Fix "IProgress not found"
When ipywidgets isn't installed in your kernel, tqdm.notebook raises an ImportError:
IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html
If you're using tqdm.auto without ipywidgets, it won't crash: it shows the same message as a TqdmWarning and falls back to the text bar. Either way, the fix is to install ipywidgets into the same environment that your Jupyter kernel is running.
%pip install ipywidgetsUsing %pip inside a notebook cell guarantees the package goes into the active kernel's environment. You can also run pip install "tqdm[notebook]" in a terminal inside that same environment, which pulls in ipywidgets>=6. Once the install finishes, restart the kernel so tqdm picks up the widget classes; if the bar still doesn't draw in JupyterLab, reload the browser tab.
JupyterLab, VS Code, QtConsole and Spyder
tqdm.auto makes its choice inside the kernel. Code running in an IPython kernel gets the widget bar, unless tqdm spots QtConsole or Spyder through the QT_API or SPYDER* environment variables or the shell's class name. A plain ipython terminal gets the text bar. Beyond that, the kernel can't tell which frontend is attached, so the frontend has to render the widget:
- Jupyter Notebook and JupyterLab: installing
ipywidgetsin the kernel's environment also installsjupyterlab_widgets, which sets up the frontend. If JupyterLab runs in a different environment from the kernel, installjupyterlab_widgetswhere JupyterLab runs andipywidgetsin each kernel's environment. - VS Code: the Jupyter extension renders widgets by downloading their scripts from jsDelivr or unpkg, set by
jupyter.widgetScriptSources. If those sites are blocked, the widget may not render. - QtConsole and Spyder: since tqdm 4.68.3,
tqdm.autodetects these and gives them the text bar, because they don't renderipywidgets. The same release added JupyterLite detection. - jupyter console: it runs the same kernel as a notebook, so in our test
tqdm.autostill picked the widget bar, which a terminal can't draw. Usefrom tqdm import tqdmthere.
Nested bars and reusing a bar across cells
For nested loops, wrap both the outer and inner iterables with tqdm. Pass leave=False on the inner bar if you want it to disappear each time the inner loop finishes instead of leaving a stack of green bars behind.
from time import sleep
from tqdm.auto import tqdm, trange
for epoch in trange(3, desc="epochs"):
for batch in tqdm(range(100), desc="batches", leave=False):
sleep(0.005)By default, a widget bar appears in the output of whichever cell created it. If you create a bar in one cell and update it in a later cell, the updates still happen back up in the first cell's output.
To control where the bar renders, create it with display=False, then call display(pbar.container) from IPython.display in the cell where you actually want it to show up. You can also reuse that same bar across multiple loops or cells by calling pbar.reset(total=...) instead of creating a new one each time.
from tqdm.notebook import tqdm
pbar = tqdm(total=100, desc="shared", display=False)
# in a later cell
from IPython.display import display
display(pbar.container)
for _ in range(100):
pbar.update(1)
# reuse the same bar for the next loop
pbar.reset(total=50)Widget bar or text bar
When widgets won't render in your environment, from tqdm import tqdm is the fallback. It prints the plain text bar into the cell output without needing ipywidgets. JupyterLab's output area handles the carriage return the bar uses to redraw its line, but it doesn't handle the cursor-up codes that nested text bars need, so nested text bars leave extra lines behind.
| Import | In a notebook | In a terminal | Without ipywidgets |
|---|---|---|---|
Runpeek: from tqdm_live import tqdm | Text bar plus a live link | Text bar plus a live link | Text bar plus a live link |
from tqdm.auto import tqdm | Widget bar | Text bar | Text bar plus a warning |
from tqdm.notebook import tqdm | Widget bar | One static line | ImportError |
from tqdm.autonotebook import tqdm | Widget bar plus a warning | Text bar | Text bar plus a warning |
from tqdm import tqdm | Text bar | Text bar | Text bar |
FAQ
Why does tqdm print a new line for every update in my notebook?
Notebook output areas redraw a single text bar with a carriage return, but they can't move the cursor up, so nested or parallel text bars print extra lines. Switch your import to from tqdm.auto import tqdm and install ipywidgets with %pip install ipywidgets, so tqdm uses the notebook widget instead of text.
What is the difference between tqdm.notebook and tqdm.auto?
from tqdm.notebook import tqdm always builds an ipywidgets bar: it raises the IProgress not found error when ipywidgets is missing and prints only one static line in a terminal. from tqdm.auto import tqdm uses the widget in notebook frontends and the text bar in plain Python or IPython terminals, QtConsole and Spyder, or when ipywidgets is missing.
Why is my bar showing in the wrong cell?
A notebook widget bar renders in the cell where the tqdm object was created, even if you call .update() on it in a cell further down. To make it appear in a different cell, create the bar with display=False and then call display(pbar.container) inside the cell where you want it to show.
How do I add a progress bar to pandas in a notebook?
Import tqdm from tqdm.auto, call tqdm.pandas(), and then use .progress_apply() instead of .apply() on your DataFrame or Series. Because you registered tqdm from tqdm.auto, pandas uses the ipywidgets bar in the notebook output.
Are tqdm.notebook widget bars streamed to Runpeek?
No. Runpeek streams standard tqdm text bars, and the widget bars from tqdm.notebook and from tqdm.auto inside a notebook are not sent. Use from tqdm_live import tqdm in the notebook instead; it shows the text bar in the cell and prints the browser link.
Check on long runs from your phone
Change one import and every tqdm bar prints a link you can open on any device. Get a Discord or Slack message when the run finishes, fails or stalls.
pip install tqdm-liveSources
- tqdm README: IPython/Jupyter integration github.com
- tqdm on PyPI pypi.org
- tqdm issue #1533: string ncols raises TypeError github.com
- ipywidgets installation guide ipywidgets.readthedocs.io
- ipywidgets on PyPI pypi.org
- VS Code Jupyter extension: widget support github.com
- JupyterLab output area stream handling github.com
- tqdm 4.68.3 release notes github.com