CLI tool
RicterZ/doujinshi-dl avatar
RicterZ/doujinshi-dl

doujinshi-dl: a plugin driven command-line downloader

Doujinshi downloader framework

991 stars121 forksPythonMIT

At a glance

What is it?
doujinshi-dl is a Python command line tool that searches, downloads and organises doujinshi through site plugins, then exports the result as CBZ, PDF or ZIP or as a generated HTML reader. The plugin boundary is strict, one plugin per environment, and the package itself knows nothing about any particular site.
Who is it for?
doujinshi-dl suits a user who wants one site's catalogue as a local, well organised archive with generated readers and comic exports, and it is the wrong tool for anyone who needs several sites in one run, for scripted unattended collection without a token, or for a pipeline that assumes stable output formats, since the sort keys and search syntax are site dependent.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The core package holds no site logic, only the plugin contract

doujinshi-dl is described as a command-line tool for searching, downloading and organizing doujinshi through site plugins. That phrasing puts the architecture in the right order. The application is generic, and the knowledge of a specific site lives in a separate distribution, such as `doujinshi-dl-nhentai`, which the readme uses as its worked example throughout.

The repository layout matches. The code lives in a `doujinshi_dl/` package, with the `include` line in pyproject.toml pulling in `doujinshi_dl/viewer/**`, which is the HTML reader asset directory that gets shipped with the distribution. The entry point is a console script named `doujinshi-dl`, bound to `doujinshi_dl.command:main`. The runtime dependencies are ordinary HTTP and parsing tools, requests, httpx, beautifulsoup4, soupsieve, chardet, tabulate and iso8601.

There is a hard constraint on how plugins are discovered, and the readme is explicit about it. The application currently loads the first site plugin it finds, so you should install only one site plugin per environment. Plugins installed outside the tool environment cannot be discovered at all, which is why the installation instructions put the plugin in with `--with` rather than as a separate global tool.

The consequence is a design with a hard ceiling of one site per environment. Multi site workflows mean multiple environments, and switching sites means reinstalling the tool.

uv owns the environment, and the plugin must live inside it

Installation is managed by uv rather than by pip and a virtualenv of your own. The readme points at the official uv installation guide and mentions Homebrew as an option on macOS.

bash
brew install uv

The application and the plugin then go into the same isolated environment in a single command.

bash
uv tool install --python 3.12 --with doujinshi-dl-nhentai doujinshi-dl
uv tool update-shell

The Python 3.12 selector is explicit, and the readme notes that Python 3.12 is recommended while the commands tell uv which version to pick. After updating the shell, a new terminal should show the command is available.

bash
doujinshi-dl --help

Upgrading and removing are handled by the same tool.

bash
uv tool upgrade doujinshi-dl
uv tool uninstall doujinshi-dl

The PDF export path needs one more package, and the install command has to be repeated with the extra while keeping the site plugin, because dropping the plugin would break the plugin contract described above.

bash
uv tool install --python 3.12 --with doujinshi-dl-nhentai --with img2pdf doujinshi-dl

The Dockerfile shows the same idea in container form. It builds on `python:3-slim`, installs the base package with pip, then installs the plugin in a deliberately indirect way, computing the plugin name by reversing a string in a Python one-liner rather than writing it out, and finally sets `ENTRYPOINT ["doujinshi-dl"]` with `/output` as the working directory.

Authentication, language and proxy are saved once and the process exits

The readme is emphatic that configuration happens before downloading. You get an API token from your account settings on the site, and the token, the language filter and the proxy are all saved for future commands. The application exits after setting any of them, so the token command and the download command are two separate invocations rather than one.

bash
doujinshi-dl --token "YOUR_API_TOKEN"
doujinshi-dl --id 123855 --output ./downloads

The same pattern applies to the other two settings.

bash
doujinshi-dl --language english
doujinshi-dl --proxy "http://127.0.0.1:1080"

# Clear the language filter or proxy
doujinshi-dl --language ""
doujinshi-dl --proxy ""

The language setting appends a language filter to keyword and artist queries, which is why it is a persistent setting rather than a per command flag. Passing an empty string clears it.

That exit-after-save behaviour is unusual and easy to trip over. A script that runs `doujinshi-dl --token ... --id ...` in one line will download nothing, because the process ends when the token is stored. The readme warns about this in plain language, and it is the single most likely reason a first attempt produces an empty downloads directory.

Batch IDs, files, search pages and favorites share one command surface

The everyday operations are all flag combinations on the same executable. Several IDs can be given at once, `--show` prints information without downloading, and `--file` reads IDs from a text file with one numeric ID per line.

bash
# Download multiple IDs
doujinshi-dl --id 123855 123866 123877 --output ./downloads

# Show information only
doujinshi-dl --id 123855 --show

# Read IDs from a file
doujinshi-dl --file doujinshi.txt --output ./downloads

Search and favorites use the same surface, with `--download` added to fetch what the query returns.

bash
# Search and download the first page
doujinshi-dl --search "full color" --page 1 --download

# Download selected favorites pages, waiting 1 second between galleries
doujinshi-dl --favorites --page 3-5,7 --download --delay 1

Page selection accepts a single page, a range, or a combination such as `1`, `3-5` or `1,3-5,7`, and `--page-all` fetches every page of a search. The `--delay` flag in the favorites example is worth noting, since it is the difference between a burst of requests and a paced run against someone else's server.

The limits of this surface are set by the plugin. Search syntax depends on the plugin, `--artist` queries by artist, and `--sorting` accepts `recent`, `popular`, `popular-today`, `popular-week` or `date` while defaulting to `popular`. The readme notes that the available sorting behaviour depends on the site, so a key that works for one plugin may not exist for another.

