Search and download#

Modrinth and CurseForge share one interface, so the code on this page works with either.

Connect to a platform#

Modrinth needs no key, but asks every client to identify itself:

import modsmith as ms

modrinth = ms.platforms.Modrinth("my-tool/1.0")

CurseForge needs an API key from the CurseForge console:

import os

curseforge = ms.platforms.CurseForge(os.environ["CURSEFORGE_API_KEY"])

Warning

Treat the API key as a secret. Read it from the environment rather than writing it in your code.

Both can be used as context managers, which close their connections when you finish.

Look up a project#

get_project accepts an id, a slug or a project URL:

project = modrinth.get_project("sodium", project_type="mod")

Tip

A slug can change. Store project.id if you need to find the project again later.

Choose a release#

iter_releases yields releases newest first, and reads pages only as you need them.

latest = next(modrinth.iter_releases(project))

That makes one request, however many releases the project has. To show a short list, take only what you need:

from itertools import islice

recent = list(islice(modrinth.iter_releases(project), 20))

Filter by what the player is running:

stable = modrinth.iter_releases(
    project, game_version="1.21.1", loader="fabric", release_only=True
)

The newest release is not always for the newest game version, so pass game_version when it matters. next raises StopIteration if nothing matches. Give it a default if that can happen:

release = next(modrinth.iter_releases(project, game_version="1.21.1"), None)

list_releases returns every release at once. It has to read every page, which can take many requests on a large CurseForge project.

Download#

fetch downloads a release’s main file into a folder and returns its path:

if release is not None:
    path = modrinth.fetch(release, "downloads")
    print(path)

Each release can have several files. release.primary_file is the one fetch uses, and release.files lists them all.

modrinth.close()

Respect rate limits#

Reuse one platform object rather than creating a new one for each call, and use iter_releases to avoid reading pages you do not need. Modsmith waits and retries when a platform asks it to slow down.