Skip to main content

anime-dl-core

English · Русский

CI PyPI Python License: MIT

Python library that turns an anime player embed link into direct video URLs: Aniboom, CVH (CdnVideoHub), Kodik, Sibnet, Animedia, AniLibria, VK Video and SovetRomantica.

The library does one thing: players. You give it an embed URL, you get back a list of streams (HLS / DASH / MP4) with resolutions and the headers without which the CDN will not serve the file. Everything else — search, catalogues, ratings — is deliberately out of scope; small optional helpers live in anime_dl_core.sources.

import anime_dl_core as ap

result = ap.extract("https://aniboom.one/embed/9G1MJ6NMV8z?episode=1&translation=30")

print(result.qualities)                     # [360, 480, 720, 1080]
stream = result.best(kind="hls")            # the 1080p stream
print(stream.url)                           # https://.../media_6.m3u8
print(stream.headers)                       # {'Referer': 'https://aniboom.one/', ...}
print(stream.ffmpeg_command("ep1.mp4"))     # ready-to-paste download command

Contents

Supported players

Player Name in the library Accepted input Returns Verified live
Aniboom aniboom https://aniboom.one/embed/<id> or the bare <id> HLS (master + per quality), DASH ✅
CVH (CdnVideoHub) cvh /cdn-iframe/<id>/<season>/<episode>?dubbing=<studio> or a numeric <id> HLS, DASH, MP4 144p–1080p ✅
Kodik kodik https://kodikplayer.com/seria|serial|video/<id>/<hash>/720p HLS and MP4 per quality + opening/ending timecodes ✅
Sibnet sibnet https://video.sibnet.ru/shell.php?videoid=<id> or <id> MP4 ✅
Animedia animedia https://aser.pro/vod/<id> or the bare <id> HLS (master + per quality) ✅
AniLibria (AniLiberty) anilibria release alias (bleach), bleach/3 or an episode URL HLS 480/720/1080 + timecodes ✅
VK Video vk embed, video URL or oid_id MP4 144p–2160p, HLS (master + qualities), DASH ✅
SovetRomantica sovetromantica /embed/episode_<id>_<episode>-<dubbed|subtitles> or the slug HLS + timecodes, poster, thumbnails, next episode ⚠️ site offline

"Verified live" means the player really returned working links during development, and a live test (pytest -m live) keeps it that way.

SovetRomantica: parsing is verified against real embed pages, but the team's own site is currently down — the sovetromantica.com domain changed hands and serves unrelated content, the CDN (scu*.sovetromantica.com) is switched off, and the team is raising money to relaunch. Examples and live tests therefore use a real page from the Wayback Machine; once the site is back, point the player at the new domain: SovetRomanticaPlayer(base_url="https://new-domain"). Their current releases are published on VK and are handled by the vk player.

Installation

pip install anime-dl-core                # plain install (requests only)
pip install "anime-dl-core[async]"       # + async mode (aiohttp)
pip install "anime-dl-core[socks]"       # + socks5 proxy support

From source, for development and the test suite:

git clone https://github.com/ialakey/anime-dl-core.git
cd anime-dl-core
pip install -e ".[async,dev]"

There is exactly one required dependency — requests. HTML is parsed with regular expressions, so neither bs4 nor lxml is needed.

Python 3.9+.

The same wheel and sdist are attached to every release, together with the SHA-256 of each file and the commit they were built from.

Quick start

import anime_dl_core as ap

# 1. The player is detected from the URL
result = ap.extract("https://kodikplayer.com/seria/1304528/932d5da818729ec5ccc9be7968ee3717/720p")

result.player          # 'kodik'
result.qualities       # [360, 480, 720]
result.translation     # '2x2'
result.skip_segments   # [SkipSegment(start=30, end=110, kind='opening'), ...]

# 2. Picking a stream
result.best()                       # highest quality
result.best(kind="mp4")             # direct files only
result.best(max_quality=480)        # nothing above 480p
result.master()                     # HLS master playlist (the player picks the quality)
result.filter("hls", quality=720)   # every matching stream

# 3. Downloading
stream = result.best(kind="mp4")
stream.url                          # direct link
stream.headers                      # Referer/User-Agent — required!
stream.ffmpeg_args("ep1.mp4")       # argument list for subprocess
stream.ffmpeg_command("ep1.mp4")    # the same as a single string

