HtmlDownloader - Download a page from the command line and from the text menu
HtmlDownloader downloads one HTML page and the stylesheets, scripts, and images that page links to. The typed verb download saves that page. Menu row 1 download lists pages saved earlier, or accepts a URL. Menu row 2 list downloaded lists saved page names, then opens the chosen page in Visual Studio Code or the default browser.
On a terminal, starting it with no arguments opens a text menu. The menu does not download a page by itself, and it does not call pip. It does not join media, call an external encoder, or list files in the folder.
Features
- Text menu on a terminal: download, list downloaded, serve, System Log, self-management, language, and Exit
- The first row shows the current folder and a local clock (
HH:MM:SS) when the row has room - Numbered rows line up. A rounded input box sits along the bottom, as wide as the terminal, with the name and version on the status line under the box
- download (1) lists saved
page name: URLpairs, or accepts a URL and a page name. The typed verbdownload --url URL --name PAGENAMEsaves the page and does not draw the menu. A later run keepsindex.htmland fills in files that are still missing - list downloaded (2) lists saved page names by number. After a page is chosen, 21 edit opens
index.htmlin Visual Studio Code when thecodecommand or the Visual Studio Code desktop entry is installed, and 22 view opens it in the default browser when one is set. A missing tool is left off that menu. 0 returns to the page list, then to the main menu - serve (3) lists saved page names by number, then asks for a port. An empty port uses 5000. The page folder is served at
http://127.0.0.1:<port>/until Ctrl+C. The typed verbserve --page-name PAGENAMEdoes the same without the menu.--portchanges the port - The page is
~/.app/HtmlDownloader/output/<pagename>/index.html. Linked stylesheets go inoutput/<pagename>/assets/css/. Linked scripts go inoutput/<pagename>/assets/js/. Linked images go inoutput/<pagename>/assets/img/. Those three folders stay flat, with no subfolders. Font files sit inassets/css/. Whenindex.htmlis already there, the page is not downloaded again. Missing stylesheets, scripts, and images are fetched. Files already saved are kept. - System Log (4) opens view-log, clear-log, and log-folder. self-management (6) opens version, about, and the pip lifecycle rows. language (7) picks the menu language
- Console script
html-downloaderand module entrypython -m HtmlDownloader - Typed verbs:
help,version,about,download,serve,self-install,version-check,self-update,self-uninstall
Advantages
- Two ways to download.
html-downloader download --url URL --name PAGENAMEsaves the page in the terminal and does not draw the menu. On the menu, row 1 download lists saved pages by number, or accepts a URL. With no arguments on a terminal, the text menu opens and waits. With no terminal and no verb, the program prints help and returns 0. There is no--json. - Built-in languages. Row 7 lists thirteen languages: English, Simplified Chinese, Traditional Chinese, Spanish, Arabic, French, Portuguese, Russian, German, Japanese, Korean, Dutch, and Greek. The choice is saved in
~/.local/HtmlDownloader/languagefor the next run.HTMLDOWNLOADER_LANGoverrides that file for one process and does not write it. The download verb stays English. The note on row 1 follows the menu language. - Lifecycle and diagnostics.
version-check,self-update,self-install, andself-uninstallare menu rows 63–66 and typed verbs.self-uninstallon the command line needs--force. They call pip and do not use root. System Log (4) views a log, clears a log, and shows the log folder. about (62) stays in English.
Quick Installation
Python dependency: ChronicleLogger>=1.3.1 (required). Pip installs it with HtmlDownloader. No external media tool is required.
PyPI (registry)
pip install HtmlDownloader
This installs the console entry html-downloader and the package HtmlDownloader. Packaging name SSOT is pyproject.toml [project].name = HtmlDownloader. This tree is 1.0.0. The PyPI badge above shows the live index.
Local install (checkout)
From a checkout (editable / unreleased work):
git clone https://github.com/cloudgen/HtmlDownloader.git
cd HtmlDownloader
python3 -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -e .
Main menu
After install, on a terminal, html-downloader with no arguments prints this screen. The verb is bold and the note after the colon is italic. 9 leaves. 0 on a submenu goes back. After a command finishes, the main menu is shown again. A number that is not on the list prints an error and lets you choose again.
Picture of the English menu. Current directory /tmp/clips. The rows are the text the menu paints. The frame is the 80-column box.
$ html-downloader
Path: /tmp/clips 12:06:45
1. **download** : *download a page and its stylesheets, scripts, and images*
2. **list downloaded**: *show saved page names*
3. **serve** : *serve a saved page on this computer*
4. **System Log** : *view, clear, and the log folder*
6. **self-management**: *version, about, and pip lifecycle*
7. **language** : *display language for this menu*
9. **Exit** : *leave*
╭─────────────────────────────────────────────────────────────────────────────╮
│ > │
╰─────────────────────────────────────────────────────────────────────────────╯
HtmlDownloader 1.0.0 │ main menu │ Up/Down • Enter
System Log (4). Numbers 44–49 are not printed.
Path: /tmp/clips 12:06:45
41. **view-log** : *list a log file and show it*
42. **clear-log** : *empty one log file*
43. **log-folder**: *show the log folder*
0. **Back** : *return to the main menu*
╭─────────────────────────────────────────────────────────────────────────────╮
│ > │
╰─────────────────────────────────────────────────────────────────────────────╯
HtmlDownloader 1.0.0 │ System Log │ Up/Down • Enter
language (7). The short on each language row is that language’s own name. Numbers 84–98 are not printed. 0 goes back and does not save.
Path: /tmp/clips 12:06:46
71. **English** : *use English for this menu*
72. **简体中文** : *use 简体中文 for this menu*
73. **繁體中文** : *use 繁體中文 for this menu*
74. **Español** : *use Español for this menu*
75. **العربية** : *use العربية for this menu*
76. **Français** : *use Français for this menu*
77. **Português** : *use Português for this menu*
78. **Русский** : *use Русский for this menu*
79. **Deutsch** : *use Deutsch for this menu*
80. **日本語** : *use 日本語 for this menu*
81. **한국어** : *use 한국어 for this menu*
82. **Nederlands**: *use Nederlands for this menu*
83. **Ελληνικά** : *use Ελληνικά for this menu*
0. **Back** : *return to the main menu*
╭─────────────────────────────────────────────────────────────────────────────╮
│ > │
╰─────────────────────────────────────────────────────────────────────────────╯
HtmlDownloader 1.0.0 │ language │ Up/Down • Enter
self-management (6). Numbers 67–70 are not printed.
Path: /tmp/clips 14:05:09
61. **version** : *show the installed version*
62. **about** : *version and this computer*
63. **version-check** : *compare this install with pip*
64. **self-update** : *upgrade this package with pip*
65. **self-uninstall**: *remove this package with pip*
66. **self-install** : *install this package with pip*
0. **Back** : *return to the main menu*
╭─────────────────────────────────────────────────────────────────────────────╮
│ > │
╰─────────────────────────────────────────────────────────────────────────────╯
HtmlDownloader 1.0.0 │ self-management │ Up/Down • Enter
Choose a number, or type the command name in the box. The block caret appears in that box while it is focused.
Usage
html-downloader
# or
python -m HtmlDownloader
On a terminal, that opens the main menu above. It does not download a page yet, and it does not call pip. With no terminal, the same command prints help and returns 0.
download (1) stays on the menu. It lists saved page name: URL rows. Type a number to download that pair again, or type an http:// or https:// URL and then a page name. The typed verb does not draw the menu:
html-downloader download --url https://example.com/ --name example
That writes ~/.app/HtmlDownloader/output/example/index.html, puts linked stylesheets in output/example/assets/css/, linked scripts in output/example/assets/js/, and linked images in output/example/assets/img/. Each of those folders is a single layer. The saved page points at those local files. A <base> tag or an xml:base attribute is removed so local links stay on the saved page. A canonical link and HTML comments are removed too. The pair is remembered in ~/.app/HtmlDownloader/output/url-map.json. Running the same command again leaves index.html in place and downloads only the stylesheets, scripts, and images that are not already in the page folder.
list downloaded (2) lists those page names by number. Choose one, then 21 edit opens index.html in Visual Studio Code when code is installed, and 22 view opens it in the default browser when a default browser is set. If either tool is missing, that row is not shown. 0 goes back.
serve (3) lists those page names by number. Choose one, then type a port. Press Enter with an empty box to use 5000. The server listens on 127.0.0.1 and stops on Ctrl+C. The menu then shows Stopped <name>. The typed verb does not draw the menu:
html-downloader serve --page-name example
html-downloader serve --page-name example --port 8080
That serves ~/.app/HtmlDownloader/output/example/ so http://127.0.0.1:5000/ is index.html and assets/ stays beside it.
html-downloader help
html-downloader version
html-downloader about
html-downloader download --url https://example.com/ --name example
html-downloader serve --page-name example
html-downloader version-check
html-downloader self-update
html-downloader self-install
html-downloader self-uninstall --force
version prints HtmlDownloader 1.0.0 and does not call pip. about shows one English page: the product identity, a host check of this computer, and a star box. It does not call pip. download saves the page and does not draw the menu. help prints usage.
version-check runs python -m pip index versions HtmlDownloader. self-update runs python -m pip install --upgrade HtmlDownloader. self-install runs python -m pip install HtmlDownloader. self-uninstall runs python -m pip uninstall -y HtmlDownloader and needs --force on the command line. Those pip verbs do not use sudo. Empty arguments do not install or update.
Exit codes: non-zero for an unknown verb, a failed download, a failed serve, a pip failure, or a menu that cannot open. Menu Exit (9) returns 0. A saved page returns 0. Ctrl+C on serve returns 0.
Import for scripts (thin entry):
from HtmlDownloader import main
# interactive session; a terminal opens the text menu
Screenshots
Each heading is the file name. The paragraph is what that picture shows: the words on the screen and the characters in the input box. Package 1.0.0. These pictures were captured from the running text menu in /tmp/clips. On each menu picture the input box shows > and no typed text, and 1 download or the first row of that board is highlighted. The package index can fetch a picture only after that file is on the public main branch.
language-menu.png
Row 7 has opened the language list. 71 English is highlighted, with the note "use English for this menu." The other rows are 72 简体中文, 73 繁體中文, 74 Español, 75 العربية, 76 Français, 77 Português, 78 Русский, 79 Deutsch, 80 日本語, 81 한국어, 82 Nederlands, and 83 Ελληνικά. Each note says to use that language for this menu. 0 Back says "return to the main menu." The path label is Path. The path is /tmp/clips. The clock is 19:48:09 on the right of that row. The status line says HtmlDownloader 1.0.0 and language.
main-menu-en.png
English main menu. There is no saved-language line above the box. The path label is Path. The path is /tmp/clips. The clock is 19:48:12 on the right of that row. 1 download is highlighted: "download a page and its stylesheets, scripts, and images." Then 2 list downloaded "show saved page names," 3 serve "serve a saved page on this computer," 4 System Log "view, clear, and the log folder," 6 self-management "version, about, and pip lifecycle," 7 language "display language for this menu," and 9 Exit "leave." The status line says HtmlDownloader 1.0.0 and main menu.
main-menu-zh-hans.png
Simplified Chinese main menu. The line above the box says 菜单语言是简体中文. The path label is 路径. The path is /tmp/clips. The clock is 19:48:14 on the right of that row. 1 download is highlighted and stays download: "下载页面、样式表和脚本." 2 stays list downloaded. 3 stays serve. 4 is 系统日志. 6 is 自我管理. 7 is 语言. 9 is 离开. The status line says HtmlDownloader 1.0.0 and 主菜单.
main-menu-zh-hant.png
Traditional Chinese main menu. The line above the box says 選單語言是繁體中文. The path label is 路徑. The path is /tmp/clips. The clock is 19:48:17 on the right of that row. 1 download is highlighted and stays download: "下載頁面、樣式表和指令碼." 2 stays list downloaded. 3 stays serve. 4 is 系統日誌. 6 is 自我管理. 7 is 語言. 9 is 離開. The status line says HtmlDownloader 1.0.0 and 主選單.
main-menu-es.png
Spanish main menu. The line above the box says El idioma del menú es español. The path label is Ruta. The path is /tmp/clips. The clock is 19:48:19 on the right of that row. 1 download is highlighted and stays download: "descarga una página, sus hojas de estilo y sus scripts." 2 stays list downloaded. 3 stays serve. 4 is registro. 6 is autogestión. 7 is idioma. 9 is Salir. The status line says HtmlDownloader 1.0.0 and menú principal.
main-menu-ar.png
Arabic main menu. The line above the box says لغة القائمة هي العربية. The path label is المسار. The path is /tmp/clips. The clock is 19:48:22 on the right of that row. The numbers stay on the left. Arabic words on each row are shaped and read right to left. 1 download is highlighted and stays download. 2 stays list downloaded. 3 stays serve. 4 is سجل النظام. 6 is إدارة ذاتية. 7 is لغة. 9 is خروج. The status line says HtmlDownloader 1.0.0 and القائمة الرئيسية.
main-menu-fr.png
French main menu. The line above the box says La langue du menu est le français. The path label is Chemin. The path is /tmp/clips. The clock is 19:48:24 on the right of that row. 1 download is highlighted and stays download: "télécharger une page, ses feuilles de style et ses scripts." 2 stays list downloaded. 3 stays serve. 4 is journal. 6 is autogestion. 7 is langue. 9 is Quitter. The status line says HtmlDownloader 1.0.0 and menu principal.
main-menu-pt.png
Portuguese main menu. The line above the box says O idioma do menu é português. The path label is Caminho. The path is /tmp/clips. The clock is 19:48:27 on the right of that row. 1 download is highlighted and stays download: "transferir uma página, as folhas de estilo e os scripts." 2 stays list downloaded. 3 stays serve. 4 is registo. 6 is autogestão. 7 is idioma. 9 is Sair. The status line says HtmlDownloader 1.0.0 and menu principal.
main-menu-ru.png
Russian main menu. The line above the box says Язык меню — русский. The path label is Путь. The path is /tmp/clips. The clock is 19:48:29 on the right of that row. 1 download is highlighted and stays download: "скачать страницу, таблицы стилей и скрипты." 2 stays list downloaded. 3 stays serve. 4 is системный журнал. 6 is самоуправление. 7 is язык. 9 is Выход. The status line says HtmlDownloader 1.0.0 and главное меню.
main-menu-de.png
German main menu. The line above the box says Die Menüsprache ist Deutsch. The path label is Pfad. The path is /tmp/clips. The clock is 19:48:32 on the right of that row. 1 download is highlighted and stays download: "eine Seite, ihre Stylesheets und ihre Skripte herunterladen." 2 stays list downloaded. 3 stays serve. 4 is Systemprotokoll. 6 is Selbstverwaltung. 7 is Sprache. 9 is Beenden. The status line says HtmlDownloader 1.0.0 and Hauptmenü.
main-menu-ja.png
Japanese main menu. The line above the box says メニューの言語は日本語. The path label is パス. The path is /tmp/clips. The clock is 19:48:34 on the right of that row. 1 download is highlighted and stays download: "ページとスタイルシートとスクリプトを取得する." 2 stays list downloaded. 3 stays serve. 4 is システムログ. 6 is 自己管理. 7 is 言語. 9 is 終了. The status line says HtmlDownloader 1.0.0 and メインメニュー.
main-menu-ko.png
Korean main menu. The line above the box says 메뉴 언어는 한국어. The path label is 경로. The path is /tmp/clips. The clock is 19:48:37 on the right of that row. 1 download is highlighted and stays download: "페이지와 스타일시트와 스크립트를 받습니다." 2 stays list downloaded. 3 stays serve. 4 is 시스템 로그. 6 is 자기관리. 7 is 언어. 9 is 종료. The status line says HtmlDownloader 1.0.0 and 주 메뉴.
main-menu-nl.png
Dutch main menu. The line above the box says De menutaal is Nederlands. The path label is Pad. The path is /tmp/clips. The clock is 19:48:39 on the right of that row. 1 download is highlighted and stays download: "download een pagina, de stylesheets en de scripts." 2 stays list downloaded. 3 stays serve. 4 is systeemlog. 6 is zelfbeheer. 7 is taal. 9 is Afsluiten. The status line says HtmlDownloader 1.0.0 and hoofdmenu.
main-menu-el.png
Greek main menu. The line above the box says Η γλώσσα του μενού είναι ελληνικά. The path label is Διαδρομή. The path is /tmp/clips. The clock is 19:48:42 on the right of that row. 1 download is highlighted and stays download: "κατέβασε μια σελίδα, τα φύλλα στυλ και τα σκριπτ." 2 stays list downloaded. 3 stays serve. 4 is αρχείο καταγραφής. 6 is αυτοδιαχείριση. 7 is γλώσσα. 9 is Έξοδος. The status line says HtmlDownloader 1.0.0 and κύριο μενού.
self-management.png
Row 6 has opened self-management. 61 version is highlighted: "show the installed version." Then 62 about "version and this computer", 63 version-check "compare this install with pip", 64 self-update "upgrade this package with pip", 65 self-uninstall "remove this package with pip", 66 self-install "install this package with pip", and 0 Back "return to the main menu." The path label is Path. The path is /tmp/clips. The clock is 19:48:44 on the right of that row. The status line says HtmlDownloader 1.0.0 and self-management.
tui-about.png
about (62) on the result page. The title is HtmlDownloader (1.0.0) — result. The page prints HtmlDownloader 1.0.0, Domain: Download a page and its stylesheets, scripts, and images, Runtime tools: none, and Entry points: html-downloader, python -m HtmlDownloader. The host check is stamped 2026-10-16 19:48:50.012150 and headed [CHECK SYSTEM]:. Visible lines include Python 3.12.11, C Library GCC 13.3.0, Ubuntu 24.04.5 LTS, amd64, the current user, the shell /bin/bash, Python Executable python3, python2 location, python3 location, a blank conda location, pyenv location, Inside docker container: False, and Cython String: cpython-312-x86_64-linux-gnu. The footer says Up/Down scrolls this page. and Press a key to return to the main menu. There is no input box and no clock. The page stays in English.
system-log.png
Row 4 has opened System Log. 41 view-log is highlighted: "list a log file and show it." Then 42 clear-log "empty one log file", 43 log-folder "show the log folder", and 0 Back "return to the main menu." The path label is Path. The path is /tmp/clips. The clock is 19:48:47 on the right of that row. The status line says HtmlDownloader 1.0.0 and System Log.
Examples
html-downloader
html-downloader version
version prints HtmlDownloader 1.0.0 and does not call pip. A run that is not the text menu can also print ChronicleLogger status lines above that. The text menu keeps those lines off the screen.
html-downloader download --url https://example.com/ --name example
That saves the page and does not draw the menu. On a terminal, row 1 lists saved pages or accepts a URL.
Platform Compatibility
| Platform | Status |
|---|---|
| Linux | Primary; tested development path |
| macOS | Supported when CPython is on PATH |
| Windows | Supported when CPython is on PATH (venv activate differs) |
| Architectures | Any with CPython |
The text menu needs a terminal. With no terminal and no verb, the program prints help and returns 0. It does not wait.
Related Projects
- HtmlDownloader on GitHub — this program’s source
- HtmlDownloader on PyPI — this program on PyPI
- AnimeDlp — command-line downloader for anime video sites
- ChronicleLogger — status logger this program depends on (
ChronicleLogger>=1.3.1) - VideoSpeed — cuts, changes speed, and boomerangs a clip. That program is not this one
- CIAO — Caution, Intentional, Anti-fragile, Over-engineered
- CIAO-Lite — short agent contract
- safe-rm — guarded
rm
Contributing
- Keep product law under
docs/requirements/in sync when behavior changes. - Prefer small, CIAO-safe changes. Do not put media joining, an external encoder, or a file listing back without an explicit design.
- Version dual SSOT: bump
pyproject.tomlandsrc/HtmlDownloader/__init__.__version__together. - Open issues and pull requests on GitHub.
License
MIT — see LICENSE.md. Also declared in pyproject.toml.
Last Update
2026-10-16 — 1.0.0. Public source is https://github.com/cloudgen/HtmlDownloader. The console script is html-downloader. download --url URL --name PAGENAME saves the page under ~/.app/HtmlDownloader/output/. Menu row 1 download lists saved pages or accepts a URL. Menu pictures show this board: language 71–83, one main menu for each language, self-management 61–66, about, and System Log 41–43. Product law under docs/requirements/ names this version and this menu. Version badge matches pyproject.toml and __version__. ChronicleLogger>=1.3.1 is required.
Metadata
Release files for HtmlDownloader 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| htmldownloader-1.0.0.tar.gz | 91.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| htmldownloader-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 157.7 kB
Release files / htmldownloader-1.0.0.tar.gz
| Download URL | htmldownloader-1.0.0.tar.gz |
|---|---|
| Size | 91.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
58dbe2a08c8b91d5278a95fad3bec3bd82ca79ae3187887301297cc555f2e14a
|
|
BLAKE2b-256 checksum How to use checksums |
e261d8b7ed3e2483b7309748a1a071840adfc20d7afe0ecdbd88ce6437d3a17b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.11
|
Release files / htmldownloader-1.0.0-py3-none-any.whl
| Download URL | htmldownloader-1.0.0-py3-none-any.whl |
|---|---|
| Size | 66.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6093e721560e64ee18b7d38d013a986c9a610dd1f463d38c674028956356c557
|
|
BLAKE2b-256 checksum How to use checksums |
3686cc3008006eef1fca5c4474d14f1c14cad10ce10739c804c99759c834768c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.11
|