Skip to content

Translator

The library provides multiple translation providers that implement the BaseTranslator interface.

NekoTranslator

Client for the NekoTranslate API. Supports anonymous mode with automatic proxy rotation.

from nhentai import NekoTranslator, NekoEngine, Language

translator = NekoTranslator(token="YOUR_BEARER_TOKEN") # token is optional
data = translator.translate_file("page.jpg", tgt_lang=Language.INDONESIAN, engine=NekoEngine.DEEPL)

nhentai.translator.NekoTranslator(token: str | None = None, proxy_list_url: str | None = None, proxies: list[str] | None = None)

Bases: BaseTranslator

NekoTranslate API client.

Anonymous (no token): uses free quota per IP, rotates proxies automatically. Authenticated: pass token from nhentai.net localStorage.

Parameters:

Name Type Description Default
token str | None

Bearer token for authenticated requests (optional).

None
proxy_list_url str | None

URL to a plain-text proxy list. Defaults to proxifly socks5 list.

None
proxies list[str] | None

Explicit proxy list (overrides proxy_list_url).

None
Source code in nhentai/providers/neko.py
def __init__(
    self,
    token: str | None = None,
    proxy_list_url: str | None = None,
    proxies: list[str] | None = None,
):
    """
    :param token: Bearer token for authenticated requests (optional).
    :param proxy_list_url: URL to a plain-text proxy list. Defaults to proxifly socks5 list.
    :param proxies: Explicit proxy list (overrides proxy_list_url).
    """
    self.token = token
    self.headers: dict[str, str] = {}
    if self.token:
        self.headers["Authorization"] = f"Bearer {self.token}"

    raw = proxies or self._fetch_proxies(proxy_list_url)
    self._proxy_list = [_parse_proxy(p) for p in raw if p.strip()]
    self._proxy_cycle = cycle(self._proxy_list) if self._proxy_list else None

find_proxy_with_quota() -> dict | None

Returns the first proxy with remaining anonymous quota, or None.

Source code in nhentai/providers/neko.py
def find_proxy_with_quota(self) -> dict | None:
    """Returns the first proxy with remaining anonymous quota, or None."""
    for proxy in self._proxy_list:
        try:
            resp = requests.get(
                f"{BASE_URL}/get-quota",
                proxies=proxy,
                verify=False,
                timeout=_QUOTA_SCAN_TIMEOUT,
            )
            if resp.status_code == 200 and resp.json().get("quota", 0) > 0:
                return proxy
        except requests.exceptions.RequestException:
            continue
    return None

get_balance() -> dict

Returns {"email", "plan", "level", "quota"}.

Source code in nhentai/providers/neko.py
def get_balance(self) -> dict:
    """Returns ``{"email", "plan", "level", "quota"}``."""
    result: dict = {"email": None, "plan": PLAN_NAMES[0], "level": 0, "quota": None}

    if self.token:
        try:
            resp = self._request(
                "GET", f"{BASE_URL}/get-user", headers=self.headers, timeout=_POLL_TIMEOUT,
            )
            if resp.status_code == 200:
                user = resp.json()
                result["email"] = user.get("email")
                level = user.get("level", 0)
                result["level"] = level
                result["plan"] = PLAN_NAMES[level] if level < len(PLAN_NAMES) else f"Level {level}"
        except requests.exceptions.RequestException:
            pass

    try:
        resp = self._request(
            "GET", f"{BASE_URL}/get-quota",
            headers=self.headers,
            use_proxy=bool(self._proxy_list),
            timeout=_POLL_TIMEOUT,
        )
        if resp.status_code == 200:
            result["quota"] = resp.json().get("quota")
    except requests.exceptions.RequestException:
        pass

    return result

translate_file(image_path: Path, tgt_lang: Language | str = Language.ENGLISH, engine: NekoEngine | str = NekoEngine.DEEPL) -> bytes

Translate an image file and return the result as bytes.

Source code in nhentai/providers/neko.py
def translate_file(
    self,
    image_path: Path,
    tgt_lang: Language | str = Language.ENGLISH,
    engine: NekoEngine | str = NekoEngine.DEEPL,
) -> bytes:
    """
    Translate an image file and return the result as bytes.
    """
    image_path = Path(image_path)
    if not image_path.exists():
        raise FileNotFoundError(f"Image not found: {image_path}")
    if not image_path.is_file():
        raise ValueError(f"Not a file: {image_path}")

    engine = NekoEngine(engine)
    tgt_lang = Language(tgt_lang) if not isinstance(tgt_lang, Language) else tgt_lang

    force_proxy = None
    if not self.token and self._proxy_list:
        force_proxy = self.find_proxy_with_quota()
        if force_proxy is None:
            raise TranslationError("All proxies have exhausted anonymous quota.")

    manga_id = self._upload(image_path, tgt_lang, engine, force_proxy)
    result_url = self._poll(manga_id)
    return self._download(result_url)

translate_bytes(data: bytes, filename: str, tgt_lang: Language | str = Language.ENGLISH, engine: NekoEngine | str = NekoEngine.DEEPL) -> bytes

Translate raw image bytes. Writes to a temp file, translates, returns result bytes.

Source code in nhentai/providers/neko.py
def translate_bytes(
    self,
    data: bytes,
    filename: str,
    tgt_lang: Language | str = Language.ENGLISH,
    engine: NekoEngine | str = NekoEngine.DEEPL,
) -> bytes:
    """
    Translate raw image bytes. Writes to a temp file, translates, returns result bytes.
    """
    suffix = Path(filename).suffix or ".jpg"
    with tempfile.NamedTemporaryFile(suffix=suffix, delete=False) as tmp:
        tmp.write(data)
        tmp_path = Path(tmp.name)
    try:
        return self.translate_file(tmp_path, tgt_lang, engine)
    finally:
        os.unlink(tmp_path)

ComicTranslator

Client for the Comic-Translator API. Automatically handles guest registration and supports direct URL translation.

from nhentai import ComicTranslator, ComicEngine, Language

translator = ComicTranslator()
# Direct URL translation (Faster)
data = translator.translate_url("https://i.nhentai.net/...", tgt_lang=Language.ENGLISH, engine=ComicEngine.GEMINI_FLASH)

nhentai.translator.ComicTranslator()

Bases: BaseTranslator

ComicTranslator.com API client. Automatically handles guest registration and credit management.

Source code in nhentai/providers/comic.py
def __init__(self):
    self.token = None
    self.credits = 0.0
    self._session = requests.Session()
    self._session.headers.update({
        "User-Agent": (
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
            "AppleWebKit/537.36 (KHTML, like Gecko) "
            "Chrome/124.0.0.0 Safari/537.36"
        ),
        "Origin": "chrome-extension://liquiddev99@comictranslator.com",
        "Referer": "https://comictranslator.com/",
    })

nhentai.translator.TranslationError

Bases: Exception

Raised when the translation server reports a failure.