Skip to main content

pymal

Programmatic access to MyAnimeList data in Python. Objects are lazy-loading — MAL is only contacted when you first access a property.


Quick start

from pymal import anime

# Lazy — no network call yet
a = anime.Anime(52991)

# First property access triggers the MAL fetch
print(a.title)    # "Sousou no Frieren"
print(a.score)    # 9.07
print(a.episodes) # 28
print(a.genres)   # {'Adventure': '...', 'Drama': '...', 'Fantasy': '...'}
print(a.english)  # "Frieren: Beyond Journey's End"
print(a.japanese) # "葬送のフリーレン"

Installation

curl -LsSf https://astral.sh/uv/install.sh | sh   # install uv once

git clone https://github.com/varyg1001/pymal
cd pymal
uv sync

With pip

git clone https://github.com/varyg1001/pymal
cd pymal
pip install -e .

Requirements

  • Python >=3.10, <3.15
  • uv (recommended) or pip

Key runtime dependencies (full list in pyproject.toml):

Package Purpose
niquests[socks,utls] HTTP client (modern drop-in for requests)
beautifulsoup4 + lxml HTML parsing
singleton-factory Object singleton lifecycle

Search & Endpoint Features

  • Search API: Search providers (SearchAnimesProvider, SearchMangasProvider) automatically query MyAnimeList's modern prefix.json API endpoint (/search/prefix.json), falling back gracefully if needed.
  • Seasons: Seasonal anime lookups (Season, Seasons) scrape directly from native MyAnimeList season pages (/anime/season/<year>/<season>) and the archive listing (/anime/season/archive).
  • User Lists: Account anime and manga lists (AccountAnimes, AccountMangas) utilize MAL's modern JSON list endpoints (load.json).

Running tests

# Offline suite — no network or account needed (40 tests)
uv run pytest tests/test_fixes.py -v

# Full suite — account tests auto-skip unless credentials are set
MAL_USERNAME=you MAL_PASSWORD=secret uv run pytest -v

Project structure

pymal/
├── pymal/
│   ├── anime.py                  # Anime object
│   ├── manga.py                  # Manga object
│   ├── account.py                # MAL account & auth
│   ├── global_functions.py       # HTTP + HTML parsing helpers
│   ├── account_objects/          # MyAnime, MyManga, lists, friends
│   ├── searches/                 # Search providers
│   └── inner_objects/            # Season, recommendation, etc.
├── tests/
│   ├── test_fixes.py             # Offline test suite (40 tests)
│   └── account_objects/          # Live account tests (skipped without creds)
├── docs/                         # MkDocs documentation source
├── mkdocs.yml                    # Docs config (GitHub Pages)
├── pyproject.toml                # Build config & pinned deps (uv_build)
└── uv.lock                       # Lockfile — commit this

What changed in v1.0.0

The original project (v0.5b4–v0.6) had broken against MAL's HTML updates and modern Python. v1.0.0 brings it back to life:

# Area Fix
1 Parser html5lib → lxml (no more six conflict)
2 HTTP requests → niquests[socks,utls] (HTTP/2, QUIC, modern TLS)
3 Sidebar Full rewrite from brittle index-based to label-based lookup (span.dark_text)
4 Title Fixed IndexError — MAL now wraps <h1> content in <strong>
5 Table Fixed AttributeError — MAL removed <tbody> from tables
6 Search Migrated from legacy anime.php to MAL's modern prefix.json API
7 Seasons Migrated from dead malupdater.com to native MAL /anime/season pages
8 User Lists Updated AccountAnimes & AccountMangas to MAL's load.json API
9 Build setup.py → uv_build + pyproject.toml
10 Tests New offline suite with 40 tests; account tests skip without credentials
11 Docs Migrated from Sphinx/RST to MkDocs Material (GitHub Pages)
12 Cleanup Removed .travis.yml, MANIFEST.in, upload_new_version.bat, dead HTML fixtures

Also fixed latent bugs: == used instead of = in my_anime.py and my_manga.py meant download_episodes and times_rewatched were never actually stored.


Credits

Original authors

pymal was created and developed by:

Original repository: pymal-developers/pymal

v1.0.0

The update was made with mostly AI. The main reason for the update is the errors cause by the old things used in the last released version. I still feel that this is the easiest way to get info from MAL, even with the original version, since MAL has not changed much.


License

BSD License — see original repository for full text.

Metadata

Release files for pymal-ng 1.0.0

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

Source distribution (sdist)

Source distribution for pymal-ng 1.0.0
File Size Uploaded Provenance Actions
pymal_ng-1.0.0.tar.gz 29.7 kB With provenance Details for pymal_ng-1.0.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for pymal-ng 1.0.0
File Interpreter ABI Platform Actions
pymal_ng-1.0.0-py3-none-any.whl Python 3 none any Details for pymal_ng-1.0.0-py3-none-any.whl

Total release size: 73.7 kB

Release files / pymal_ng-1.0.0.tar.gz

Download URL pymal_ng-1.0.0.tar.gz
Size 29.7 kB
Tags Source
SHA-256 checksum
How to use checksums
a1cdac708f30093f22e231ed145a3f4152aeaf4513d1d46561803774c9517866
BLAKE2b-256 checksum
How to use checksums
779e63e73a83d36de77d76f7e43e326a8303bb0f7d678ae8a2802b696fedfbdd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 Oct 23, 2026.

Transparency log

Release files / pymal_ng-1.0.0-py3-none-any.whl

Download URL pymal_ng-1.0.0-py3-none-any.whl
Size 44.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8f4a051546e6595670ba46cfa31f7148fc14b6a5a5062951acf72919a59de445
BLAKE2b-256 checksum
How to use checksums
132b2f4bdf35202b2ac8f8bd9cb32e242b6af54310871abe1a1b1545d7fb3d22
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 Oct 23, 2026.

Transparency log

Security for pymal-ng 1.0.0

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.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for pymal_ng-1.0.0.tar.gz

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 Oct 23, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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