Skip to main content

mtgwiki

PyPI version Python versions License: MIT Publish to PyPI

mtgwiki is a lightweight Python package for getting useful, reusable data out of MediaWiki Action API sites without teaching the package what the wiki's subject matter means.

MTG Wiki is the default endpoint and the original use case, but the transport, traversal, parsing and snapshot layers are domain-neutral.

The package does not contain functions such as get_plane(), get_character(), flora() or depicted_cards(). Instead it exposes generic MediaWiki building blocks and a generic snapshot/structure layer that downstream projects can interpret however they want.

Installation

python -m pip install mtgwiki

Requires Python 3.10 or newer.

Quick start

from mtgwiki import Wiki

wiki = Wiki()

page = wiki.get("Skyship Weatherlight")
print(page["title"])

hits = wiki.search("Bloomburrow", limit=20)
for hit in hits:
    print(hit["title"])

Search results are ranked search results. search() does not pretend the first result is the entity you meant.

For category-based research, recursive traversal is built in:

pages = wiki.members(
    "Planeswalker characters",
    recurse=True,
    namespace=0,
    cmtype="page",
)

for page in pages:
    print(page["title"])

Design rule

If a feature needs to know Magic semantics, it does not belong in mtgwiki.

The package has three jobs:

  1. Acquire data politely and efficiently from MediaWiki.
  2. Structure generic wiki syntax such as templates, parameters, sections, lists, tables and links.
  3. Export JSON-friendly snapshots that preserve source/provenance and raw data.

User-Agent and other MediaWiki sites

For sustained API use, identify your own project in the User-Agent:

from mtgwiki import Wiki

wiki = Wiki(
    user_agent="my-project/0.1 (https://example.com/contact)"
)

Point the same client at another MediaWiki installation by supplying its Action API endpoint:

wiki = Wiki(
    api_url="https://www.mediawiki.org/w/api.php",
    user_agent="my-project/0.1 (https://example.com/contact)",
)

The package name and default URL are conveniences; the public data model contains no Magic-specific entity types.

Compatibility

The client targets modern MediaWiki Action API installations and always requests JSON with formatversion=2. Revision-content handling supports main-slot responses and includes fallbacks for older response shapes. Rendered section discovery prefers tocdata and falls back to the older sections output. Use siteinfo() and paraminfo() when a consuming project needs to discover site-specific capabilities rather than assume them.

Generic structure discovery

Ask the package what syntax exists instead of hard-coding what you expect:

structure = wiki.structure(
    "Skyship Weatherlight",
    section="In-game references",
)

for template in structure["templates"]:
    print(template["name"])
    print(template["params"].keys())

A template call is returned generically, for example:

{
    "name": "Some template",
    "depth": 1,
    "raw": "{{Some template|x=1|data=...}}",
    "params": {
        "x": "1",
        "data": "...",
    },
    "params_clean": {
        "x": "1",
        "data": "...",
    },
    "parameters": [...],
}

The package does not assign meaning to x, data, art, species, job1 or any other parameter name.

Snapshots: easiest way to build reusable datasets

snapshot = wiki.extract("Dack Fayden")

print(snapshot.keys())
print(snapshot["source"])
print(snapshot["data"])
print(snapshot["structure"].keys())

A snapshot contains:

schema_version
exists
source
  api_url
  requested_title
  resolved_title
  pageid
  revision_id
  revision_timestamp
  retrieved_at
  redirects
page
revision
data
  categories
  links
  templates
  images
  external_links
  pageprops
content
  raw
  text
structure
  sections
  templates
  wikilinks
  external_links
  lists
  tables
raw
  page
  normalized
  redirects
  converted

Raw source is deliberately retained. Cleaned/normalized values are conveniences, not replacements for the source.

Batch extraction

MediaWiki accepts multiple titles in one query. extract_many() batches up to 50 titles per request group instead of making one independent request per title.

pages = wiki.extract_many(
    [
        "Urza",
        "Dack Fayden",
        "Skyship Weatherlight",
        "Bloomburrow (plane)",
    ]
)

You can request a smaller snapshot when you do not need everything:

pages = wiki.extract_many(
    ["Urza", "Dack Fayden"],
    include=("revision", "categories", "wikitext", "structure"),
)

Supported include values:

revision
categories
links
templates
images
external_links
pageprops
wikitext
structure

JSON / JSONL

from mtgwiki import write_json, write_jsonl

write_json("one-page.json", wiki.extract("Urza"))
write_jsonl("dataset.jsonl", wiki.extract_many(["Urza", "Karn", "Squee"]))

JSONL is convenient for larger datasets because every page is one independent line.

Raw API is always available

The high-level helpers never lock you out of MediaWiki itself:

data = wiki.api(
    action="query",
    meta="siteinfo",
    siprop="general|namespaces",
)

Continuation:

for response in wiki.iter_api(
    action="query",
    list="categorymembers",
    cmtitle="Category:Example",
    cmlimit="max",
):
    print(response)

Or collect common list modules directly:

members = wiki.members("Example category")
backlinks = wiki.backlinks("Example page")
embeds = wiki.embedded_in("Template:Example")

These are MediaWiki concepts, not domain semantics.

