Command-line tool to download manga from mangaplus
Project description
Mangaplus Downloader
mloader - download manga from mangaplus.shueisha.co.jp
🚩 Table of Contents
💾 Installation
The recommended installation method is using uv:
uv tool install mloader-ng
After installation, the mloader command will be available. Check the command line section for supported commands.
If you prefer pip, pip install mloader-ng still works.
🛠 Development
git clone https://github.com/l0westbob/mloader.git
cd mloader
uv sync
This package is published as mloader-ng (temporary maintained rewrite fork).
The CLI command remains mloader.
Stability and API access posture
mloader is maintained as a stable production CLI/Docker app. Current development is evolutionary:
small, tested hardening changes are preferred over large rewrites so current cron jobs, paths, flags,
manifest files, and exit codes stay stable.
The auth settings shipped in this repository are suitable for free-tier/local development only. They can download free-access chapters, but they must not be treated as proof that subscription/MAX or full-catalog downloads work. Full-catalog cron usage requires your own subscription-capable auth settings via environment variables, config, or Docker secrets.
When the free-tier key hits a subscription-only chapter, mloader should fail cleanly with an
external/access error such as “subscription required”, not an internal bug.
✅ Testing
uv run pytest
Coverage is enforced at 100% in CI:
uv run pytest --cov=mloader --cov-report=term-missing --cov-fail-under=100
Lint and format checks run through Ruff:
uv run ruff check .
uv run ruff format --check .
Type checking runs through ty. The project does not maintain a Pyright configuration; ty is the
single supported local and CI type checker.
uv run ty check mloader scripts tests
Run the same local quality gate used for implementation phases with:
uv run ruff format --check .
uv run ruff check .
uv run ty check mloader scripts tests
uv run python scripts/sync_readme_cli_reference.py --check
uv run pytest --cov=mloader --cov-report=term-missing --cov-fail-under=100
Verify README example targets against live MangaPlus API responses:
uv run python scripts/verify_readme_examples.py
Safe local smoke checks that do not require paid access:
uv run pytest -q
uv run mloader --all --list-only --language english
uv run mloader --chapter-id 1024959 --out /tmp/mloader-smoke
Subscription-limited/full-catalog checks should be run only with your own subscription-capable auth settings. With the repository default/free-tier auth, subscription-only chapters are expected to fail as controlled external access failures.
📙 Usage
Copy the url of the chapter or title you want to download and pass it to mloader.
Use --title with --chapter to target chapter numbers, or --chapter-id for direct API chapter IDs.
You can download individual chapters or full title (but only available chapters).
Chapters can be saved in different formats (check the --help output for the available formats).
Typical MangaPlus IDs are multi-digit integers (title IDs are commonly 6 digits), for example:
mloader https://mangaplus.shueisha.co.jp/viewer/1024959
mloader https://mangaplus.shueisha.co.jp/titles/100312 -f pdf
mloader --title 100312 --chapter 12
mloader --chapter-id 1024959
mloader --title 100312 --cover
mloader --title 100312 --cover-format webp
For an exhaustive, option-complete command catalog (including discovery, capture, resume, and output modes):
mloader --show-examples
When --capture-api is enabled, mloader stores every fetched API payload (raw protobuf + metadata + parsed JSON when possible). This is useful for regression fixture collection and for tracking upstream API changes over time.
Every title directory now includes a resumable download manifest at .mloader-manifest.json.
Rerunning the same command skips chapters already marked as completed and retries chapters that previously failed or were interrupted.
Use --no-resume to ignore manifest state for a run, or --manifest-reset to clear manifest state before downloading.
Download all discoverable titles from MangaPlus list pages with one command. This is a subscription-auth example when paired with non-free chapters:
mloader --all --format pdf
As of February 25, 2026, this will download 24,944 chapters over a total of 637 titles with a size of around 220GB (English catalog).
The bulk command uses protobuf API discovery first (/api/title_list/allV2), then falls back to
static page scraping and optional browser-rendered scraping (--browser-fallback, enabled by
default) when needed.
For unattended Docker/cron runs, --run-report <file> or MLOADER_RUN_REPORT_PATH writes a JSON
report with run timing, selected args, discovered-title count, summary counters, access-failure
count, and exporter safety mode.
Restrict bulk discovery to specific languages:
mloader --all --language english --language spanish --list-only
Supported --language values:
englishspanishfrenchindonesianportugueserussianthaigermanvietnamese
As of February 24, 2026, all the languages above are present in the live allV2 payload.
Install browser runtime locally with:
playwright install chromium
🖥️ Command line interface
Currently mloader supports these options
Usage: mloader [OPTIONS] [URLS]...
Command-line tool to download manga from mangaplus
Options:
--version Show the version and exit.
--json Emit structured JSON output to stdout
--quiet Suppress non-error human-readable output
--show-examples Print exhaustive command examples and exit
--verbose Increase logging verbosity (repeatable)
-o, --out <directory> Output directory for downloads [default:
mloader_downloads]
--verify-capture-schema <directory>
Verify captured API payloads
against required response schema fields and
exit
--verify-capture-baseline <directory>
Compare verified capture schema
signatures against a baseline capture
directory
--all Discover all available titles and
download them
--page TEXT MangaPlus list page to scrape for title
links (repeatable)
--title-index-endpoint TEXT MangaPlus mobile API endpoint used for
API-first title discovery
--id-length INTEGER RANGE If set, keep only title IDs with this
exact digit length
--language [english|spanish|french|indonesian|portuguese|russian|thai|german|vietnamese]
Restrict --all discovery to one or
more languages (repeatable)
--list-only Only print discovered title IDs for
--all and exit
--browser-fallback / --no-browser-fallback
Use Playwright-rendered scraping when
static page fetch yields no title IDs
-r, --raw Save raw images
-f, --format [cbz|pdf] Save as CBZ or PDF [default: cbz]
--capture-api <directory> Dump raw API payload captures (protobuf +
metadata) to this directory
--run-report <file> Write a JSON run report for unattended
cron/systemd runs
-q, --quality [super_high|high|low]
Image quality [default: super_high]
-s, --split Split combined images
-c, --chapter INTEGER Chapter number
--chapter-id INTEGER Chapter API ID
-t, --title INTEGER Title id
-b, --begin INTEGER RANGE Minimal chapter to try to download
[default: 0;x>=0]
-e, --end INTEGER RANGE Maximal chapter to try to download [x>=1]
-l, --last Download only the last chapter for title
--chapter-title Include chapter titles in filenames
--chapter-subdir Save raw images in subdirectories by chapter
-m, --meta Export additional metadata as JSON
--cover Download each title cover image (PNG by
default)
--cover-format [png|jpg|webp] Cover image format; implies --cover when
provided [default: png]
--resume / --no-resume Use per-title manifest state to skip
already completed chapters
--manifest-reset Reset per-title manifest state before
downloading
--help Show this message and exit.
Output mode behavior:
--json: emits machine-readable JSON payloads for successful command completion and controlled command failures.--quiet: suppresses intro and informational command output.--verbose: enables debug-level logging.
Download run summaries include:
- downloaded chapter count
- manifest-skipped chapter count
- failed chapter count and failed chapter IDs
Parameter reference
This section is generated from CLI metadata. Update it with uv run python scripts/sync_readme_cli_reference.py.
URLS:
- Positional MangaPlus URLs (
viewer/<id>andtitles/<id>).
| Option | Description | Default | Env |
|---|---|---|---|
--version |
Show the version and exit. | false |
- |
--json |
Emit structured JSON output to stdout | false |
- |
--quiet |
Suppress non-error human-readable output | false |
- |
--show-examples |
Print exhaustive command examples and exit | false |
- |
--verbose, -v |
Increase logging verbosity (repeatable) | 0 |
- |
--out, -o |
Output directory for downloads | mloader_downloads |
MLOADER_EXTRACT_OUT_DIR |
--verify-capture-schema |
Verify captured API payloads against required response schema fields and exit | - |
- |
--verify-capture-baseline |
Compare verified capture schema signatures against a baseline capture directory | - |
- |
--all |
Discover all available titles and download them | false |
- |
--page |
MangaPlus list page to scrape for title links (repeatable) | https://mangaplus.shueisha.co.jp/manga_list/ongoing, https://mangaplus.shueisha.co.jp/manga_list/completed, https://mangaplus.shueisha.co.jp/manga_list/one_shot |
- |
--title-index-endpoint |
MangaPlus mobile API endpoint used for API-first title discovery | https://jumpg-api.tokyo-cdn.com/api/title_list/allV2 |
MLOADER_TITLE_INDEX_ENDPOINT |
--id-length |
If set, keep only title IDs with this exact digit length | - |
- |
--language |
Restrict --all discovery to one or more languages (repeatable) | - |
- |
--list-only |
Only print discovered title IDs for --all and exit | false |
- |
--browser-fallback, --no-browser-fallback |
Use Playwright-rendered scraping when static page fetch yields no title IDs | true |
- |
--raw, -r |
Save raw images | false |
MLOADER_RAW |
--format, -f |
Save as CBZ or PDF | cbz |
MLOADER_OUTPUT_FORMAT |
--capture-api |
Dump raw API payload captures (protobuf + metadata) to this directory | - |
MLOADER_CAPTURE_API_DIR |
--run-report |
Write a JSON run report for unattended cron/systemd runs | - |
MLOADER_RUN_REPORT_PATH |
--quality, -q |
Image quality | super_high |
MLOADER_QUALITY |
--split, -s |
Split combined images | false |
MLOADER_SPLIT |
--chapter, -c |
Chapter number (integer, e.g. 1, 12) | - |
- |
--chapter-id |
Chapter API ID (integer, e.g. 1024959) | - |
- |
--title, -t |
Title ID (integer, usually 6 digits, e.g. 100312) | - |
- |
--begin, -b |
Minimal chapter to download | 0 |
- |
--end, -e |
Maximal chapter to download | - |
- |
--last, -l |
Download only the last chapter for each title | false |
- |
--chapter-title |
Include chapter titles in filenames | false |
- |
--chapter-subdir |
Save raw images in subdirectories by chapter | false |
- |
--meta, -m |
Export additional metadata as JSON | false |
- |
--cover |
Download each title cover image (PNG by default) | false |
- |
--cover-format |
Cover image format; implies --cover when provided | png |
- |
--resume, --no-resume |
Use per-title manifest state to skip already completed chapters | true |
- |
--manifest-reset |
Reset per-title manifest state before downloading | false |
- |
Deterministic exit-code mapping:
0: success2: user input/usage error (Click argument parsing)3: validation error (invalid CLI option combinations, schema verification validation)4: external failure (upstream API/subscription/access failures)5: internal bug/unexpected runtime failure
Runtime auth settings (app_ver, os, os_ver, secret) are resolved with this priority:
- CLI/runtime overrides (internal, reserved for programmatic usage)
- Environment variables:
APP_VER,OS,OS_VER,SECRET - Config file:
MLOADER_CONFIG_FILE(or local.mloader.toml) - Built-in defaults
Example TOML config:
[auth]
app_ver = "97"
os = "ios"
os_ver = "18.1"
secret = "your-secret"
When --meta is enabled, title_metadata.json stores chapters keyed by chapter ID ("chapters": {"<chapter_id>": ...}) and includes each chapter sub_title and thumbnail_url.
Verify your recorded payload set:
mloader --verify-capture-schema ./capture
Compare a new capture run against your committed baseline:
mloader --verify-capture-schema ./capture --verify-capture-baseline ./tests/fixtures/api_captures/baseline
🐳 Docker
docker/Dockerfile installs mloader from the local repository files.
The default compose.yaml now runs a long-lived cron daemon inside the container and executes mloader weekly.
The container preserves explicit --out /downloads behavior, uses a lock directory to avoid
overlapping cron runs, and logs clear start/end markers with exit codes.
Default schedule and arguments:
MLOADER_CRON_SCHEDULE="0 3 * * 1"
MLOADER_CRON_ARGS="--all --language english --format pdf --out /downloads --cover"
This means: every Monday at 03:00 container time.
For full-catalog Docker runs, replace the free-tier repository auth settings with your own subscription-capable settings. Otherwise subscription-only chapters will be reported as controlled external access failures.
Useful runtime knobs in compose.yaml:
MLOADER_CRON_SCHEDULE: standard 5-field cron expression.MLOADER_CRON_ARGS: arguments passed tomloaderfor scheduled runs.MLOADER_RUN_ON_START:"true"to run one job immediately on container startup.MLOADER_RUN_REPORT_PATH: optional JSON report path for weekly unattended runs.MLOADER_CRON_LOCK_DIR: lock directory used to skip overlapping schedule ticks.
Run in background:
docker compose up -d --build
Check scheduler logs:
docker compose logs -f mloader
🧩 Extending mloader
mloader is designed around domain DTOs, composed runtime services, and exporter classes.
- Add a new exporter by subclassing
ExporterBase. - Set
format = "<name>"in your exporter. - Implement
add_imageandskip_image.
See CONTRIBUTING.md for architecture and extension details.
Detailed architecture notes are in docs/ARCHITECTURE.md.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mloader_ng-2.1.0.tar.gz.
File metadata
- Download URL: mloader_ng-2.1.0.tar.gz
- Upload date:
- Size: 214.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d2afafdbb8bdf8b749b847da2382eb8dd552a490ac016420c1f99fddbb69dc42
|
|
| MD5 |
8d7c6fb3b4764f9b52f7cac426432ff7
|
|
| BLAKE2b-256 |
093d9fa67bca2e4261e22e2245eaa6041311a61ec955d908b64090eed1a0a2a9
|
Provenance
The following attestation bundles were made for mloader_ng-2.1.0.tar.gz:
Publisher:
publish-pypi.yml on l0westbob/mloader
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mloader_ng-2.1.0.tar.gz -
Subject digest:
d2afafdbb8bdf8b749b847da2382eb8dd552a490ac016420c1f99fddbb69dc42 - Sigstore transparency entry: 1654507018
- Sigstore integration time:
-
Permalink:
l0westbob/mloader@4f9da4b8570775d3ba490bfd4ae7aa9cd86f48d5 -
Branch / Tag:
refs/tags/v2.1.0 - Owner: https://github.com/l0westbob
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@4f9da4b8570775d3ba490bfd4ae7aa9cd86f48d5 -
Trigger Event:
push
-
Statement type:
File details
Details for the file mloader_ng-2.1.0-py3-none-any.whl.
File metadata
- Download URL: mloader_ng-2.1.0-py3-none-any.whl
- Upload date:
- Size: 106.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ec1f405498595340aaed65b24943fa4de34ecda4d00f841cb3995201703f53e4
|
|
| MD5 |
158f3ecc743e9cbbd592d64b65ddd5ac
|
|
| BLAKE2b-256 |
9ee3a7ecf9ff503c61b7f6b41a26607409cca9a0d3e947cf1284f9b9b45fbd1d
|
Provenance
The following attestation bundles were made for mloader_ng-2.1.0-py3-none-any.whl:
Publisher:
publish-pypi.yml on l0westbob/mloader
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mloader_ng-2.1.0-py3-none-any.whl -
Subject digest:
ec1f405498595340aaed65b24943fa4de34ecda4d00f841cb3995201703f53e4 - Sigstore transparency entry: 1654507096
- Sigstore integration time:
-
Permalink:
l0westbob/mloader@4f9da4b8570775d3ba490bfd4ae7aa9cd86f48d5 -
Branch / Tag:
refs/tags/v2.1.0 - Owner: https://github.com/l0westbob
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@4f9da4b8570775d3ba490bfd4ae7aa9cd86f48d5 -
Trigger Event:
push
-
Statement type: