doujinshi-dl: a plugin driven command-line downloader
Doujinshi downloader framework
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.
brew install uvThe application and the plugin then go into the same isolated environment in a single command.
uv tool install --python 3.12 --with doujinshi-dl-nhentai doujinshi-dl
uv tool update-shellThe 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.
doujinshi-dl --helpUpgrading and removing are handled by the same tool.
uv tool upgrade doujinshi-dl
uv tool uninstall doujinshi-dlThe 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.
uv tool install --python 3.12 --with doujinshi-dl-nhentai --with img2pdf doujinshi-dlThe 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.
doujinshi-dl --token "YOUR_API_TOKEN"
doujinshi-dl --id 123855 --output ./downloadsThe same pattern applies to the other two settings.
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.
# 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 ./downloadsSearch and favorites use the same surface, with `--download` added to fetch what the query returns.
# 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 1Page 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.
# 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 ./downloadsSo 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.
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
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.
[](https://hysenlabs.com/projects/ricterz-doujinshi-dl)Was this useful?