# 4. Everything as json
import json; print(json.dumps(result.to_dict(), ensure_ascii=False, indent=2))

If you hit the same player several times, go through the player object so the HTTP session is reused:

with ap.AnilibriaPlayer() as player:
    for number in range(1, 13):
        print(player.extract("bleach", episode=number).best(max_quality=720).url)

Data model

PlayerResult

Field Type Description
player str player name
source_url str what was parsed
streams list[Stream] streams that were found
title str | None title, when the player exposes one
poster str | None cover image
duration int | None duration in seconds
translation str | None dub / voice-over
skip_segments list[SkipSegment] opening / ending
extra dict everything player-specific

Methods: best(), filter(), master(), qualities, to_dict(). The object iterates over its streams and is falsy when there are none.

best(kind=None, max_quality=None, allow_master=True) returns the highest quality stream; on a tie it prefers mp4 (easiest to download), then hls, then dash. Master playlists (quality unknown) rank last and are only chosen when nothing else is available — allow_master=False excludes them entirely.

Stream

Field Description
url direct link
kind StreamKind.HLS / DASH / MP4
quality picture height (720), or None for a master playlist
headers headers that are mandatory while downloading
label caption ('720p', 'master', a dub name)
extra bitrate, codecs, the original response key, and so on

Methods: ffmpeg_args(output), ffmpeg_command(output), to_dict(), plus the is_master property.

The headers are not decoration. Sibnet, Kodik and Aniboom answer with 403 without the right Referer. Always pass stream.headers to your downloader:

requests.get(stream.url, headers=stream.headers, stream=True)

For yt-dlp use --referer; for ffmpeg, stream.ffmpeg_args(...) already inserts -headers.

SkipSegment

start, end (seconds from the start of the file), kind ('opening' / 'ending') and the duration property.

Player by player

Aniboom

from anime_dl_core import AniboomPlayer

with AniboomPlayer() as player:
    result = player.extract(
        "https://aniboom.one/embed/9G1MJ6NMV8z?episode=1&translation=30",
        referer="https://animego.org/",   # the default
        resolve_qualities=True,           # +1 request: expand master.m3u8 into qualities
    )
    print(result.qualities)               # [360, 480, 720, 1080]
    print(result.master().url)            # the master.m3u8
    print(result.filter("dash"))          # the MPD manifest

Also useful: AniboomPlayer.embed_url(video_id, episode=…, translation=…) and AniboomPlayer.video_id(url). result.extra carries video_id, max_quality, thumbnails (the vtt sprite sheet) and rating.

CVH (CdnVideoHub)

from anime_dl_core import CvhPlayer

with CvhPlayer() as player:
    # every episode and dub
    for episode in player.playlist("51019"):
        print(episode.season, episode.episode, episode.studio, episode.voice_type)

    # a specific episode; the dub name is matched loosely
    result = player.extract("51019", season=1, episode=3, studio="AniLibria")

    # given an iframe URL, season / episode / studio are taken from it
    result = player.extract("https://animego.me/cdn-iframe/51019/1/3?dubbing=AnilibriaTV")
    # the older shape, with the dub in the path, still works
    result = player.extract("https://animego.me/cdn-iframe/51019/AnilibriaTV/1/3")

Video is served by the Odnoklassniki CDN, so besides HLS/DASH you get direct mp4 files from 144p to 1080p. The publisher parameters are configurable: CvhPlayer(pub="747", aggr="mali") (the defaults are the ones AnimeGO uses).

Kodik

from anime_dl_core import KodikPlayer

with KodikPlayer() as player:
    result = player.extract(
        "https://kodikplayer.com/seria/1304528/932d5da818729ec5ccc9be7968ee3717/720p",
        # for /serial/... links you can pass the episode and season:
        # season=1, episode=5,
        include_mp4=True,     # add direct mp4 links (on by default)
    )
    print(result.best(kind="mp4").url)   # .../720.mp4
    print(result.skip_segments)          # opening and ending

No Kodik API token is required — the library works from the embed link an aggregator site hands out. Those links are time-limited (note the :2026090707 stamp in the path), so fetch them right before downloading.

If Kodik has rate-limited your IP the links come through a /s/m/ proxy host; result.extra["warnings"] then carries a warning, and the proxy= parameter fixes it.

Sibnet

