ModrinthSharp Icon

ModrinthSharp Documentation

A powerful .NET 8 library for seamless integration with the Modrinth API. Search, retrieve, and analyze Modrinth projects, versions, users, and more.

Latest Version: 1.5.0

ModrinthSharp Library Overview

ModrinthSharp is a comprehensive .NET 8 library that provides a simple and powerful interface to the Modrinth API. Whether you're building mod managers, server tools, or analytics platforms, ModrinthSharp gives you full access to Modrinth's extensive ecosystem of Minecraft mods, modpacks, resource packs, and shaders.

Key Features

  • Complete API Coverage: Access all Modrinth API endpoints with type-safe methods
  • Async/Await Support: Built from the ground up with modern async patterns
  • Rich Search Capabilities: Advanced filtering, sorting, and faceted search
  • Rate Limiting: Built-in respect for API rate limits
  • Automatic Retries: Handles transient failures gracefully
  • Strongly Typed: Full IntelliSense support with comprehensive models
  • Caching Support: Optional caching for improved performance

Installation

1Install via NuGet Package Manager

Use the Package Manager Console in Visual Studio:

Install-Package ModrinthSharp

2Install via .NET CLI

Use the command line interface:

dotnet add package ModrinthSharp

3Add PackageReference

Add directly to your .csproj file:

<PackageReference Include="ModrinthSharp" Version="1.5.0" />

Requirements

  • .NET 8.0 or later
  • Active internet connection for API calls
  • Optional: Modrinth API key for authenticated requests

Basic Usage

Creating a Client

Start by creating a ModrinthSharp client instance:

using ModrinthSharp;

// Create a basic client
var modrinth = new ModrinthSharp();

Async Usage

All methods are async and should be used in an async context:

using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        var modrinth = new ModrinthSharp();
        // ... call methods below ...
    }
}

Search for Projects

Search the Modrinth database with simple or advanced queries:

// Basic search
var results = await modrinth.SearchProjectsAsync("sodium");
foreach (var project in results.Hits)
{
    Console.WriteLine($"{project.Title} ({project.Slug})");
}

// Advanced search with filters
var advanced = await modrinth.SearchProjectsAdvancedAsync(
    query: "optimization",
    categories: new[] { "performance" },
    loaders: new[] { "fabric" },
    gameVersions: new[] { "1.20.1" }
);
foreach (var project in advanced.Hits)
{
    Console.WriteLine($"{project.Title} - {project.Downloads} downloads");
}

Get Random Projects

Discover new content with random project methods:

// Get 10 random projects of any type
var randomProjects = await modrinth.GetRandomProjectsAsync(10);

// Get specific types
var randomMods = await modrinth.GetRandomModsAsync(5);
var randomShaders = await modrinth.GetRandomShadersAsync(3);

API Reference

SearchProjectsAsync(string query)

Returns: Task<SearchResult>

Search for projects on Modrinth with a simple query string.

Example Usage

var results = await modrinth.SearchProjectsAsync("sodium");
foreach (var project in results.Hits)
{
    Console.WriteLine($"{project.Title} ({project.Slug})");
}

SearchProjectsAdvancedAsync(string query, ...)

Returns: Task<SearchResult>

Search with advanced filters including categories, loaders, and game versions.

Example Usage

var advanced = await modrinth.SearchProjectsAdvancedAsync(
    query: "optimization",
    categories: new[] { "performance" },
    loaders: new[] { "fabric" },
    gameVersions: new[] { "1.20.1" }
);
foreach (var project in advanced.Hits)
{
    Console.WriteLine($"{project.Title} - {project.Downloads} downloads");
}

GetRandomProjectsAsync(int count, string projectType = null)

Returns: Task<List<ModrinthProject>>

Get a list of random projects from Modrinth, optionally filtered by project type.

Example Usage

// Get 10 random projects of any type
var randomProjects = await modrinth.GetRandomProjectsAsync(10);
foreach (var project in randomProjects) 
{ 
    Console.WriteLine($"{project.Title} ({project.ProjectType}) - {project.Downloads} downloads"); 
}

