Modgrade API
Two free JSON addresses: the grade and security result of the projects you ask for, and the list of the projects where we found malware. No key is needed. Any website can read them from the browser.
1. Project lookup
The grade and the security result of up to 100 projects per request, by Modrinth project id, CurseForge project id or file SHA-1. Separate several values with commas. You can mix the three. Use the Modrinth id (AANobbMI), not the slug (sodium): a slug is not found.
curl "https://modgrade.com/api/v1/projects?modrinth=AANobbMI,P7dR8mSH"
curl "https://modgrade.com/api/v1/projects?curseforge=394468"
curl "https://modgrade.com/api/v1/projects?sha1=<40 hex characters>"An answer, shortened:
{
"version": 1,
"generated_at": "2026-10-24T20:00:00Z",
"data_updated_at": "2026-10-24T18:59:17Z",
"results": [
{
"query": "modrinth:AANobbMI",
"found": true,
"project": {
"id": "mg_01m232r6303kss5prbhgy22dy4",
"slug": "sodium",
"type": "mod",
"title": "Sodium",
"url": "https://modgrade.com/mod/sodium",
"grade": "A",
"grade_note": null,
"security": "passed",
"malware_platforms": null,
"malware_confirmed": null,
"coverage": {
"latest_files": 7,
"checked": 7,
"code_read": 7,
"read_in_part": 0,
"cannot_check": 0,
"recent_versions_only": true
},
"modrinth_id": "AANobbMI",
"curseforge_id": 394468
},
"malware_on_this_platform": false,
"file": null
},
{
"query": "curseforge:1",
"found": false,
"project": null,
"malware_on_this_platform": null,
"file": null
}
],
"terms": "Free to use. Credit \"Data: Modgrade\" with a link to the project's Modgrade page. No guarantee: ...",
"docs": "https://modgrade.com/api"
}generated_at: When this answer was made.data_updated_at: When our data was last updated. It is updated every 2 hours.results: One result per value asked for, in the order of the request.query: The value you asked for: modrinth:<id>, curseforge:<id> or sha1:<hash>.found: false when we do not know this project or file.project.id, slug, type, title, url: As in the malware feed. url is the project page on Modgrade.project.grade: A to F, as on Modgrade. null when the project has no grade: grade_note says why.project.grade_note: What limits or replaces the grade, as on the project page, for example "Limited history", "Abandoned" or "Malware found". null when nothing.project.security: The result of our checks of its latest files: passed, partly_checked, warning, malware or not_checked.project.malware_platforms: With malware only: the platforms where it was published, as in the malware feed. null otherwise.project.malware_confirmed: With malware only: confirmed of the malware feed. false for a modpack whose installed file is not checked yet. null otherwise.project.coverage: The latest files the result is about: latest_files, checked, code_read (their code was read), read_in_part (some packed files could not be read), cannot_check (CurseForge does not let other sites download them) and recent_versions_only (true: only the files for recent Minecraft versions count, as on the project page). null for a modpack.project.modrinth_id, project.curseforge_id: The project on each platform. null when it is not there.malware_on_this_platform: For a Modrinth or CurseForge id: true when the malware of the project was published on that platform. A project on both platforms can have malware on one only. false without malware, null for a SHA-1 or a project not found.file: For a SHA-1 only: sha1 and result, the result of that very file (the same words as security). A file of a project with malware can pass on its own: look at project.security too.
In JavaScript:
const res = await fetch("https://modgrade.com/api/v1/projects?modrinth=AANobbMI,P7dR8mSH");
if (!res.ok) throw new Error((await res.json()).error);
const { results } = await res.json();
for (const r of results) {
if (!r.found) continue;
const p = r.project;
// the grade, or why there is none, with a link to the page
const label = p.grade ?? p.grade_note ?? "No grade";
// block only malware confirmed on the platform the file comes from
const block = r.malware_on_this_platform === true && p.malware_confirmed === true;
const warn = p.security === "malware";
console.log(p.title, label, p.url, block ? "block" : warn ? "warn" : "");
}2. The malware feed
The feed lists the Minecraft projects where our checks found malware: the projects that Modgrade shows as Malware. Launchers, modpack indexes and other tools can use it to warn players or to hide these projects.
It lists nothing else: no grades, no warnings, no projects without malware.
curl "https://modgrade.com/api/v1/malware.json"An answer with two projects, shortened. The names are made up.
{
"version": 1,
"generated_at": "2026-10-24T08:00:00Z",
"count": 2,
"projects": [
{
"id": "mg_0123abcd",
"slug": "example-mod",
"type": "mod",
"title": "Example Mod",
"url": "https://modgrade.com/mod/example-mod",
"platforms": {
"modrinth": { "id": "AbCd1234", "slug": "example-mod", "url": "https://modrinth.com/mod/example-mod", "removed": false, "has_malware": true },
"curseforge": { "id": 123456, "slug": "example-mod", "url": "https://www.curseforge.com/minecraft/mc-mods/example-mod", "removed": false, "has_malware": false }
},
"malware_platforms": ["modrinth"],
"confirmed": true,
"does": "steals your Minecraft session and sends it to a web address",
"affected_files": [
{
"sha1": "0a1b2c3d4e5f60718293a4b5c6d7e8f901234567",
"file_name": "example-mod-1.2.0.jar",
"version_name": "1.2.0",
"published_at": "2026-10-12T09:30:00Z",
"latest": true,
"platforms": [{ "platform": "modrinth", "version_id": "XyZ98765" }]
}
],
"file_counts": { "with_malware": 1, "checked_without_malware": 4, "not_checked": 0 },
"through_contained": false,
"contained": [],
"pack_own_files": [],
"reports": [{ "platform": "modrinth", "date": "2026-10-13" }]
},
{
"id": "mg_4567efgh",
"slug": "example-pack",
"type": "modpack",
"title": "Example Pack",
"url": "https://modgrade.com/modpack/example-pack",
"platforms": {
"modrinth": null,
"curseforge": { "id": 654321, "slug": "example-pack", "url": "https://www.curseforge.com/minecraft/modpacks/example-pack", "removed": false, "has_malware": true }
},
"malware_platforms": ["curseforge"],
"confirmed": true,
"does": null,
"affected_files": [],
"file_counts": null,
"through_contained": true,
"contained": [
{
"id": "mg_0123abcd",
"slug": "example-mod",
"type": "mod",
"title": "Example Mod",
"url": "https://modgrade.com/mod/example-mod",
"does": "steals your Minecraft session and sends it to a web address",
"file_checked": true,
"pack_file_names": []
}
],
"pack_own_files": [],
"reports": []
}
],
"terms": "Free to use. Credit \"Data: Modgrade\" with a link to the project's Modgrade page. No guarantee: ...",
"docs": "https://modgrade.com/api"
}version: 1. It changes only if a field is renamed or removed.generated_at: When this content was built (UTC, ISO 8601).count: The number of projects.projects: The projects, most downloaded first.terms: The terms below, in short.docs: The address of this page.
Each project:
id: The Modgrade id of the project.slug, type, title: As on Modgrade. type is mod, modpack, resourcepack, datapack, shader or plugin.url: The project page on Modgrade.platforms.modrinth, platforms.curseforge: The project on each platform: id, slug, url, removed (true when the platform removed it) and has_malware (true when a file with malware was published there). null when it is not on that platform. The Modrinth id is text, the CurseForge id is a number.malware_platforms: The platforms where the malware was published. A project on both platforms can have malware on one only: the page on the other platform is then not concerned. For a modpack, the platform of the release we checked. Every platform of the project when we do not know.confirmed: true when a file of the project itself has malware, or the very file a modpack installs or carries. false for a modpack listed only because other files of a mod it contains have malware, while the file it installs is not checked yet: warn, do not block.does: What the malware does, in the words of the project page. null when it is not known, and for a modpack (see contained).affected_files: The files with malware, newest first: sha1, file_name, version_name, published_at, latest (one of the latest files of the project) and platforms (each platform with version_id: the Modrinth version id or the CurseForge file id; on CurseForge also file_id, the same id as a number; removed: true when the platform no longer lists that file).file_counts: The published files of the project: with_malware, checked_without_malware and not_checked. null for a modpack.through_contained: true for a modpack listed because of a project it contains.contained: For a modpack: the projects it contains that have malware, with id, slug, type, title, url and does. file_checked is true when the file the pack installs has malware, false when that file is not checked yet and other files of the project have malware. pack_file_names then names the files the pack installs.pack_own_files: For a modpack: the paths of files with malware that the pack itself carries.reports: The reports we sent to the platforms: platform and date (YYYY-MM-DD).
- The feed changes when our checks confirm malware in a project, and when we send a report.
- Ask for it at most every few minutes. Each answer has an ETag: send it back in
If-None-Matchand you get a 304 when nothing changed. - To check a file, compare its SHA-1 with
affected_files. A file of a listed project that is not in that list is not proven harmless.
3. Warn or block
- Show the grade with a link to the project page (
url), where players can see why it has this grade. - A project with
securitymalware: show a warning and link to its page. - Block a download only when the malware is confirmed where the file comes from:
file.resultis malware for that SHA-1, ormalware_on_this_platformandmalware_confirmedare both true. In the feed:confirmedis true andhas_malwareis true for that platform. - A project on Modrinth and CurseForge is one entry when both pages have the same author name, slug and title. The malware can be on one platform only: do not warn about the page on the other platform.
- Passed means our checks found nothing in the files listed in
coverage, not that the project is harmless.
4. Errors and limits
- Each error is JSON with an
errormessage: 400 for a bad value, 429 for too many requests, 503 when our data is not available for a moment. - At most 60 lookup requests per minute from one address, and 100 values per request. Ask for many projects in one request rather than one by one. After a 429 or a 503, wait for the seconds given in
Retry-After. - Lookup answers are kept 5 minutes in browsers and have no ETag. The malware feed has an ETag and no request limit. Our data is updated every 2 hours.
- A value that is not known is null or an empty list. We may add fields. We will not rename or remove fields in version 1.
5. Terms
- Free to use.
- Credit "Data: Modgrade" with a link to the project page on Modgrade (the
urlfield). - No guarantee. The feed lists what our checks found. A project that is not listed is not proven harmless, and our checks can be wrong.
6. Contact
For a question, or a project you think is listed by mistake, contact us.