Python client to search and download torrents from nyaa.si
Project description
nyaa-downloader
Python package to search and download torrents from nyaa.si.
Installation
pip install nyaa-downloader
On Windows, libtorrent (for direct content download) is installed automatically via libtorrent-windows-dll.
Dependencies: requests, feedparser, anitopy, libtorrent (optional on non-Windows, for direct torrent content download)
Quick Start
from nyaa_downloader import NyaaAnime, Preferences
# Simple search
nyaa = NyaaAnime.search("Jujutsu Kaisen", trusted_only=True)
# Enrich with MAL metadata (seasons, episode counts)
nyaa.enrich_from_mal()
# Get a season
s2 = nyaa.season(2)
# Get episode 1 of season 2
ep1 = s2.get(1)
print(f"Title: {ep1.title}")
print(f"Seeders: {ep1.seeders}")
API Reference
NyaaAnime
Main interface for searching anime torrents.
NyaaAnime.search(title, trusted_only=False, category="1_2", max_pages=1, filters=None)
Search for an anime on Nyaa.
from nyaa_downloader import NyaaAnime, SearchFilters
# Basic search
nyaa = NyaaAnime.search("Sousou no Frieren")
# Search with advanced filters
filters = SearchFilters(
min_seeders=50,
resolution="1080p",
exclude_batches=True
)
nyaa = NyaaAnime.search("Jujutsu Kaisen",
trusted_only=True,
max_pages=2, # More results
filters=filters
)
| Parameter | Type | Description |
|---|---|---|
title |
str |
Anime title |
trusted_only |
bool |
Only trusted releases |
category |
str |
Nyaa category (default: "1_2" = Anime English) |
max_pages |
int |
Pages to fetch (1 ≈ 75 results) |
filters |
SearchFilters |
Advanced filters |
nyaa.enrich_from_mal(mal_id=None)
Enrich results with MyAnimeList metadata (seasons, episodes).
nyaa = NyaaAnime.search("Jujutsu Kaisen")
nyaa.enrich_from_mal()
print(f"MAL ID: {nyaa.mal_id}")
print(f"Total episodes: {nyaa.total_episodes}")
print(f"Season info: {nyaa._season_episodes_info}")
# Example: {1: (1, 24), 2: (25, 47)} → S1: eps 1-24, S2: eps 25-47
nyaa.season(season_number)
Returns results for a given season.
s1 = nyaa.season(1)
s2 = nyaa.season(2)
print(f"S1: {len(s1.episodes)} results")
print(f"S2: {len(s2.episodes)} results")
nyaa.seasons
Full mapping {season_number: SeasonResults}.
for season_num, season_results in nyaa.seasons.items():
print(f"Season {season_num}: {len(season_results.episodes)} releases")
nyaa.to_relative_episode(absolute_ep, season) / nyaa.to_absolute_episode(relative_ep, season)
Convert between absolute and relative episode numbering.
# Jujutsu Kaisen S2 starts at episode 25
nyaa.to_relative_episode(25, 2) # → 1 (S2E1)
nyaa.to_absolute_episode(1, 2) # → 25
nyaa.download_torrent(result, dest_dir="torrents")
Download the .torrent file.
s2 = nyaa.season(2)
ep1 = s2.get(1)
path = nyaa.download_torrent(ep1, "my_torrents")
SeasonResults
Results for a given season.
season.get(episode_number, preferences=None)
Returns the best torrent for an episode.
from nyaa_downloader import Preferences
s2 = nyaa.season(2)
# Best by seeders
ep1 = s2.get(1)
# With preferences
prefs = Preferences(
preferred_resolution="1080p",
preferred_release_groups=["SubsPlease", "Erai-raws"],
min_seeders=10
)
ep1 = s2.get(1, preferences=prefs)
NyaaSearcher
Low-level client for direct searching.
from nyaa_downloader import NyaaSearcher, SearchFilters
searcher = NyaaSearcher(timeout=60)
# Simple search
results = searcher.search("Frieren", trusted_only=True)
# Paginated search
for page_results in searcher.search_paginated("Jujutsu Kaisen", max_pages=3):
print(f"Page: {len(page_results)} results")
# Full search
all_results = searcher.search_all("Oshi no ko", max_pages=5)
# With filters
filters = SearchFilters(
min_seeders=100,
resolution="1080p",
exclude_batches=True
)
filtered = searcher.search("Frieren", filters=filters)
SearchFilters
Advanced search filters.
from nyaa_downloader import SearchFilters
from datetime import datetime
filters = SearchFilters(
min_seeders=50, # Minimum seeders
max_seeders=None, # Maximum seeders
min_size_mb=100, # Minimum size in MB
max_size_mb=2000, # Maximum size in MB
trusted_only=True, # Trusted only
batches_only=False, # Batches only
exclude_batches=True, # Exclude batches
resolution="1080p", # Preferred resolution
release_group="SubsPlease", # Release group
date_after=datetime(2024, 1, 1), # After this date
date_before=None, # Before this date
)
Preferences
Preferences for sorting results.
from nyaa_downloader import Preferences
prefs = Preferences(
preferred_resolution="1080p", # Preferred resolution
preferred_release_groups=["SubsPlease"], # Preferred groups
excluded_release_groups=["HorribleSubs"], # Excluded groups
min_seeders=10, # Minimum seeders
prefer_trusted=True, # Prefer trusted
)
# Score a result
score = prefs.score(result) # Lower = better
# Sort a list
sorted_results = prefs.sort_results(results)
download_torrent(result, dest_dir, timeout=30, retry_config=None)
Download a .torrent file.
from nyaa_downloader import download_torrent, RetryConfig
# Simple
path = download_torrent(result, "torrents")
# With custom retry
config = RetryConfig(max_retries=5, base_delay=2.0)
path = download_torrent(result, "torrents", timeout=60, retry_config=config)
TorrentSession (optional, requires libtorrent)
Direct torrent content download.
from nyaa_downloader import TorrentSession, TorrentConfig, download_torrent_content
# Optimized configuration
config = TorrentConfig(
connections_limit=300,
cache_size=1024, # 16MB cache
sequential_download=True, # For streaming
)
# Usage with context manager
with TorrentSession(config) as session:
handle = session.add_torrent(magnet_link, save_path)
def on_progress(progress):
print(f"[{progress.state}] {progress.progress:.1f}% - "
f"↓{progress.download_rate//1024}KB/s - "
f"Peers: {progress.num_peers}")
await session.wait_for_download(handle, on_progress)
# Or directly
await download_torrent_content(magnet_link, "downloads", config)
Exceptions
from nyaa_downloader import (
NyaaError, # Base exception
NetworkError, # Network error (timeout, connection)
DownloadError, # Download error
ParseError, # RSS parsing error
RateLimitError, # API rate limit
RetryConfig, # Retry configuration
)
try:
results = searcher.search("anime")
except NetworkError as e:
print(f"Network error: {e}")
except ParseError as e:
print(f"Parse error: {e}")
CLI
# Basic search
nyaa-downloader "Sousou no Frieren"
# Trusted only, download best result
nyaa-downloader "Jujutsu Kaisen" --trusted-only --best
# Limit results
nyaa-downloader "Frieren" --limit 20
# Custom destination folder
nyaa-downloader "Oshi no ko" --dest ./my_torrents
Result Structure
NyaaResult
@dataclass
class NyaaResult:
title: str # Full title
link: str # .torrent URL
magnet: Optional[str] # Magnet link
size: str # Size (e.g. "1.4 GiB")
date: str # Publication date
seeders: int # Seeder count
leechers: int # Leecher count
downloads: int # Total downloads
trusted: bool # Trusted release
anime_title: Optional[str] # Parsed anime title
episode: Optional[str] # Parsed episode number
release_group: Optional[str] # Group (e.g. "SubsPlease")
resolution: Optional[str] # Resolution (e.g. "1080p")
source: Optional[str] # Source (e.g. "WEB-DL")
season: Optional[int] # Detected season
parsed_episode: ParsedEpisode # Parsed episode object
is_batch: bool # Is a batch
ParsedEpisode
@dataclass
class ParsedEpisode:
episode: Optional[int] # Single episode
episode_range: Optional[Tuple[int, int]] # Range (1, 12)
is_batch: bool # Is a batch
def contains(self, ep: int) -> bool # Episode is in range
def episodes(self) -> List[int] # List of episodes
def sort_key(self) -> Tuple[int, int] # For sorting
Full Example
from nyaa_downloader import NyaaAnime, Preferences, SearchFilters
# Search with filters
filters = SearchFilters(min_seeders=100, resolution="1080p")
nyaa = NyaaAnime.search("Jujutsu Kaisen",
trusted_only=True,
max_pages=2,
filters=filters
)
# Enrich with MAL
nyaa.enrich_from_mal()
print(f"Detected seasons: {list(nyaa.seasons.keys())}")
# Download preferences
prefs = Preferences(
preferred_resolution="1080p",
preferred_release_groups=["SubsPlease"],
)
# Download S2E1
s2 = nyaa.season(2)
ep1 = s2.get(1, preferences=prefs)
if ep1:
print(f"Choice: {ep1.title}")
print(f"Group: {ep1.release_group}")
print(f"Resolution: {ep1.resolution}")
print(f"Seeders: {ep1.seeders}")
# Download
path = nyaa.download_torrent(ep1, "torrents")
print(f"Downloaded: {path}")
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nyaa_downloader-1.0.1.tar.gz.
File metadata
- Download URL: nyaa_downloader-1.0.1.tar.gz
- Upload date:
- Size: 24.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
542ffdeba86b83e2eddb40669dd2f00851d5b6ef35ea1e06c99928f7ad81f24e
|
|
| MD5 |
15c5833da992c5d5eb4914fd2ef4efa0
|
|
| BLAKE2b-256 |
913fe21f1626d66d8c96d5246448357c0100c5e5c94322a04e3a32a04fa2ada9
|
Provenance
The following attestation bundles were made for nyaa_downloader-1.0.1.tar.gz:
Publisher:
publish.yml on matth-blt/nyaa-downloader
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nyaa_downloader-1.0.1.tar.gz -
Subject digest:
542ffdeba86b83e2eddb40669dd2f00851d5b6ef35ea1e06c99928f7ad81f24e - Sigstore transparency entry: 969976033
- Sigstore integration time:
-
Permalink:
matth-blt/nyaa-downloader@f905747826b1d1e69f91141d0c3bd819d4fdd8b2 -
Branch / Tag:
refs/tags/v1.0.1 - Owner: https://github.com/matth-blt
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f905747826b1d1e69f91141d0c3bd819d4fdd8b2 -
Trigger Event:
release
-
Statement type:
File details
Details for the file nyaa_downloader-1.0.1-py3-none-any.whl.
File metadata
- Download URL: nyaa_downloader-1.0.1-py3-none-any.whl
- Upload date:
- Size: 26.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d8cc4ad95acfa86307a7cd81d61670766dee5fbae25a372d1ca51877dff8c2e0
|
|
| MD5 |
c613ed1989417d394569b2aff1a7b0ab
|
|
| BLAKE2b-256 |
62383f2e39c800277a81d0584632e87aefe6d57efa42fa2151aeb16b760659b0
|
Provenance
The following attestation bundles were made for nyaa_downloader-1.0.1-py3-none-any.whl:
Publisher:
publish.yml on matth-blt/nyaa-downloader
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nyaa_downloader-1.0.1-py3-none-any.whl -
Subject digest:
d8cc4ad95acfa86307a7cd81d61670766dee5fbae25a372d1ca51877dff8c2e0 - Sigstore transparency entry: 969976141
- Sigstore integration time:
-
Permalink:
matth-blt/nyaa-downloader@f905747826b1d1e69f91141d0c3bd819d4fdd8b2 -
Branch / Tag:
refs/tags/v1.0.1 - Owner: https://github.com/matth-blt
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f905747826b1d1e69f91141d0c3bd819d4fdd8b2 -
Trigger Event:
release
-
Statement type: