ranobelib-python-sdk
Async Python SDK for ranobelib.me: fetch title metadata, download chapters and volumes, and export to epub, fb2, txt, or pdf.
The SDK talks to the undocumented but open JSON API behind the site (api.cdnlibs.org,
part of the lib.social network) instead of scraping HTML — see API notes
for what's been learned about it along the way.
Installation
uv add ranobelib-python-sdk
or
pip install ranobelib-python-sdk
Requires Python 3.11+. fmt="pdf" on RanobeLib.export()
additionally needs WeasyPrint's native dependencies
(Pango/cairo, via a GTK3 runtime) installed on the system — pip install/uv add alone
doesn't guarantee that on every platform. Without them, export(fmt="pdf") raises the same
"unknown format" error the other three formats don't.
Quickstart
from ranobelib import RanobeLib
async with RanobeLib("https://ranobelib.me/ru/book/6712--high-school-dxd-novel") as lib:
info = await lib.get_info()
toc = await lib.get_table_of_contents()
chapter = await lib.get_chapter(volume=6, number="51.6")
volume = await lib.get_volume(volume=6)
chapters = await lib.get_chapters([(6, "51.6"), (6, "52")])
volumes = await lib.get_volumes([1, 2, 3])
translations = await lib.get_translations(volume=6, number="51.6")
chapter = await lib.get_chapter(volume=6, number="51.6", branch_id=...)
await lib.export(chapters, fmt="epub", path="output.epub")
number is a string exactly as the API returns it, and may contain a decimal for
sub-chapters ("51.6") — there's no separate parameter for the fractional part.
Selecting a translation
When a chapter has more than one team's translation, get_chapter() (and anything built on
it — get_chapters(), get_volume(), get_volumes()) raises
MultipleTranslationsError instead of guessing which
one you want:
from ranobelib import MultipleTranslationsError
try:
chapter = await lib.get_chapter(volume=6, number="51.6")
except MultipleTranslationsError as exc:
for branch in exc.branches:
print(branch.branch_id, [team.name for team in branch.teams])
chapter = await lib.get_chapter(volume=6, number="51.6", branch_id=exc.branches[0].branch_id)
Caching
Raw API responses (title metadata, chapter list, chapter content) are cached to disk by default, so re-exporting to a different format or downloading newly added chapters doesn't re-fetch data already on hand:
async with RanobeLib(url, cache_dir=".cache", cache_ttl=3600) as lib:
toc = await lib.get_table_of_contents() # First call: hits the API.
toc = await lib.get_table_of_contents() # Second call: served from disk.
toc = await lib.get_table_of_contents(refresh=True) # Bypasses the cache.
Documentation
- API reference — generated from the source's own docstrings.
- API notes — a running log of what's been learned about ranobelib's undocumented API and the design decisions that followed from it (translation selection, rate limiting, why each exporter is built the way it is, and more).
- The project's CLAUDE.md documents the full architecture, public API contract, and roadmap.
License
MIT — see LICENSE.