from anime_dl_core import SibnetPlayer

with SibnetPlayer() as player:
    result = player.extract("2589828")             # the bare id works too
    result = player.extract(
        "https://video.sibnet.ru/shell.php?videoid=2589828",
        resolve=True,   # follow the redirect to the signed CDN address right away
    )

Without resolve=True you get the stable video.sibnet.ru/v/<hash>/<id>.mp4 link, which redirects to the CDN itself — that is the more reliable option, because the signed address is short-lived and bound to your IP.

Animedia

from anime_dl_core import AnimediaPlayer

with AnimediaPlayer() as player:
    result = player.extract("https://aser.pro/vod/20182")   # or just 20182
    print(result.qualities)          # [360, 720]
    print(result.best().url)         # .../hls/720/index.m3u8
    print(result.extra)              # {'vod_id': '20182', 'slug': '...', 'episode': 1}

Player links live on the title page at amd.online; the sources.Animedia helper collects them for you.

The old online.animedia.tv/embed/<id>/<season>/<episode> links that some aggregators still serve do not work: the domain answers with an endless redirect to itself. The current player address is aser.pro/vod/<id>.

AniLibria (AniLiberty)

from anime_dl_core import AnilibriaPlayer

with AnilibriaPlayer() as player:
    print(player.search("Bleach")[:1])                 # find the release alias
    print(len(player.episodes("bleach")))              # 354
    result = player.extract("bleach", episode=2)       # or "bleach/2", or an episode URL
    print(result.title, result.qualities, result.skip_segments)

This is not an embed player but the open anilibria.top/api/v1 API (no token needed). A mirror can be set with AnilibriaPlayer(api_base="https://aniliberty.top/api/v1").

VK Video

from anime_dl_core import VkPlayer

with VkPlayer() as player:
    # an anime episode in the SovetRomantica VK community
    result = player.extract("https://vk.com/video_ext.php?oid=-33905270&id=456239024")

    print(result.title)         # [субтитры | 08] Гримгар из пепла и фантазий ...
    print(result.qualities)     # [144, 240, 360, 480, 720]
    print(result.duration)      # 1440
    print(result.best(kind="mp4").url)

Every link shape is understood, no manual normalisation needed:

player.extract("https://vk.com/video_ext.php?oid=-33905270&id=456239024&hash=...")
player.extract("https://vkvideo.ru/video-33905270_456239024")
player.extract("-33905270_456239024")
VkPlayer.embed_url(-33905270, 456239024, access_key="abc")   # build an embed by hand

Notes:

  • resolve_qualities=True (default) expands the HLS master playlist into separate qualities, the same way Aniboom does;
  • "link only" videos need the hash from the embed code; private, deleted and geo-blocked videos raise ContentBlocked with an explanation;
  • live streams are parsed too — they only carry HLS, and result.extra["is_live"] marks them.

Both page formats are supported: the current one (apiPrefetchCache → video.get → files) and the legacy var playerParams with url720-style keys that some mirrors still serve.

SovetRomantica

The team's site is currently offline (see the table above), so the example uses a real embed page from the Wayback Machine:

from anime_dl_core import SovetRomanticaPlayer

archived = ("https://web.archive.org/web/20240905174049id_/"
            "https://sovetromantica.com/embed/episode_1073_1-dubbed")

with SovetRomanticaPlayer(base_url="https://web.archive.org") as player:
    result = player.extract(archived)

result.title            # 'Gekkan Shoujo Nozaki-kun - Озвучка - Эпизод 1'
result.translation      # 'Озвучка SovetRomantica'
result.best().url       # 'https://scu2.sovetromantica.com/.../episode_1.m3u8'
result.skip_segments    # [SkipSegment(174, 262, 'opening'), SkipSegment(1316, 1398, 'ending')]
result.extra["next_episode"]  # link to the next episode
result.extra["thumbnails"]    # vtt thumbnails for the timeline

Once the site is back (or if you have a mirror):

with SovetRomanticaPlayer(base_url="https://new-domain") as player:
    result = player.extract("episode_1073_1-dubbed")   # the slug is enough

base_url also allows the player to visit any host, which is what mirrors, the Wayback Machine and local copies need. If the page does not look like an embed — and that is exactly what the hijacked domain returns today — you get NoStreamsFound with an explanation.

Runnable script with both examples: examples/06_vk_sovetromantica.py.