// Get random projects filtered by type 
var randomMods = await modrinth.GetRandomProjectsAsync(15, "mod"); 
var randomModpacks = await modrinth.GetRandomProjectsAsync(5, "modpack");

// Helper methods for specific project types
var randomMods = await modrinth.GetRandomModsAsync(10); 
var randomShaders = await modrinth.GetRandomShadersAsync(5); 
var randomResourcePacks = await modrinth.GetRandomResourcePacksAsync(8); 
var randomModpacks = await modrinth.GetRandomModpacksAsync(3);

GetProjectAsync(string idOrSlug)

Returns: Task<ModrinthProject>

Get detailed information about a specific project by ID or slug.

Example Usage

var project = await modrinth.GetProjectAsync("sodium");
Console.WriteLine($"{project.Title}: {project.Description}");

GetProjectVersionsAsync(string projectId)

Returns: Task<List<ModrinthVersion>>

Get all versions for a specific project.

Example Usage

var versions = await modrinth.GetProjectVersionsAsync("sodium");
foreach (var version in versions)
{
    Console.WriteLine($"{version.Name} ({version.VersionNumber})");
}

GetVersionAsync(string versionId)

Returns: Task<ModrinthVersion>

Get detailed information about a specific version.

Example Usage

var version = await modrinth.GetVersionAsync(versions[0].Id);
Console.WriteLine($"Version: {version.Name} - {version.Changelog}");

GetVersionFilesAsync(string versionId)

Returns: Task<List<ModrinthFile>>

Get all files for a specific version.

Example Usage

var files = await modrinth.GetVersionFilesAsync(version.Id);
foreach (var file in files)
{
    Console.WriteLine($"File: {file.Filename} ({file.Size} bytes)");
}

DownloadFileAsync(string url, string filePath)

Returns: Task

Download a file from a URL to a local path.

Example Usage

await modrinth.DownloadFileAsync(files[0].Url, @"C:\\Downloads\\" + files[0].Filename);

GetUserAsync(string idOrUsername)

Returns: Task<User>

Get information about a Modrinth user by ID or username.

Example Usage

var user = await modrinth.GetUserAsync("johndoe");
Console.WriteLine($"User: {user.Username} ({user.Id})");

GetTeamAsync(string teamId)

Returns: Task<Team>

Get information about a team by ID.

Example Usage

var team = await modrinth.GetTeamAsync("teamid");
Console.WriteLine($"Team: {team.Name}");

GetProjectDependenciesAsync(string projectId)

Returns: Task<List<Dependency>>

Get all dependencies for a project.

Example Usage

var dependencies = await modrinth.GetProjectDependenciesAsync("sodium");
foreach (var dep in dependencies)
{
    Console.WriteLine($"Depends on: {dep.ProjectId} ({dep.DependencyType})");
}

Helper Methods for Random Projects

Convenience methods for specific project types

Specialized methods for getting random projects of specific types.

Available Methods

  • GetRandomModsAsync(int count) - Get random mods
  • GetRandomShadersAsync(int count) - Get random shaders
  • GetRandomResourcePacksAsync(int count) - Get random resource packs
  • GetRandomModpacksAsync(int count) - Get random modpacks

Example Usage

// Get specific types of random projects
var randomMods = await modrinth.GetRandomModsAsync(10);
var randomShaders = await modrinth.GetRandomShadersAsync(5);
var randomResourcePacks = await modrinth.GetRandomResourcePacksAsync(8);
var randomModpacks = await modrinth.GetRandomModpacksAsync(3);

// Display results
Console.WriteLine("Random Mods:");
foreach (var mod in randomMods)
{
    Console.WriteLine($"  - {mod.Title} ({mod.Downloads:N0} downloads)");
}

Console.WriteLine("\nRandom Shaders:");
foreach (var shader in randomShaders)
{
    Console.WriteLine($"  - {shader.Title} ({shader.Downloads:N0} downloads)");
}

Error Handling

ModrinthApiException handling

All methods throw ModrinthApiException on API errors, which includes the HTTP status and any error message from Modrinth.

Example Usage

try
{
    var project = await modrinth.GetProjectAsync("nonexistent_project");
}
catch (ModrinthApiException ex)
{
    Console.WriteLine($"API Error: {ex.StatusCode} - {ex.ApiError}");
}

Complete Examples

Complete Workflow Example

A typical workflow showing how to search, get project details, download files, and handle errors:

using ModrinthSharp;
using System;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        var modrinth = new ModrinthSharp();
        
        try
        {
            // Search for projects
            var results = await modrinth.SearchProjectsAsync("sodium");
            Console.WriteLine($"Found {results.Hits.Count} results for 'sodium'");
            
            // Get detailed project info
            var project = await modrinth.GetProjectAsync(results.Hits[0].Slug);
            Console.WriteLine($"\nProject: {project.Title}");
            Console.WriteLine($"Description: {project.Description}");
            Console.WriteLine($"Downloads: {project.Downloads:N0}");
            
            // Get project versions
            var versions = await modrinth.GetProjectVersionsAsync(project.Id);
            Console.WriteLine($"\nFound {versions.Count} versions");
            
            // Get latest version details
            var version = await modrinth.GetVersionAsync(versions[0].Id);
            Console.WriteLine($"Latest version: {version.Name} ({version.VersionNumber})");
            
            // Get files for this version
            var files = await modrinth.GetVersionFilesAsync(version.Id);
            Console.WriteLine($"Version has {files.Count} files");
            
            // Download the first file
            if (files.Count > 0)
            {
                var file = files[0];
                var downloadPath = @"C:\\Downloads\\" + file.Filename;
                await modrinth.DownloadFileAsync(file.Url, downloadPath);
                Console.WriteLine($"Downloaded {file.Filename} to {downloadPath}");
            }
        }
        catch (ModrinthApiException ex)
        {
            Console.WriteLine($"API Error: {ex.StatusCode} - {ex.ApiError}");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"General Error: {ex.Message}");
        }
    }
}

Advanced Search Example

Demonstrate advanced search capabilities with filters:

using ModrinthSharp;
using System;
using System.Threading.Tasks;

class ModSearcher
{
    private readonly ModrinthSharp _modrinth;
    
    public ModSearcher()
    {
        _modrinth = new ModrinthSharp();
    }
    
    public async Task FindOptimizationMods()
    {
        // Search for performance/optimization mods for Fabric 1.20.1
        var results = await _modrinth.SearchProjectsAdvancedAsync(
            query: "optimization performance",
            categories: new[] { "optimization", "utility" },
            loaders: new[] { "fabric" },
            gameVersions: new[] { "1.20.1" }
        );
        
        Console.WriteLine($"Found {results.Hits.Count} optimization mods for Fabric 1.20.1:");
        
        foreach (var project in results.Hits.Take(10))
        {
            Console.WriteLine($"\n{project.Title}");
            Console.WriteLine($"  Author: {project.Author}");
            Console.WriteLine($"  Downloads: {project.Downloads:N0}");
            Console.WriteLine($"  Description: {project.Description?.Substring(0, Math.Min(100, project.Description.Length ?? 0))}...");
            Console.WriteLine($"  Categories: {string.Join(", ", project.Categories)}");
        }
    }
    