CBZ, PDF and ZIP exports sit alongside a generated HTML reader

Downloads land in the current working directory by default and an HTML reader is generated, with `--output` choosing a different destination. On top of that, four export modes exist.

bash
# Export a CBZ with metadata
doujinshi-dl --id 123855 --cbz --output ./downloads

# Export a PDF; install img2pdf first
doujinshi-dl --id 123855 --pdf --output ./downloads

# Download directly to ZIP, disabling HTML generation
doujinshi-dl --id 123855 --zip --output ./downloads

# Generate HTML readers for downloaded directories
doujinshi-dl --html ./downloads

# Generate an overview page after downloading
doujinshi-dl --id 123855 --gen-main --output ./downloads

So the HTML reader can be produced for directories that were downloaded earlier, and `--gen-main` adds an overview page for a gallery. `--no-html` disables HTML generation after a download, and `--meta` writes additional metadata files provided by the plugin. `--regenerate` asks for an existing CBZ or PDF to be rebuilt.

PDF export is the one that needs an extra package, `img2pdf`, which is why it is documented separately and why the install command has to be rerun with the extra.

There are two destructive flags and the readme is careful about both. Image directories are kept by default; `--rm-origin-dir` deletes the original directory and should only be used after confirming that the export succeeded, while `--move-to-folder` removes the original files inside the directory and moves the exported file into it. The readme says not to combine those two options.

Folder names are template driven, with platform specific escaping

The default folder name format is `[%i][%a][%t]`, meaning the gallery ID, the artists and the title. Any subset can be selected by passing a different `--format` string.

bash
doujinshi-dl --id 123855 --format '[%i]%t'

The example site plugin documents the available placeholders: `%i` for the gallery ID, `%t` for the title, `%s` for the subtitle or translated title, `%p` for a pretty title, `%a` for artists, `%g` for groups, `%ag` for artists falling back to groups, and `%f` for the favorite count.

Two platform notes come with this. In Windows `.bat` or `.cmd` files you write `%%` instead of `%`, since a single percent sign is a variable reference in batch. In PowerShell, the single-quoted example is used as written, which avoids PowerShell's own interpolation of the percent sign.

The placeholder set is plugin specific. The list above comes from the example plugin, so a different site plugin may expose a different set, and the fallback from artists to groups in `%ag` shows that the values are computed by the plugin rather than by the core.

Where the tool stops being convenient

Three constraints shape when this project is the wrong choice.

The first is the one plugin per environment rule. If your workflow spans several sites, you need several installations, and there is no command to select a plugin at runtime. The Dockerfile makes the same assumption by shipping exactly one plugin alongside the base package.

The second is that every operation depends on a site account and an API token. There is no anonymous mode described in the readme, and the token must be configured before anything else runs. Automation therefore means a script that first stores a token and then issues download commands, and the exit-after-save behaviour means the token step is a separate process that has to succeed first.

The third is the version story. The newest release tag is v2.0.9, dated 2026-04-14, while pyproject.toml declares `version = "2.1.0"` and the project itself is `python = "^3.8"` even though the install commands ask for 3.12. The last push to the default branch was on 2026-10-01, so work continues on master between releases.

Nothing in the readme documents a plugin API version, an upgrade path between plugin releases, or how the core discovers and validates a plugin beyond finding the first one. If you plan to automate this, that is the part you will be reading the source for.

The licence is MIT, stated in pyproject.toml with the full text in the `LICENSE` file at the repository root.

Editorial conclusion

doujinshi-dl suits a user who wants one site's catalogue as a local, well organised archive with generated readers and comic exports, and it is the wrong tool for anyone who needs several sites in one run, for scripted unattended collection without a token, or for a pipeline that assumes stable output formats, since the sort keys and search syntax are site dependent. Before adopting it, install exactly one site plugin into the tool environment, save the API token with `doujinshi-dl --token` before running any download, and note that the newest release tag is v2.0.9 from 2026-04-14 while pyproject.toml already declares version 2.1.0.

Frequently asked questions

How do I install doujinshi-dl with a site plugin?

Install the application and the plugin into the same uv tool environment, for example `uv tool install --python 3.12 --with doujinshi-dl-nhentai doujinshi-dl`, then run `uv tool update-shell`. Plugins installed elsewhere cannot be discovered, so keep only one site plugin per environment.

How do I authenticate and set the language or proxy?

Run `doujinshi-dl --token "YOUR_API_TOKEN"`, `doujinshi-dl --language english` or `doujinshi-dl --proxy "http://127.0.0.1:1080"` as separate commands, because the application exits after saving a setting. Pass an empty string to clear the language filter or the proxy.

How do I export a gallery as CBZ or PDF?

Pass `--cbz` for a CBZ with metadata or `--pdf` for a PDF, for example `doujinshi-dl --id 123855 --pdf --output ./downloads`. PDF export needs the `img2pdf` package installed alongside the site plugin.

Can I search and download in one step?

Yes. Add `--download` to a search, artist or favorites query, and select pages with `--page`, `--page-all` or `--page 1,3-5,7`. The `--delay` flag pauses between galleries, and `--sorting` accepts `recent`, `popular`, `popular-today`, `popular-week` or `date`.

Does doujinshi-dl keep the original images after an export?

Image directories are kept by default. `--rm-origin-dir` deletes the original directory and `--move-to-folder` moves the exported file into it after removing the original files inside, and the readme says not to combine the two options.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. Releases
  5. RicterZ/doujinshi-dl on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/ricterz-doujinshi-dl.svg)](https://hysenlabs.com/projects/ricterz-doujinshi-dl)

Was this useful?