A small AnimeGO helper ships with the library — just enough for an end-to-end scenario:

from anime_dl_core.sources import AnimeGo
import anime_dl_core as ap

with AnimeGo() as site:                    # AnimeGo(mirror="animego.me", proxy=...)
    anime = site.search("Магическая битва")[0]
    print(anime.id, anime.title, anime.original_title, anime.url)

    print(site.episodes(anime.id))         # {1: 'https://animego.org/player/videos/...', ...}

    for link in site.players(anime.id, episode=2):
        print(link.player, link.label, link.embed)
        # CVH      JAM CLUB     https://animego.me/cdn-iframe/40748/1/2?dubbing=Jam%20Club
        # AniBoom  JAM CLUB     https://aniboom.one/embed/9G1MJKRXV8z?episode=2...
        # Kodik    JAM CLUB     https://kodikplayer.com/seria/723706/...

    aniboom = next(link for link in site.players(anime.id, episode=2) if link.player == "AniBoom")
    result = site.resolve(aniboom)         # same as ap.extract(aniboom.embed)

Runnable script: examples/02_animego_pipeline.py.

The second helper is the Animedia site (amd.online):

from anime_dl_core.sources import Animedia
import anime_dl_core as ap

with Animedia() as site:                       # Animedia(base_url="https://new-domain")
    anime = site.search("Боруто")[0]
    print(site.info(anime.url).title)          # Боруто: Новое поколение Наруто

    episodes = site.episodes(anime.url)        # {1: 'https://aser.pro/vod/1067', ...}
    print(len(episodes))                       # 293

    print(site.players(anime.url))             # {'animedia': [...], 'kodik': [...]}

    result = ap.extract(episodes[1])           # direct video links

Both sites are Russian-language, so the search queries are in Russian too. The helpers are auxiliary and depend on site markup; the core of the library does not, and player links can come from anywhere.

Alloha: catalogue and iframe

Alloha (api.alloha.tv) is not a player in this library's sense but a source: given a Kinopoisk / IMDb / TMDb id or a title, it returns the description, the dubs, seasons with episodes and a ready iframe link.

from anime_dl_core.sources import Alloha

with Alloha() as alloha:                             # Alloha(token="your token")
    anime = alloha.find(name="Атака титанов")        # or find(kp=749374), find(imdb="tt2560140")
    anime.name, anime.year, anime.category           # ('Атака титанов', 2013, 'сериал')
    anime.seasons                                    # {1: [1..25], 2: [...], 3: [...], 4: [...]}
    [t.name for t in anime.translations]             # ['DEEP', 'Субтитры', 'Anilibria', ...]

    # each episode has its own set of dubs
    voices = alloha.translations_for(anime, season=1, episode=1)
    alloha.iframe(anime, season=1, episode=1, translation=voices[0].name)
    # 'https://.../?token_movie=...&translation=10&season=1&episode=1&token=...'

Alloha does not expose direct video links. Its player fetches them over a WebSocket from a heavily obfuscated bundle — they are in neither the HTML nor the open HTTP API. So Alloha returns an iframe URL: embed it in a page or open it in a browser/webview. If you need the files themselves, a headless browser is the only way; plain HTML parsing will not get you there.

The API has a public token (sources.alloha.PUBLIC_TOKEN) which is used by default. If it stops working, pass your own: Alloha(token="...").

Runnable script with Animedia and Alloha: examples/07_animedia_alloha.py.

Async

pip install "anime-dl-core[async]"
import asyncio
import anime_dl_core as ap

async def main():
    # different players in parallel
    results = await asyncio.gather(
        ap.extract_async("https://aniboom.one/embed/9G1MJ6NMV8z"),
        ap.extract_async("https://video.sibnet.ru/shell.php?videoid=2589828"),
    )

    # one player, many episodes — a single session for all of them
    async with ap.CvhPlayer() as player:
        streams = await asyncio.gather(
            *(player.aextract("51019", episode=n, studio="AniLibria") for n in range(1, 5))
        )

asyncio.run(main())

Every player has an async twin: aextract(), aplaylist(), arelease(), afetch(). With async with nothing has to be closed by hand; otherwise call await player.aclose().

Command line