    public async Task ExploreRandomContent()
    {
        Console.WriteLine("=== Random Modrinth Content ===\n");
        
        // Get random mods
        var randomMods = await _modrinth.GetRandomModsAsync(5);
        Console.WriteLine("Random Mods:");
        foreach (var mod in randomMods)
        {
            Console.WriteLine($"  - {mod.Title} ({mod.Downloads:N0} downloads)");
        }
        
        // Get random shaders
        var randomShaders = await _modrinth.GetRandomShadersAsync(3);
        Console.WriteLine("\nRandom Shaders:");
        foreach (var shader in randomShaders)
        {
            Console.WriteLine($"  - {shader.Title} ({shader.Downloads:N0} downloads)");
        }
        
        // Get random resource packs
        var randomResourcePacks = await _modrinth.GetRandomResourcePacksAsync(3);
        Console.WriteLine("\nRandom Resource Packs:");
        foreach (var pack in randomResourcePacks)
        {
            Console.WriteLine($"  - {pack.Title} ({pack.Downloads:N0} downloads)");
        }
        
        // Get random modpacks
        var randomModpacks = await _modrinth.GetRandomModpacksAsync(2);
        Console.WriteLine("\nRandom Modpacks:");
        foreach (var modpack in randomModpacks)
        {
            Console.WriteLine($"  - {modpack.Title} ({modpack.Downloads:N0} downloads)");
        }
    }
}

// Usage
class Program
{
    static async Task Main()
    {
        var searcher = new ModSearcher();
        
        await searcher.FindOptimizationMods();
        Console.WriteLine("\n" + new string('=', 50) + "\n");
        await searcher.ExploreRandomContent();
    }
}

User and Team Analysis

Example showing how to analyze users, teams, and project relationships:

using ModrinthSharp;
using System;
using System.Threading.Tasks;
using System.Linq;

class UserAnalyzer
{
    private readonly ModrinthSharp _modrinth;
    
    public UserAnalyzer()
    {
        _modrinth = new ModrinthSharp();
    }
    
    public async Task AnalyzeUser(string username)
    {
        try
        {
            // Get user info
            var user = await _modrinth.GetUserAsync(username);
            Console.WriteLine($"=== User Analysis: {user.Username} ===");
            Console.WriteLine($"Display Name: {user.Name ?? "N/A"}");
            Console.WriteLine($"Bio: {user.Bio ?? "No bio"}");
            Console.WriteLine($"Joined: {user.Created:yyyy-MM-dd}");
            Console.WriteLine($"Role: {user.Role}");
            
            // Note: In a real implementation, you'd need additional API calls
            // to get user's projects, as the base API doesn't include this
            Console.WriteLine("\nTo get user's projects, you would need to:");
            Console.WriteLine("1. Use the search API with author filter");
            Console.WriteLine("2. Or use dedicated user projects endpoint if available");
            
        }
        catch (ModrinthApiException ex)
        {
            Console.WriteLine($"Failed to get user info: {ex.StatusCode} - {ex.ApiError}");
        }
    }
    
    public async Task AnalyzeTeam(string teamId)
    {
        try
        {
            var team = await _modrinth.GetTeamAsync(teamId);
            Console.WriteLine($"=== Team Analysis: {team.Name} ===");
            Console.WriteLine($"Team ID: {team.Id}");
            
            // Additional team analysis would require more API endpoints
            Console.WriteLine("\nFor complete team analysis, you would typically:");
            Console.WriteLine("1. Get team members");
            Console.WriteLine("2. Get team's projects");
            Console.WriteLine("3. Analyze team activity and contributions");
            
        }
        catch (ModrinthApiException ex)
        {
            Console.WriteLine($"Failed to get team info: {ex.StatusCode} - {ex.ApiError}");
        }
    }
}

// Usage
class Program
{
    static async Task Main()
    {
        var analyzer = new UserAnalyzer();
        
        // Analyze a specific user
        await analyzer.AnalyzeUser("jellysquid3");
        
        Console.WriteLine("\n" + new string('-', 40) + "\n");
        
        // For team analysis, you'd need a valid team ID
        // await analyzer.AnalyzeTeam("some-team-id");
    }
}

Dependency Analysis Example

Show how to analyze project dependencies and relationships:

using ModrinthSharp;
using System;
using System.Threading.Tasks;
using System.Linq;

class DependencyAnalyzer
{
    private readonly ModrinthSharp _modrinth;
    
    public DependencyAnalyzer()
    {
        _modrinth = new ModrinthSharp();
    }
    
