Library / SDK guide¶
This is the complete guide to the Nyora library (pip install nyora,
import nyora). It covers the cloud client, its async counterpart, every service
method with its signature and return type, context-manager usage, error
handling, and the model dataclasses. Cloud account and library sync live in a
separate client, nyora.sync.NyoraSync, documented in the
sync guide.
Note
The library and the nyora-cli terminal tool are separate. This guide is
about the importable nyora package only.
Clients at a glance¶
Client |
Import |
Backend |
Use when |
|---|---|---|---|
|
|
REST over HTTP to the Nyora cloud (default) |
Default. Browse, search, read, and — against a full helper deployment — manage library, downloads, history, and backup. |
|
|
Async REST to the same endpoint |
You need |
|
|
OAuth2/JWT to the Nyora sync server |
You want to sync a user’s favourites, history, and bookmarks. See the sync guide. |
nyora.NyoraHelper is a backwards-compatible alias of nyora.Nyora; new code
should use Nyora.
The client: nyora.Nyora¶
from nyora import Nyora
with Nyora() as client:
for source in client.sources.list():
print(source.id, source.name)
Nyora is a thin, typed HTTP client. By default it targets the public Nyora
cloud (nyora.CLOUD_BASE_URL, i.e.
https://api.hasanraza.tech), so a bare Nyora() just works with nothing else
running.
Construction and discovery¶
Nyora(base_url=None, *, timeout=60.0, helper=None)— connect. Whenbase_urlisNone, the URL is resolved in order: theNYORA_BASE_URLenvironment variable, a running local helper’s port file, then the public cloud.timeoutis the per-request HTTP timeout in seconds.Nyora.attach(base_url=None, *, timeout=60.0)— classmethod alias for attaching to an already-running endpoint (explicit or auto-discovered).Nyora.managed(jar_path=None, *, java="java", timeout=60.0, launch_timeout=20.0)— classmethod that launches a local helper process from a.jar(path or theNYORA_HELPER_JARenvironment variable) withjavaand binds a client to the managed process. The process is owned and stopped onclose(). Most users never need this — it is for running a private helper instead of the cloud.
Context-manager usage¶
The client holds an httpx connection. Use it as a context manager so the
connection (and any managed helper) is released on exit:
with Nyora() as client:
sources = client.sources.list()
# connection closed here
Equivalently, call client.close() yourself:
client = Nyora()
try:
sources = client.sources.list()
finally:
client.close()
Low-level HTTP and health¶
health() -> dict[str, Any]— the endpoint’s/healthpayload.get(path, *, params=None) -> Any— raw GET; returns parsed JSON or text.post(path, *, params=None, json=None, content=None) -> Any— raw POST.delete(path, *, params=None) -> Any— raw DELETE.
All raise nyora.NyoraHTTPError on a 4xx/5xx response.
Service objects¶
The client attaches six services. Methods that return model objects reference
nyora.models; methods documented as returning
dict/list return the raw payload.
client.sources — SourcesService¶
Method |
Returns |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
find(query) returns the first source whose id or name contains query
(case-insensitive), and raises LookupError if none match.
client.manga — MangaService¶
Method |
Returns |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
details takes an optional manga_id= to disambiguate an entry when the source
needs it; the manga URL alone is usually enough. pages takes an optional
branch= to select a scanlation branch/translation.
with Nyora() as client:
source = client.sources.find("mangadex")
results = client.manga.search(source.id, "berserk", page=1)
details = client.manga.details(source.id, results.entries[0].url)
pages = client.manga.pages(source.id, details.chapters[0].url)
for page in pages:
print(page.url, page.headers)
client.library — LibraryService¶
Method |
Returns |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
client.downloads — DownloadsService¶
Method |
Returns |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
client.backup — BackupService¶
Method |
Returns |
|---|---|
|
backup payload ( |
|
|
client.system — SystemService¶
Composes two sub-services: client.system.local and client.system.tracker.
Method |
Returns |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Note
Cloud account and library sync are not on client.system. They live in the
standalone nyora.sync.NyoraSync client (OAuth2/JWT against the Nyora
sync server). See the sync guide.
Note
The full set of library, downloads, backup, and tracker features requires a deployment that implements those endpoints. Browse, search, details, and pages work against the default public cloud.
nyora.AsyncNyora¶
A lightweight async client for read-style requests:
from nyora import AsyncNyora
async def main():
async with AsyncNyora.attach() as client:
payload = await client.get("/sources")
health = await client.health()
It exposes attach, get(path, *, params=None), health(), and close(), and
resolves its base URL the same way as the synchronous client (falling back to the
cloud).
Error handling¶
The exception hierarchy lives in nyora.errors and is re-exported from the
top-level package. All SDK errors derive from NyoraError, so catching it
catches everything.
Exception |
Raised when |
|---|---|
|
Base class for all SDK failures. |
|
No endpoint could be discovered for a managed/attached client. |
|
A managed helper process failed to start. |
|
The endpoint returned a 4xx/5xx. Has |
from nyora import Nyora, NyoraError, NyoraHTTPError
try:
with Nyora() as client:
page = client.manga.popular("mangadex")
except NyoraHTTPError as exc:
print("HTTP", exc.status_code, exc.body)
except NyoraError as exc:
print("Nyora error:", exc)
sources.find(...) raises the standard library LookupError (not a
NyoraError) when nothing matches. The sync client raises
nyora.sync.NotSignedInError (a RuntimeError) when a sync operation
is attempted before signing in — see the sync guide.
Model dataclasses¶
All models live in nyora.models and are slotted dataclasses with a tolerant
from_json classmethod that coerces raw camelCase payloads defensively — missing
or malformed fields fall back to sensible defaults rather than raising. Fields
below use the Python (snake_case) names.
Source¶
A content source (site). Fields: id, name, lang, base_url, engine,
content_type, is_installed, is_pinned, is_nsfw, is_obsolete,
icon_url, version, notes, can_uninstall.
SourceFilter¶
A search filter advertised by a source. Fields: name, type_name, values.
Manga¶
A manga entry as returned in listings and details. Fields: id, title,
alt_titles, url, public_url, rating (-1.0 when unknown), is_nsfw,
content_rating, cover_url, large_cover_url, state, authors, source,
source_id, description, tags, chapters, unread, progress.
MangaChapter¶
A chapter belonging to a manga. Fields: id, title, number (may be
fractional), volume, url, scanlator, upload_date (epoch ms), branch,
pages, index.
MangaPage¶
A readable image page. Fields: url, headers (request headers required to
fetch the image, e.g. Referer). MangaPage.from_json also accepts a bare
string URL.
SearchPage¶
One page of results. Fields: entries (a list[Manga]), has_next_page.
MangaDetails¶
Full metadata plus chapters. Fields: manga (a Manga), chapters
(a list[MangaChapter]).
Library and system models¶
These appear in responses from library, downloads, and system endpoints:
HistoryEntry—manga,chapter_id,page,percent,updated_at.Category—id,title,manga_count.Download—id,source_id,manga_title,chapter_title,chapter_url,status,total_pages,completed_pages,failed_pages,file_path,error.DownloadSettings—max_concurrent_downloads,format.MangaPrefs—manga_id,reader_mode,brightness,contrast,saturation,hue,palette,present.GlobalSearchGroup—source_id,source_name,entries,error.Stats—total_chapters,distinct_manga,favourites_count,longest_streak_days,top_sources.BackupImportResult—ok,imported_favourites,imported_history.
See the API reference for the full autodoc, including
every field default and from_json behavior.