Lazy list iteration

For large list modules you can stream items instead of building one large list in memory:

for item in wiki.iter_list(
    "allpages",
    aplimit="max",
    apnamespace=0,
):
    print(item["title"])

list() remains available when collecting everything is more convenient.

Recursive categories

Category trees are a generic MediaWiki structure. members() can now traverse them without every research script reimplementing a queue and cycle guard:

pages = wiki.members(
    "Example root category",
    recurse=True,
    namespace=0,
    cmtype="page",
)

for page in pages:
    print(page["title"])

Use an integer to limit depth. recurse=1 includes members of immediate subcategories but does not descend further:

pages = wiki.members(
    "Example root category",
    recurse=1,
    namespace=0,
    cmtype="page",
)

For very large category trees, use iter_members() to stream the same traversal lazily. Recursive traversal is cycle-safe and de-duplicates members that appear through multiple category paths.

Sections

For rendered section discovery the package asks MediaWiki for tocdata and falls back to the older sections response when necessary:

for section in wiki.sections("Bloomburrow (plane)"):
    print(section["line"])

Fetch only one named section:

text = wiki.section("Bloomburrow (plane)", "Flora")

Extract generic list items without losing the original markup:

items = wiki.section_items(
    "Bloomburrow (plane)",
    "Flora",
    clean=True,
)

for item in items:
    print(item["raw_text"])
    print(item["text"])

The method knows only that it is reading a list in a section. It does not know what "Flora" means.

Wikitext structure parser

The built-in parser is deliberately conservative and dependency-free. It discovers:

  • section headings
  • nested template calls and arbitrary parameters
  • wikilinks
  • external links
  • list items and nesting depth
  • MediaWiki tables

Use it on any string:

from mtgwiki import parse_wikitext

structure = parse_wikitext("{{Thing|a=1}}\n* [[Target|Label]]")

It is not intended to reproduce MediaWiki's renderer. When exact rendered output matters, use wiki.parse() / wiki.section() and let the server parse the page. Raw source and spans are kept so a later project can always fall back to the original material.

Revisions and provenance

extract() records the revision ID, timestamp and SHA-1 where available. This makes exported data traceable to the wiki revision it came from.

snapshot = wiki.extract("Urza", include=("revision", "wikitext"))
print(snapshot["source"]["revision_id"])
print(snapshot["revision"]["sha1"])

API capability discovery

Do not assume every MediaWiki installation exposes exactly the same features:

info = wiki.siteinfo()
params = wiki.paraminfo(["query", "parse"])

Polite API behavior

The client defaults to:

serial requests only
min_interval = 0.5 seconds
maxlag = 5
Retry-After support
exponential retry/backoff
memory cache

Statistics:

print(wiki.client.stats())

Optional persistent cache:

wiki = Wiki(
    cache_path=".mtgwiki-cache.sqlite",
    cache_ttl=24 * 60 * 60,
)

The SQLite cache is optional and uses only Python's standard library.

Compatibility helpers

The 1.0 helpers infobox(), infobox_fields(), templates_with_params() and template_params() remain available so existing experiments keep working. New code should generally prefer template_calls() or structure() because those do not assume a particular template convention.

Development

Clone the repository and install it in editable mode:

git clone https://github.com/m0n0deaf/mtgwiki.git
cd mtgwiki

py -m venv .venv
.\.venv\Scripts\Activate.ps1

python -m pip install -e .

Run the offline test suite:

python -m unittest discover -s tests -v

Then run the optional live verifier against the configured MediaWiki endpoint:

python verify_live.py

It creates:

mtgwiki_verify_report.json
verify_output/pages.jsonl

The report can be attached to bug reports or used when troubleshooting live-site compatibility.

Metadata

Release files for mtgwiki 1.2.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 mtgwiki 1.2.1
File Size Uploaded
mtgwiki-1.2.1.tar.gz 32.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for mtgwiki 1.2.1
File Interpreter ABI Platform
mtgwiki-1.2.1-py3-none-any.whl Python 3 none any Details

Total release size: 57.0 kB

Release files / mtgwiki-1.2.1.tar.gz

Download URL mtgwiki-1.2.1.tar.gz
Size 32.6 kB
Tags Source
SHA-256 checksum
How to use checksums
fc26e56faa20c3085f76aa4a48ba1f24226f8d918946b91a5ab57eaedccb4207
BLAKE2b-256 checksum
How to use checksums
75d3f1c7d1ac32b999100c95a79c2df5d4b57b241003151bb75e4eae03de6041
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 18, 2026.

Transparency log

Release files / mtgwiki-1.2.1-py3-none-any.whl

Download URL mtgwiki-1.2.1-py3-none-any.whl
Size 24.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5502866a724bd9c6fd704123c4d148b6dbbcaeabc134bb200d81351fc4011cca
BLAKE2b-256 checksum
How to use checksums
395f7b3f92d75aa9e034c2648a1b4ebfce3320f5e4bd7bb80f48aafad0e4b08f
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 18, 2026.

Transparency log

Release history Release notifications | RSS feed

1.2.2

2 release files

This release

1.2.1 This release

2 release files

1.2.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