anime-dl-core --list                       # which players are supported
anime-dl-core https://aniboom.one/embed/9G1MJ6NMV8z
anime-dl-core 51019 --player cvh --episode 2 --studio AniLibria
anime-dl-core bleach --player anilibria --episode 1 --best --max-quality 720
anime-dl-core <url> --json                 # machine-readable output
anime-dl-core <url> --ffmpeg ep1.mp4       # ready-made ffmpeg command
anime-dl-core <url> --kind mp4 --proxy socks5://127.0.0.1:9050
anime-dl-core "https://vk.com/video_ext.php?oid=-33905270&id=456239024" --best --kind mp4
anime-dl-core -33905270_456239024 --json   # VK also takes the bare id

Without installing: python -m anime_dl_core <url>.

Sample output:

Player: kodik
Translation: 2x2
Skip: opening 30-110s, ending 1375-1445s
Streams (6):
  [hls    360p] https://cloud.solodcdn.com/.../360.mp4:hls:manifest.m3u8
  [mp4    360p] https://cloud.solodcdn.com/.../360.mp4
  ...
Headers required for downloading:
  Referer: https://kodikplayer.com/
  User-Agent: Mozilla/5.0 ...

The CLI output, docstrings and error messages are in English. Values that come from the sites themselves stay as those sites spell them: titles, dub names, and the Alloha category field are returned verbatim in Russian.

Proxies, headers, timeouts

The same parameters work in extract() and in any player's constructor:

ap.extract(url, proxy="socks5://user:pass@host:1080", timeout=30)
ap.extract(url, user_agent="Mozilla/5.0 ...", headers={"Accept-Language": "ru-RU"})

with ap.KodikPlayer(proxy="http://127.0.0.1:8080", timeout=15) as player:
    ...

socks5 needs the [socks] extra. You can also pass a ready client:

from anime_dl_core import HttpClient
client = HttpClient(proxy="http://127.0.0.1:8080", timeout=10)
result = ap.AniboomPlayer(client).extract(url)

proxy, timeout, user_agent, headers and client always go to the HTTP client; everything else (episode, season, studio, referer, resolve, resolve_qualities, include_mp4) goes to the player.

Writing your own player

from anime_dl_core import BasePlayer, PlayerResult, Stream, StreamKind, register
from anime_dl_core.utils import search

@register
class MyPlayer(BasePlayer):
    name = "myplayer"
    title = "My Player"
    domains = ("myplayer.example",)
    playback_headers = {"Referer": "https://myplayer.example/"}

    def extract(self, url, **kwargs):
        page = self.client.get(url).raise_for_status()
        playlist = search(r'file:"([^"]+\.m3u8)"', page.text, what="m3u8 link")
        return PlayerResult(
            player=self.name,
            source_url=url,
            streams=[Stream(playlist, StreamKind.HLS, None, dict(self.playback_headers))],
        )

ap.extract("https://myplayer.example/embed/1")   # works already

Full example: examples/05_custom_player.py.

Errors

Every exception inherits from AnimeDlCoreError:

Exception Raised when
UnsupportedUrl the URL matches no player
NetworkError timeout, dropped connection, unreachable proxy
ServiceError the server answered with something unexpected (has .status, .url)
ExtractionError a response arrived but could not be parsed — the player changed its markup
NoStreamsFound the page parsed fine but carries no video links
DecryptionError a Kodik link could not be decrypted
ContentBlocked geo block, age restriction, rights holder
NotFound no such episode / dub / release
try:
    result = ap.extract(url)
except ap.ContentBlocked:
    result = ap.extract(url, proxy="socks5://...")
except ap.AnimeDlCoreError as error:
    print("failed:", error)

Tests

pip install -e ".[dev]"     # from a source checkout

pytest                                      # 86 offline tests, no network
ANIME_DL_CORE_LIVE=1 pytest -m live         # 18 live tests (bash)
$env:ANIME_DL_CORE_LIVE=1; pytest -m live   # the same in PowerShell

Offline tests run the parsers against real player responses saved in tests/fixtures/ — including a genuine encrypted Kodik response, so decryption is exercised for real. Live tests hit the internet and may fail when a particular title is pulled from a site; that is not a library regression, just update the constants at the top of tests/test_live.py.

How it works inside