    public async Task AnalyzeProjectDependencies(string projectSlug)
    {
        try
        {
            // Get project info
            var project = await _modrinth.GetProjectAsync(projectSlug);
            Console.WriteLine($"=== Dependency Analysis: {project.Title} ===");
            
            // Get dependencies
            var dependencies = await _modrinth.GetProjectDependenciesAsync(project.Id);
            
            if (dependencies.Count > 0)
            {
                Console.WriteLine($"\nThis project has {dependencies.Count} dependencies:");
                
                var requiredDeps = dependencies.Where(d => d.DependencyType == "required").ToList();
                var optionalDeps = dependencies.Where(d => d.DependencyType == "optional").ToList();
                var incompatibleDeps = dependencies.Where(d => d.DependencyType == "incompatible").ToList();
                
                if (requiredDeps.Count > 0)
                {
                    Console.WriteLine($"\nRequired Dependencies ({requiredDeps.Count}):");
                    foreach (var dep in requiredDeps)
                    {
                        Console.WriteLine($"  - {dep.ProjectId}");
                        
                        // Optionally get details about the dependency
                        try
                        {
                            var depProject = await _modrinth.GetProjectAsync(dep.ProjectId);
                            Console.WriteLine($"    └─ {depProject.Title} ({depProject.Downloads:N0} downloads)");
                        }
                        catch
                        {
                            Console.WriteLine($"    └─ (Could not fetch details)");
                        }
                    }
                }
                
                if (optionalDeps.Count > 0)
                {
                    Console.WriteLine($"\nOptional Dependencies ({optionalDeps.Count}):");
                    foreach (var dep in optionalDeps)
                    {
                        Console.WriteLine($"  - {dep.ProjectId}");
                    }
                }
                
                if (incompatibleDeps.Count > 0)
                {
                    Console.WriteLine($"\nIncompatible With ({incompatibleDeps.Count}):");
                    foreach (var dep in incompatibleDeps)
                    {
                        Console.WriteLine($"  - {dep.ProjectId}");
                    }
                }
            }
            else
            {
                Console.WriteLine("\nThis project has no explicit dependencies.");
            }
            
        }
        catch (ModrinthApiException ex)
        {
            Console.WriteLine($"Error analyzing dependencies: {ex.StatusCode} - {ex.ApiError}");
        }
    }
}

// Usage
class Program
{
    static async Task Main()
    {
        var analyzer = new DependencyAnalyzer();
        
        // Analyze dependencies for popular mods
        string[] projectsToAnalyze = { "sodium", "iris", "lithium", "phosphor" };
        
        foreach (var project in projectsToAnalyze)
        {
            await analyzer.AnalyzeProjectDependencies(project);
            Console.WriteLine("\n" + new string('=', 60) + "\n");
        }
    }
}

License

ModrinthSharp is released under the MIT License. You are free to use, modify, and distribute this software in both commercial and non-commercial projects.

© 2024 MatriX Development. All rights reserved.

Features

  • Search for Modrinth projects with advanced filters
  • Get detailed project info by ID or slug
  • List all versions of a project
  • Get version details and files
  • Download project files
  • Get user and team info
  • Fetch project dependencies
  • Strongly-typed models for all major Modrinth API objects
  • Robust error handling with API error details

Installation

Add the ModrinthSharp project to your solution or reference the DLL. Target .NET 8 or later.

Usage

Creating a Client

using ModrinthSharp;

var modrinth = new ModrinthSharp();

Async Usage

using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        var modrinth = new ModrinthSharp();
        // ... call methods below ...
    }
}

Search for Projects

var results = await modrinth.SearchProjectsAsync("sodium");
foreach (var project in results.Hits)
{
    Console.WriteLine($"{project.Title} ({project.Slug})");
}

Advanced Search

var advanced = await modrinth.SearchProjectsAdvancedAsync(
    query: "optimization",
    categories: new[] { "performance" },
    loaders: new[] { "fabric" },
    gameVersions: new[] { "1.20.1" }
);
foreach (var project in advanced.Hits)
{
    Console.WriteLine($"{project.Title} - {project.Downloads} downloads");
}

