Skip to main content

H2HDB Downloader

H2HDB Downloader submits E-Hentai and ExHentai galleries to H@H and keeps resumable download requests in an h2hdb database. It can process a manual CSV queue, revisit galleries marked for redownload, and download related works by artist or group.

This is a Python library. It has no standalone command-line application or background service: use it from a Python program that chooses what to download and when to run. Browser access comes from hbrowser; an h2hdb ingest process handles the files delivered by H@H.

Requirements and installation

  • Python 3.14 or newer.
  • An E-Hentai account with access to the site you use, an available H@H client, and any funds required for archive downloads.
  • A configured h2hdb database and a running ingest process for coordinated downloads. This package does not create or upgrade the database.
  • A working browser environment supported by HBrowser.

Install into your Python environment:

python -m pip install h2hdb-downloader

To install this checkout instead, run python -m pip install . from its root. The package declares compatible h2hdb and hbrowser dependency versions; let the installer resolve them together. This release uses h2hdb schema version 8 (epoch 3), with Core 0.41.1 or later in the 0.41 lane. Follow the h2hdb setup instructions to prepare the database and configuration file before running the example.

Existing schema-7 databases require Core's offline source-collection schema upgrade before using this release. Keep downloader and all other consumers stopped during that conversion; existing database contents and CBZ files are retained. Downloader does not initialize or upgrade the database itself.

Set browser credentials in your script's environment. For Bash or Zsh:

export EH_USERNAME='your_username'
export EH_PASSWORD='your_password'
export USE_TOR=0

For PowerShell:

$env:EH_USERNAME = 'your_username'
$env:EH_PASSWORD = 'your_password'
$env:USE_TOR = '0'

USE_TOR=0 selects a direct connection. If omitted, HBrowser may use a detected Tor installation. Keep credentials out of your Python files and version control. Start with a visible browser so you can handle login challenges; unattended setup and optional FlareSolverr configuration are described in the HBrowser README.

Process your download queue

Save this as download_queue.py beside your configured h2hdb-config.json, then run python download_queue.py:

import asyncio

from h2hdb import VNextDownloadQueueFacade, load_config
from h2hdb_downloader import Downloader, TagCascadePolicy
from hbrowser import ExHDriver


async def main() -> None:
    facade = VNextDownloadQueueFacade(load_config("h2hdb-config.json"))
    try:
        async with Downloader(
            ExHDriver(headless=False),
            facade=facade,
            csv_path="todownload_gids.csv",
            wait4client=30 * 60,
            retry2download=4 * 60 * 60,
            download_submissions_per_ingest=100,
        ) as downloader:
            # Empty filters process only the galleries you queued.
            policy = TagCascadePolicy(filters=(), conditions=())
            results = await downloader.drain_queue(policy)
            for gid, submitted in results.items():
                print(gid, submitted)
    finally:
        facade.close()


if __name__ == "__main__":
    asyncio.run(main())

Downloader opens and closes the browser session. Pass it a driver that has not already been entered. If your application already manages an active driver, pass that driver and call downloader methods without entering a second context.

The example processes one snapshot of queued work, waits for ingest after each batch, and exits. New requests added after that snapshot wait for the next run. A returned True means the gallery submission was accepted; it is not a local file path. False means no submission succeeded in that operation, including cases where a gallery was skipped or unavailable.

Add galleries with a CSV file

Create todownload_gids.csv with the following two columns. Replace the sample IDs and URL with your targets:

gid,url
123,https://exhentai.org/g/123/456/
666,
,https://exhentai.org/g/789/abc/
  • A GID alone is looked up through the browser.
  • A URL alone supplies its GID automatically.
  • When both are present, they must identify the same gallery.
  • Each row must have exactly two fields. GIDs must be positive integers.

The CSV is an inbox: imported rows move into the database queue and disappear from the inbox. A missing inbox file is created automatically; its parent directory must already exist. Hidden files named .todownload_gids.csv.claim-* are interrupted imports and are replayed automatically on the next run. Keep those files until replay succeeds. A malformed row raises an error; correct the reported inbox or claim file before trying again.

Set csv_path=None if you only use requests already in the database.

To follow the queued gallery's artist and group tags, replace the empty policy with:

policy = TagCascadePolicy(
    filters=("artist", "group"),
    conditions=("language:chinese$", "language:speechless$"),
)

Each condition runs as a separate search under each matching tag. Empty conditions means no additional search restriction, so check the policy before starting a potentially large download.

Use these methods inside the active downloader context:

Task Call
Process the current durable and CSV queue await downloader.drain_queue(policy)
Process the current pending-redownload list await downloader.drain_pending_redownloads(policy)
Download one GID and its related works await downloader.deep_download_by_gid(gid, policy)
Download a known gallery URL and related works await downloader.deep_download_by_gallery(gallery, policy)
Inspect pending redownload IDs without downloading downloader.pending_redownload_gids()