src/anime_dl_core/
    __init__.py       public API
    registry.py       player registry, extract() / extract_async()
    base.py           BasePlayer: clients, URL matching, lifecycle
    models.py         Stream, PlayerResult, SkipSegment, StreamKind
    http.py           HttpClient (requests) and AsyncHttpClient (aiohttp), one Response
    utils.py          html/js parsing, m3u8, Kodik link decryption
    errors.py         exception hierarchy
    cli.py            command line
    players/          one file per player
    sources/          optional helpers (AnimeGO, Animedia, Alloha)

Parsing is decoupled from fetching: the sync and async methods perform the same steps and call the same parsing functions, so they behave identically.

How the players work, briefly:

  • Aniboom — the <video data-parameters="..."> tag holds html-escaped json with the MPD and M3U8 links. The master playlist is additionally expanded into separate qualities.
  • CVH — an open API: /playlist?pub=&aggr=&id= lists every episode and dub, /video/<vkId> returns the streams (Odnoklassniki CDN, keys such as mpegHighUrl = 720p, mpegFullHdUrl = 1080p).
  • Kodik — three steps: the embed page carries urlParams with one-off signatures and vInfo with the id/hash; the player script hides the endpoint (/ftor) behind atob(); a POST with the signatures returns links encoded as base64 with a Caesar shift, and the shift is brute-forced and cached. One important detail: the ref parameter must be url-decoded — with an empty value the server answers 500.
  • Sibnet — a relative mp4 link inside player.src([...]); the file is only served with a Referer.
  • AniLibria — the API returns ready hls_480/720/1080 links plus opening and ending timecodes.
  • Animedia — the aser.pro/vod/<id> page boils down to one useful line, new Playerjs({file: "...index.m3u8"}); every file format Playerjs understands is supported (a single link, [720]url1,[360]url2, a json playlist).
  • VK Video — video_ext.php puts an apiPrefetchCache object into window.cur with a prefetched video.get response; its files hold mp4_144…mp4_2160, hls_ondemand and dash_ondemand. The legacy var playerParams format is the fallback.
  • SovetRomantica — the player config at the end of the page: var config={...} with file/poster/title/thumbnails (not valid json — it contains js variables, so the fields are extracted one by one) and var skips=[...], which yields the opening and the ending.

Limitations

  • Players change without warning. When something breaks, the error is specific (ExtractionError naming what was not found), and the fix is a regex in the corresponding players/*.py.
  • Video links are short-lived and often bound to your IP, so caching them for long is pointless — fetch them right before downloading.
  • Some services are unavailable from certain countries; use proxy=.
  • The library downloads nothing by itself and bypasses no paywalls: it reads the same data an ordinary web player reads in a browser. What you do with it is on you — respect copyright and the terms of the sites you use.

Release process

Releases are cut by CI from a v* tag: GitHub release with artifacts and their SHA-256, then the upload to PyPI. The steps, and the one-time PyPI setup, are in docs/releasing.md. Version history: CHANGELOG.md.

License

MIT — see LICENSE.

Metadata

Release files for anime-dl-core 0.5.1

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

Source distribution (sdist)

Source distribution for anime-dl-core 0.5.1
File Size Uploaded
anime_dl_core-0.5.1.tar.gz 131.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for anime-dl-core 0.5.1
File Interpreter ABI Platform
anime_dl_core-0.5.1-py3-none-any.whl Python 3 none any Details

Total release size: 199.0 kB

Release files / anime_dl_core-0.5.1.tar.gz

Download URL anime_dl_core-0.5.1.tar.gz
Size 131.1 kB
Tags Source
SHA-256 checksum
How to use checksums
dfc92bf287639e7abee4dbe5b974af94f9f7a2f18f953cbb3c4cc7ea16981797
BLAKE2b-256 checksum
How to use checksums
916c7fd6510e4adf2902820acb5f1916b9c1eb3156d3edca9b07284021d1164e
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 20, 2026.

Transparency log

Release files / anime_dl_core-0.5.1-py3-none-any.whl

Download URL anime_dl_core-0.5.1-py3-none-any.whl
Size 67.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
108d5944efffbd35fcbc2678b2b79c3447197bd7bfaf3955c6723b25281de85b
BLAKE2b-256 checksum
How to use checksums
e4b82b7914afe7c79b3b3d3d6a7ee185878a31e7b6b60256d6e58dcc64702082
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 20, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.5.1 This release

2 release files

0.5.0

2 release files

0.4.1

2 release files

0.4.0

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