Get Project by ID or Slug

var project = await modrinth.GetProjectAsync("sodium");
Console.WriteLine($"{project.Title}: {project.Description}");

List Project Versions

var versions = await modrinth.GetProjectVersionsAsync("sodium");
foreach (var version in versions)
{
    Console.WriteLine($"{version.Name} ({version.VersionNumber})");
}

Get Version Details and Files

var version = await modrinth.GetVersionAsync(versions[0].Id);
var files = await modrinth.GetVersionFilesAsync(version.Id);
foreach (var file in files)
{
    Console.WriteLine($"File: {file.Filename} ({file.Size} bytes)");
}

Download a File

await modrinth.DownloadFileAsync(files[0].Url, @"C:\\Downloads\\" + files[0].Filename);

Get User and Team Info

var user = await modrinth.GetUserAsync("johndoe");
Console.WriteLine($"User: {user.Username} ({user.Id})");

var team = await modrinth.GetTeamAsync("teamid");
Console.WriteLine($"Team: {team.Name}");

Get Project Dependencies

var dependencies = await modrinth.GetProjectDependenciesAsync("sodium");
foreach (var dep in dependencies)
{
    Console.WriteLine($"Depends on: {dep.ProjectId} ({dep.DependencyType})");
}

Error Handling

All methods throw ModrinthApiException on API errors, which includes the HTTP status and any error message from Modrinth.

try
{
    var project = await modrinth.GetProjectAsync("nonexistent_project");
}
catch (ModrinthApiException ex)
{
    Console.WriteLine($"API Error: {ex.StatusCode} - {ex.ApiError}");
}

Complete Example

using ModrinthSharp;
using System;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        var modrinth = new ModrinthSharp();
        var results = await modrinth.SearchProjectsAsync("sodium");
        var project = await modrinth.GetProjectAsync(results.Hits[0].Slug);
        var versions = await modrinth.GetProjectVersionsAsync(project.Id);
        var version = await modrinth.GetVersionAsync(versions[0].Id);
        var files = await modrinth.GetVersionFilesAsync(version.Id);
        await modrinth.DownloadFileAsync(files[0].Url, @"C:\\Downloads\\" + files[0].Filename);
        Console.WriteLine($"Downloaded {files[0].Filename} for {project.Title}");
    }
}

Model Reference

ModrinthSharp uses strongly-typed models for all API responses. Here are the main model types:

ModrinthProject

Contains all project metadata including title, description, downloads, categories, and more.

  • Id - Unique project identifier
  • Title - Display name of the project
  • Description - Short description
  • Downloads - Total download count
  • Categories - Project categories
  • ProjectType - Type (mod, modpack, resourcepack, shader)
  • Slug - URL-friendly identifier

ModrinthVersion

Version information including name, changelog, supported game versions, and loaders.

  • Id - Unique version identifier
  • Name - Version display name
  • VersionNumber - Version number/tag
  • Changelog - Version changelog
  • GameVersions - Supported Minecraft versions
  • Loaders - Supported mod loaders
  • Files - Associated files

ModrinthFile

File information including filename, size, URL, and hashes.

  • Filename - Name of the file
  • Size - File size in bytes
  • Url - Download URL
  • Hashes - File hashes for verification
  • Primary - Whether this is the primary file

User

User account information.

  • Id - Unique user identifier
  • Username - User's username
  • Name - Display name
  • Bio - User biography
  • Created - Account creation date
  • Role - User role/permissions

Team

Team information for collaborative projects.

  • Id - Unique team identifier
  • Name - Team name
  • Members - Team member list

Dependency

Project dependency relationships.

  • ProjectId - ID of the dependency project
  • DependencyType - Type of dependency (required, optional, incompatible)
  • VersionId - Specific version requirement (if any)

SearchResult

Search results container with projects and metadata.

  • Hits - List of matching projects
  • TotalHits - Total number of matching projects
  • Offset - Current result offset
  • Limit - Results per page
MIT License