IMDBx
IMDBx - Titles, ratings, air dates, descriptions and cover art across every episode of any IMDb TV series.
Install
pip install IMDBx
Chromium is downloaded automatically the first time you run a scrape — no extra setup needed.
For development (includes pytest, ruff, coverage):
pip install "IMDBx[dev]"
Quick start
from imdbx import title
t = title("tt7441658") # Black Clover, all seasons
print(t) # Black Clover [tt7441658] — 4 seasons, 170 episodes
for season_num, episodes in t:
for ep in episodes:
print(ep) # S1.E1 · Asta and Yuno [7.6/10 (1.6K)]
Python API
from imdbx import title, season, episode, metadata, load
title() — full series
t = title("tt7441658")
t = title("tt7441658", seasons=[1, 2]) # specific seasons only
t = title("tt7441658", download_images=True) # also save cover art
t = title("tt7441658", pool_size=8) # more concurrency
print(t.meta.series_name) # "Black Clover"
print(t.meta.imdb_rating) # "8.2/10"
print(t.meta.tags) # ["Anime", "Action", "Adventure", …]
print(t.meta.years) # "2017–2021"
print(t.meta.content_rating) # "TV-PG"
all_eps = t.all_episodes() # flat list of every Episode
ep = t.get_episode(1, 1) # Episode S1E1
t.save("black_clover.json") # dump to JSON
season() — single season
eps = season("tt7441658", 1) # list[Episode] for season 1
for ep in eps:
print(ep.title, ep.rating)
episode() — single episode
ep = episode("tt7441658", 1, 1) # Season 1, Episode 1
print(ep.episode_code) # "S1.E1"
print(ep.title) # "Asta and Yuno"
print(ep.rating) # "7.6/10 (1.6K)"
print(ep.air_date) # "Tue, Oct 3, 2017"
print(ep.description) # plot summary
print(ep.cover_image) # CDN URL
print(ep.imdb_url) # full IMDBx page URL
metadata() — series info only (fast, no browser)
m = metadata("tt7441658")
print(m.series_name) # "Black Clover"
print(m.type) # "TV Series"
print(m.years) # "2017–2021"
print(m.content_rating) # "TV-PG"
print(m.episode_duration) # "24m"
print(m.imdb_rating) # "8.2/10"
print(m.rating_count) # "47K"
print(m.popularity) # "529"
print(m.tags) # ["Japanese", "Anime", "Action", …]
load() — reload a saved JSON file
t = load("black_clover.json")
print(t.meta.series_name)
Data classes
Episode
| Field | Type | Description |
|---|---|---|
episode_code |
str |
Short code, e.g. "S1.E1" |
title |
str |
Episode title |
season |
int |
Season number (1-indexed) |
episode |
int |
Episode number within the season (1-indexed) |
air_date |
str |
Original air date, e.g. "Tue, Oct 3, 2017" |
description |
str |
Plot summary |
rating |
str |
IMDBx rating, e.g. "7.6/10 (1.6K)" |
cover_image |
str | None |
CDN URL of the episode thumbnail |
cover_image_local |
str | None |
Local file path after --download-images |
imdb_url |
str |
Full IMDBx episode page URL |
SeriesMetadata
| Field | Type | Description |
|---|---|---|
title_id |
str |
IMDBx title ID, e.g. "tt7441658" |
series_name |
str |
Series title |
type |
str | None |
Content type, e.g. "TV Series" |
years |
str | None |
Run years, e.g. "2017–2021" |
content_rating |
str | None |
Audience rating, e.g. "TV-PG" |
episode_duration |
str | None |
Typical episode length, e.g. "24m" |
imdb_rating |
str | None |
Aggregate rating, e.g. "8.2/10" |
rating_count |
str | None |
Number of ratings, e.g. "47K" |
popularity |
str | None |
IMDBx popularity rank |
tags |
list[str] |
Genre and style tags |
CLI
After installing, the imdbx command is available system-wide:
imdbx tt7441658 # Black Clover, all seasons
imdbx tt0903747 # Breaking Bad
imdbx tt7441658 --seasons 1 2 # specific seasons only
imdbx tt7441658 --output out.json # save results to a JSON file
imdbx tt7441658 --download-images # also download cover art to ./images/
imdbx tt7441658 --images-dir ~/pics # download cover art to a custom directory
imdbx tt7441658 --meta-only # series metadata only — no browser needed
imdbx --load out.json # display a previously saved JSON file
imdbx tt7441658 --pool-size 8 # increase concurrency for faster scraping
imdbx tt7441658 --debug # verbose output: HTTP, browser events, timing
--test — testing mode
# Run the full offline unit-test suite (no network required)
imdbx --test
# Live end-to-end smoke test — fetches real data and checks key fields
imdbx --test tt7441658
imdbx --test tt0903747
--test alone runs pytest on the bundled test suite and exits with pytest's return code (0 = all passed). Requires pip install "IMDBx[dev]".
--test <TITLE_ID> hits the real IMDBx API, verifies that metadata and episode data are populated correctly, and prints a coloured ✓/✗ summary. Requires a network connection and Playwright/Chromium.
Architecture
imdbx/
├── __init__.py ← public API (title, season, episode, metadata, load)
├── models.py ← dataclasses (TitleInfo, SeriesMetadata, Episode)
├── cli.py ← imdbx command — all flags with full help text
├── _scraper.py ← orchestration: coordinates HTTP + browser + images
├── _http.py ← niquests connection pool + async image downloader
├── _browser.py ← Playwright pool + "Show more" expansion detection
├── _parse.py ← BeautifulSoup parsers (zero hardcoded class names)
├── _display.py ← terminal colour output
└── _log.py ← shared ANSI colour helpers + debug flag
tests/
├── test_models_episode_dataclass.py ← Episode field and repr tests
├── test_models_series_title_info.py ← TitleInfo + save/load round-trip
├── test_parse_episode_cards.py ← HTML → Episode parsing
├── test_parse_series_metadata.py ← HTML → SeriesMetadata parsing
└── test_http_session_and_load.py ← HTTP session and JSON load tests
Three-layer hybrid approach:
- Layer 1 (niquests): lightweight HTTP for metadata, season counts, and image downloads
- Layer 2 (Playwright): headless Chromium for JS-rendered episode pages with "Show more" expansion
- Layer 3 (async): concurrent cover-image fetching via
niquests.AsyncSession
Running tests
Tests require a source checkout:
git clone https://github.com/ENC4YP7ED/IMDBx
cd IMDBx
pip install -e ".[dev]"
# Via pytest directly
pytest
# Via the CLI — same result
imdbx --test
# Live smoke test against a real title (network + Chromium required)
imdbx --test tt7441658
Contributing
- Fork the repository
- Create a feature branch:
git checkout -b feat/my-change - Install dev dependencies:
pip install -e ".[dev]" - Make your changes and add tests
- Verify everything passes:
imdbx --test - Open a pull request
Changelog
1.1.5
- Added changelog to README
1.1.4
imdbx.__version__now reflects the installed package version viaimportlib.metadata
1.1.3
- Fixed
AttributeError: type object 'C' has no attribute 'BRED'that crashedimdbx --testand smoke-test error output
1.1.2
- Fixed
air_dateparsing returning episode title prefix alongside the date (e.g.S1.E1 ∙ PilotSun, Jan 20, 2008); inlinespan/timeelements are now searched beforedivcontainers
1.1.1
- Fixed
imdbx --testfrom a PyPI install incorrectly resolving to another package'stests/directory - Fixed
SyntaxErroron Python 3.10/3.11 caused by backslash inside f-string expressions
1.1.0
- Switched scraping target from imdbx.com to imdb.com
- Fixed genre tag deduplication and filtering of IMDb navigation links
- Initial public release
License
MIT — see LICENSE for details.
Metadata
Release files for IMDBx 1.1.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| imdbx-1.1.5.tar.gz | 33.4 kB | With provenance | Details for imdbx-1.1.5.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| imdbx-1.1.5-py3-none-any.whl | Python 3 | none | any | Details for imdbx-1.1.5-py3-none-any.whl |
Total release size: 64.9 kB
Release files / imdbx-1.1.5.tar.gz
| Download URL | imdbx-1.1.5.tar.gz |
|---|---|
| Size | 33.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ecb17a919c51c24c5a25f2f9627f59bbc2fd657c6b1d5f0234f109537c22f7fe
|
|
BLAKE2b-256 checksum How to use checksums |
3ea19e53dbd4c1a0a5f8d6723fcdfe91b9d0d7a93dadd09923a17b10b0fc67b7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
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 Feb 28, 2026.
Transparency logRelease files / imdbx-1.1.5-py3-none-any.whl
| Download URL | imdbx-1.1.5-py3-none-any.whl |
|---|---|
| Size | 31.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
60f618b753109e8e2773f22648ca497b635b23b90aee1d560d061a05ec8223f0
|
|
BLAKE2b-256 checksum How to use checksums |
e028691554d25cc569f53c82c91ed7a788f1c5e5490ce3d23ed2622fb68f4b74
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
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 Feb 28, 2026.
Transparency logSecurity for IMDBx 1.1.5
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.
Attestation for imdbx-1.1.5.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 Feb 28, 2026.
Transparency logA 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.