Import a local mod list (for example exported from Prism Launcher) into a Modrinth collection with one command.
This tool:
- Reads a
modlist.jsoncontaining your mods (names + URLs) - Helps you resolve non-Modrinth entries (CurseForge, missing URLs) interactively
- Fetches your Modrinth collections via the official API
- Lets you pick which collection to update
- Updates that collection using the same API the Modrinth website uses
- Caches your collections locally so you don’t spam the API
If you maintain a client modpack and want a clean, shareable Modrinth collection for it, this is what you want.
- Features
- Project Structure
- Requirements
- Configuration (
config.json) modlist.json(Input Mod List)- Usage
- Files Created
- Notes & Limitations
- Import an entire modpack from a single
modlist.json - Interactive handling of entries that don’t have a Modrinth URL
- Uses the official Modrinth API:
/v3/user/.../collections/v3/collection/.../v2/project/...
- Stores a snapshot of your collections in
modrinth_state.json - Has a dry-run mode (see exactly what would happen without changing anything)
- Secrets are not hard-coded; they live in
config.json(which you should never commit)
A typical repo layout:
your-repo/
├─ main.py # the script
├─ config.json # your Modrinth credentials (never commit this)
├─ modlist.json # exported mod list from Prism Launcher (or similar)
└─ modrinth_state.json # auto-generated snapshot of your collections
If your main script file is not called main.py, just adjust the commands below accordingly.
- Python 3.8+
requestslibrary
Install dependencies:
pip install requestsThe script reads its settings from a config.json file in the same directory as main.py.
Example:
{
"token": "mrp_your_personal_access_token_here",
"user_agent": "your-name/modrinth-collection-importer/0.1",
"user_id": "UWlQXVVZ"
}tokenYour Modrinth Personal Access Token (PAT). It must start withmrp_....user_agentA custom identifier for this script. Modrinth expects non-generic User-Agents for API clients. Example:"your-name/modrinth-collection-importer/0.1 (personal use)"user_idYour Modrinth user ID (short ID, e.g."UWlQXVVZ").
Do not leak your token. At minimum, add these to .gitignore:
config.json
modrinth_state.jsonNever commit real tokens or config.json to GitHub.
-
Log in to Modrinth in your browser.
-
Go to your Account / Settings page.
-
Find Personal Access Tokens.
-
Create a new token:
- Give it a sensible name, e.g.
Modpack Collection Importer. - Give it scopes that allow reading and modifying collections for your user.
- Give it a sensible name, e.g.
-
Copy the generated token (it should look like
mrp_XXXXXXXXXXXXXXXX). -
Put it into
config.jsonas the value of"token".
Do not use the
authorizationvalue you see in your browser’s DevTools (thosemra_...tokens). Those are session tokens and will break or get you 401s. Use a PAT (mrp_...) only.
You only need to find this once.
If you’re comfortable with curl:
curl -H "Authorization: mrp_XXXXXXXXXXXXXXXX" \
-H "User-Agent: your-name/modrinth-collection-importer/0.1" \
https://api.modrinth.com/v3/userIn the JSON response, look for the "id" field.
That value is your user_id.
If you’ve seen a request like this in the Network tab:
GET https://api.modrinth.com/v3/user/UWlQXVVZ/collectionsThen UWlQXVVZ is your user_id. Put that in config.json.
By default, the script expects a file named modlist.json in the same directory as main.py.
Format (simplified):
[
{
"name": "3d-Skin-Layers",
"url": "https://modrinth.com/mod/zV5r3pPn"
},
{
"name": "Architectury",
"url": "https://www.curseforge.com/projects/419699"
},
{
"name": "No Mining Cooldown"
}
]-
name– purely for display/debug. The script doesn’t depend on it. -
url– optional:- If it’s a Modrinth mod URL (e.g.
https://modrinth.com/mod/P7dR8mSH), the script can resolve the project automatically. - If it is missing or points somewhere else (CurseForge, random link, etc.), the script will interactively ask what to do for that entry.
- If it’s a Modrinth mod URL (e.g.
Prism Launcher can export your instance’s mod list.
Rough idea (exact labels depend on your version/theme):
- Open Prism Launcher.
- Right-click your modded instance → Edit.
- Go to the Mods tab.
- Look for something like “Export mod list”.
- If it can export to JSON, use that and adapt the structure to match the example above if needed.
Save the final list as modlist.json next to main.py.
If you use another name or location, you can point the script to it with --modlist.
All commands below assume the script file is called main.py.
python main.pyWhat happens:
-
The script reads
config.json. -
It fetches your collections from Modrinth and writes a snapshot to
modrinth_state.json. -
It shows your collections and asks which one to use, for example:
Your collections: [1] Armi's Modrinth Collection (id=tIDygMuC) A collection of mods curated by Armi for Minecraft. Select collection by number (or paste collection ID, or 'q' to quit) > -
It loads
modlist.jsonand walks through each entry:-
If
urlis a Modrinth URL → resolves it automatically. -
If
urlis missing or non-Modrinth → you see a prompt like:Entry needs attention: Architectury Current URL: https://www.curseforge.com/projects/419699 [u] enter Modrinth URL | [s] skip this mod | [q] abort >
-
-
After processing the list, it prints a summary, for example:
[summary] To add: 81 new project(s). Skipped: 0. Final collection size will be 83. Proceed with updating the collection? [y/N] > -
If you confirm with
y, it sends a singlePATCHrequest like:PATCH /v3/collection/tIDygMuC Body: {"new_projects": ["P7dR8mSH","AANobbMI", ...]}
and updates the collection on Modrinth.
To see what would happen without actually patching the collection:
python main.py --dry-run- The script still reads the config and modlist.
- It still resolves project IDs and prints a summary.
- It does not send the final
PATCHrequest.
Useful if you don’t trust your modlist.json yet.
Use a different config file:
python main.py --config my_config.jsonUse a different modlist file:
python main.py --modlist my_modlist.jsonCombine them:
python main.py --config my_config.json --modlist instances/fabric-pack/modlist.jsonIf you already know the collection ID (for example tIDygMuC):
python main.py --collection-id tIDygMuCThe script will:
- Sync collections and update
modrinth_state.json - Validate that
tIDygMuCbelongs to your user - Use it directly without the interactive selection
You can combine this with all other flags (--dry-run, --config, --modlist).
-
modrinth_state.jsonLocal snapshot of your collections (user_id, collection list, and a timestamp). You can delete it any time; the script will just recreate it. -
Your own
config.jsonContains your token anduser_id. Do not commit this.
-
Only mods that exist on Modrinth can be added. If some mods are CurseForge-only or custom, you will have to:
- Find a Modrinth equivalent, or
- Skip them when prompted.
-
The script uses the public Modrinth API and is subject to normal rate limits. For a typical modpack (tens of mods), this is not a problem.
-
If Modrinth changes their API for collections in the future, this script may need updates.
If you extend it (non-interactive modes, auto-creating collections, other launcher formats), keep your tokens out of version control and don’t push anything that contains real secrets.