For URL-based methods, construct gallery with h2h_galleryinfo_parser.GalleryURLParser(url). Deep methods normally follow related tags only when the root gallery was downloaded. Pass skip_check=True to follow its tags even if the root was already downloaded; queue-draining methods use this setting by default.

Coordinated methods take turns with ingest and wait for it to finish. With the default download_submissions_per_ingest=100, a queue batch hands off after at least 100 unique submissions or when its snapshot is exhausted. The current gallery and all its related downloads finish before that threshold is checked, so a batch can exceed 100. This setting counts accepted submissions, not completed files or elapsed time.

For applications that manage their own ingest scheduling, download_by_gallery(gallery), download_by_gid(gid), and download_by_tag(tag, conditions) submit directly without claiming a download turn or waiting for ingest. Prefer the coordinated methods above when sharing a database with ingest.

Retry settings and recovery

The two required retry settings are in seconds:

Setting Effect
wait4client Delay before retrying when the H@H client is offline. Use 0 to raise immediately.
retry2download Delay before retrying when the account has insufficient funds. Use 0 to raise immediately.
turn_poll_seconds Interval while waiting for a download turn or ingest completion; default 5.
turn_lease_seconds Recoverable download-turn lease; default 300.
turn_heartbeat_seconds Lease renewal interval; default 60, and must be shorter than the lease.

The turn timing values must be positive and finite; the lease and download_submissions_per_ingest must be positive integers. Usually the defaults need no adjustment.

Interrupted or failed queued work remains available for a later run. Only a confirmed missing-gallery result marks a gallery removed; login, challenge, search, or navigation errors are failures to retry after their cause is fixed. Already downloaded galleries are usually skipped unless requested again or marked for redownload; periodic rechecks can still submit a settled gallery.

H@H may accept a request immediately before the program stops. Restarting can therefore submit that gallery again. Submission is at least once; the library does not promise that a gallery is submitted exactly once.

Symptom What to do
Waiting indefinitely for a turn or ingest Check that the ingest process is running against the same database and is making progress.
DownloadTurnLostError Stop the current operation; unfinished queued work can be retried in a later run. Check for competing workers or delayed lease renewal.
Login or challenge error Retry with headless=False and verify the account, route, and HBrowser settings.
H@H offline or insufficient funds Restore the client or balance, or set the corresponding retry delay to 0 to handle the error in your application.
CSV parsing error Check the two-column format, positive GIDs, and URL/GID agreement, including any retained claim file.
Database schema rejected Follow h2hdb's setup or offline upgrade instructions. Downloader does not upgrade an existing database.

For browser diagnostics and optional logging, see the HBrowser README. When reporting a problem, include package versions, the failing operation, and a sanitized exception; do not include credentials or private account pages. Report issues through the issue tracker.

License

Licensed under GPL-3.0-only. See LICENSE.

Release files for h2hdb-downloader 0.22.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for h2hdb-downloader 0.22.0
File Size Uploaded
h2hdb_downloader-0.22.0.tar.gz 67.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for h2hdb-downloader 0.22.0
File Interpreter ABI Platform
h2hdb_downloader-0.22.0-py3-none-any.whl Python 3 none any Details

Total release size: 96.3 kB

Release files / h2hdb_downloader-0.22.0.tar.gz

Download URL h2hdb_downloader-0.22.0.tar.gz
Size 67.3 kB
Tags Source
SHA-256 checksum
How to use checksums
40350c4fe1904ab13f8e1dac39a9d45751611dee4db8512e03a747bace233300
BLAKE2b-256 checksum
How to use checksums
cd248e123ff0059a0d9defb26302af0877562817d63150aeb9ec0f359b3d3626
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 23, 2026.

Transparency log

Release files / h2hdb_downloader-0.22.0-py3-none-any.whl

Download URL h2hdb_downloader-0.22.0-py3-none-any.whl
Size 29.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
810226a12ad64a59444b50bab5ea603c1d3d8f57ef8b16ff1cd74fc83220c261
BLAKE2b-256 checksum
How to use checksums
22a1f7bc603a75a84e2ca6ad7675993b1502b9386a3716ffa965232ecc16fac0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 23, 2026.

Transparency log

Release history Release notifications | RSS feed

0.22.1

2 release files

This release

0.22.0 This release

2 release files

0.21.0

2 release files

0.20.2

2 release files

0.20.1

2 release files

0.14.0

2 release files

0.13.1

2 release files

0.13.0

2 release files

0.12.0

2 release files

0.11.0

2 release files

0.10.7

2 release files

0.10.5

2 release files

0.10.4

2 release files

0.10.3

2 release files

0.10.2

2 release files

0.10.1

2 release files

0.10.0

2 release files

0.9.5

2 release files

0.9.4

2 release files

0.9.2

2 release files

0.9.1

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.9

2 release files

0.4.8

2 release files

0.4.7

2 release files

0.4.6

2 release files

0.4.5

2 release files

0.4.4

2 release files

0.4.3

2 release files

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.1

2 release files

0.1.0

2 release files

0.0.9

2 release files

0.0.7

2 release files

0.0.6

2 release files

0.0.5

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.2

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page