Single interface for several game mod portals
Project description
ModMux
Unified async client for multiple game mod platforms. ModMux normalises provider responses into shared Pydantic models and ships a small CLI for quick lookups.
Features
- Async HTTP client with rate limiting and retry handling
- Normalised
Modmetadata model across providers - Bulk
get_mods(...)support with native batching where available - Pluggable provider registry
- URL parsing helpers for provider links
- CLI for fetching one or more mods and printing JSON
Supported providers
- Modrinth
- CurseForge
- Nexus Mods
- Mod.io
- Steam Workshop
- Factorio Mod Portal (Wube)
- transportfever.net
Requirements
- Python 3.13+
- Dependencies:
pydantic,httpx,aiolimiter
Install
python -m pip install modmux
Credentials and environment variables
--tokenaccepts API tokens/keys.--usersupplies a user id for providers that need user-scoped base URLs (mod.io).- Environment variables:
MODMUX_TOKEN(fallback for all providers)MODMUX_<PROVIDER>_TOKEN(provider-specific, e.g.MODMUX_MODRINTH_TOKEN)MODMUX_<PROVIDER>_USER(provider-specific user id, e.g.MODMUX_MODIO_USER)
Library usage
Two supported patterns are available: an async context manager or a manually closed client.
import asyncio
from modmux import ModID, ModrinthCreds, Muxer, Provider
mod_id = ModID(provider=Provider.MODRINTH, id="fabric-api")
async def run() -> None:
async with Muxer(creds=[ModrinthCreds(api_key="api-key")]) as mux:
mod = await mux.get_mod(Provider.MODRINTH, mod_id)
print(mod.name)
asyncio.run(run())
Use the same context manager pattern as above; you can supply multiple provider credentials in one go:
from modmux import ModioCreds, Muxer, NexusCreds, SteamCreds
mux = Muxer(
creds=[
ModioCreds(api_key="api-key", user_id="user-id"),
NexusCreds(token="nexus-token"),
SteamCreds(api_key="steam-key"),
]
)
import asyncio
from modmux import ModID, Muxer, Provider
mod_id = ModID(provider=Provider.MODRINTH, id="fabric-api")
async def run() -> None:
mux = Muxer()
try:
mod = await mux.get_mod(Provider.MODRINTH, mod_id)
finally:
await mux.aclose()
print(mod.name)
asyncio.run(run())
The modmux_client(...) helper remains available as a convenience wrapper
around Muxer for existing code.
You can also pass raw credential dicts when you do not want to import the credential models directly:
from modmux import ModID, Muxer, Provider
mod_id = ModID(provider=Provider.MODRINTH, id="fabric-api")
async with Muxer(creds={Provider.MODRINTH: {"token": "token"}}) as mux:
mod = await mux.get_mod(Provider.MODRINTH, mod_id)
You can also fetch multiple mods in one call:
from modmux import ModID, Muxer, Provider
mod_ids = [
ModID(provider=Provider.STEAM, id="123"),
ModID(provider=Provider.STEAM, id="456"),
]
async with Muxer() as mux:
mods = await mux.get_mods(Provider.STEAM, mod_ids)
URL parsing
Parse provider URLs into ModID instances, or fetch directly from a URL.
import asyncio
from modmux import Muxer, parse_url
async def run_mod_id() -> None:
async with Muxer() as mux:
mod = await mux.get_mod_from_url("https://modrinth.com/mod/fabric-api")
print(mod.name)
async def run_from_url() -> None:
mod_id = parse_url("https://modrinth.com/mod/fabric-api")
if mod_id:
async with Muxer() as mux:
mod = await mux.get_mod(mod_id.provider, mod_id)
print(mod.name)
asyncio.run(run())
Some providers require extra context (game ids or credentials); use
get_mod_from_url(..., game="...") when the URL cannot supply it.
CLI usage
The CLI expects a provider name and one or more provider-specific mod ids. Provider names are case-insensitive.
modmux MODRINTH fabric-api --pretty
modmux CURSEFORGE 238222 --pretty
modmux STEAM 123 456 --pretty
modmux NEXUSMODS 12345 --game transportfever2
modmux MODIO some-mod --game 4321 --user 12345 --token <api-key>
modmux TRANSPORTFEVERNET 7867 --pretty
modmux TRANSPORTFEVERNET urbanist_classic_station_1 --game tpf1 --pretty
modmux --from-urls urls.txt --pretty
Or without installing a script:
python -m modmux MODRINTH fabric-api --pretty
Output is a JSON serialisation of a single Mod when one id is provided, or a JSON array of Mod objects when multiple ids are provided.
When using --from-urls, provide one mod URL per line. Blank lines and lines starting with # are ignored. URLs are grouped by provider internally so the CLI can reuse native bulk lookups where available.
Provider notes
- CurseForge: slug lookups require
ModID.game(numeric game id or game slug from a CurseForge URL). - Nexus Mods: requires
ModID.game(game domain, e.g.skyrim). - mod.io: requires
ModID.gameplus a user id (use--userorMODMUX_MODIO_USER). - Steam: uses a Workshop published file id;
ModID.gameis optional. - transportfever.net: uses the TPF2 repository by default; set
ModID.gametotpf1,tf1, ortransportfever1for the TPF1 repository. - Wube: uses the Factorio mod name slug.
- Native bulk lookup is currently implemented for Modrinth, CurseForge, Steam Workshop, mod.io, and transportfever.net.
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 modmux-0.6.1.tar.gz.
File metadata
- Download URL: modmux-0.6.1.tar.gz
- Upload date:
- Size: 36.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b1061d59e76905d5da89385c7949e9d2c6c0202f52b3937edd3f93a3aea6d9b0
|
|
| MD5 |
f2f813d9f6d5d1cbc626b8ae00c91074
|
|
| BLAKE2b-256 |
1d941f08d3a380573e34c00a72f1f0656d16f57e3dae09d01c8388d171a866c5
|
File details
Details for the file modmux-0.6.1-py3-none-any.whl.
File metadata
- Download URL: modmux-0.6.1-py3-none-any.whl
- Upload date:
- Size: 52.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
acbcefcad079085126ef740a873dd6ff2c2273c4dbeaa63869d4e468c8d97944
|
|
| MD5 |
f25fe55d358fc526baf4a0f001e0e952
|
|
| BLAKE2b-256 |
258809ceb63da9f966315517aeda17b23d6694743b938e99681bccaf608785ef
|