mihomo wraps Honkai: Star Rail parsed data in pydantic 1.x models
A simple Python Pydantic model for Honkai: Star Rail parsed data from the Mihomo API.
At a glance
- What is it?
- mihomo is a small Python package that fetches Honkai: Star Rail user data from the Mihomo API and hands back pydantic models, in two shapes, v1 and v2. The dependency pins are the part to read before anything else: pydantic==1.*, aiohttp==3.* and a Python 3.10 floor.
- Who is it for?
- Use mihomo if your Python program needs typed Honkai: Star Rail user data and you are on pydantic 1.x with aiohttp 3, and if you can live with a client that speaks only the two parsed formats the API serves. Leave it alone if your environment is already on pydantic 2, since the dependency pin is pydantic==1.* and the README documents no v2 path, and do not assume the merge helpers are safe defaults, since the README does not state which side wins on a conflict.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 6 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 26, 2026, and from our analysis. They are not legal advice.
Editorial analysis
pip installs from KT-Yeh/mihomo, not from this repository
The install line in the README points somewhere other than the repository hosting it.
pip install -U git+https://github.com/KT-Yeh/mihomo.gitThe author recorded in pyproject.toml is KT with the email [email protected], and the package name is mihomo at version 1.1.7. So the command installs a branch tip from a different GitHub account, and no release on a package index is named anywhere in the documentation. Anyone who wants the tree that ships the examples and the README should clone the repository under review instead of trusting the URL above to match it. Two further gaps sit in the same file. The project declares https://wiki.metacubex.one as its homepage, and nothing in the README points at that wiki, so a reader cannot tell from the repository whether the wiki documents this library at all. And the release list shows v1.19.31 from 2026-09-14 and v1.19.30 from 2026-08-16 alongside a Prerelease-Alpha tag from 2024-08-12, numbers that have nothing to do with 1.1.7. Treat release tags as unusable version numbers for this package.
fetch_user and fetch_user_v1 return two unrelated model classes
The API serves two parsed formats and the client keeps them apart. V1 is requested by adding version=v1 to the request, read through client.fetch_user(800333171), and typed as mihomo.models.v1.StarrailInfoParsedV1, with every model defined under the mihomo/models/v1 directory. V2 drops the version parameter, is read through client.fetch_user(800333171), and typed as mihomo.models.StarrailInfoParsed from the mihomo/models directory. The imports alone tell you which one you are holding.
from mihomo import Language, MihomoAPI
from mihomo.models import StarrailInfoParsed
from mihomo.models.v1 import StarrailInfoParsedV1
client = MihomoAPI(language=Language.EN)Language is fixed when the client is built, not per call, because the value becomes the lang parameter of the request URL. A program that needs English and Japanese output keeps two clients, each with its own models in memory. Mixing the two formats in one codebase also means two import paths and two serialization shapes to keep apart, and the README does not say whether one format is being retired or which one a new integration should start on.
replace_icon_name_with_url trades a lazy lookup for eager asset urls
Character images arrive as icon names in the parsed payload, and there are two ways to get a URL. The default is to ask for each one, through client.get_icon_url, at the point where you need it. The alternative is a flag on the fetch call.
data = await client.fetch_user(800333171, replace_icon_name_with_url=True)With that flag the returned data already carries asset urls. The choice is about when the work happens: per asset, on demand, or once for the whole payload before you touch it. If you are rendering a roster, the eager form saves a call per character. If you are reading one field out of a payload and will never touch the art, the eager form has done work you did not ask for. What the README does not say is whether the urls are cached between calls, whether repeated fetches of the same user re-resolve assets, or whether a missing asset raises or yields an empty string, so a caller building a cache on top of this has no documented contract to lean on.
pydantic==1.* is pinned, and the persistence example says why
Two dependencies are pinned exactly, and the pins are the real constraint of this package: aiohttp==3.* and pydantic==1.*. The Python floor is requires-python >= 3.10, and the project is classified as OS Independent.
The reason the pydantic pin matters shows up in the load path of the persistence example, which reads a saved payload back with StarrailInfoParsed.parse_raw. That method belongs to pydantic v1. On a v2 install, parse_raw is gone or deprecated, and the installed pydantic cannot be both 1.x and 2.x in one environment, so the resolver will either downgrade pydantic for this package or refuse. The README documents no pydantic v2 migration, no replacement call and no extra for v2 support, and the repository holds no compatibility table to check. A team already on pydantic v2 therefore has a choice to make before it installs anything: put this client in its own environment, or do the HTTP call and the model definitions itself.
merge_character_data fills a gap the API leaves between game changes
The tools module exists because of a timing problem specific to this API. When a character changes in game, the parsed data served by the API can lag until it refreshes, so a fresh fetch can come back with less than the game shows. The documented pattern is to take a snapshot, wait, take another, and merge.
old_data = await client.fetch_user(800333171)
# Change characters in game and wait for the API to refresh
# ...
new_data = await client.fetch_user(800333171)
data = tools.merge_character_data(new_data, old_data)There is also tools.remove_duplicate_character(data) for collapsing repeated characters in one payload. What the documentation leaves open is the part that decides correctness: which side wins when a field differs, whether merge keeps the newer or the older level and attributes, and whether the call mutates its arguments or returns a new model. Without those answers, merge_character_data is something to try against a known roster rather than a rule to build on, and the repository has no test directory to check the behaviour against either. The examples directory holds basic.py, data_persistence.py and merge_data.py, which show the shape of the call but not its contract.
Pickle persistence ties your cache to the model definition
The persistence example stores a fetched payload two ways, and the two round trips are not equivalent. The pickle path compresses the model directly.
# Save
pickle_data = zlib.compress(pickle.dumps(data))
print(len(pickle_data))
json_data = data.json(by_alias=True, ensure_ascii=False)
print(len(json_data))# Load
data_from_pickle = pickle.loads(zlib.decompress(pickle_data))
data_from_json = StarrailInfoParsed.parse_raw(json_data)
print(type(data_from_pickle))
print(type(data_from_json))The example prints the byte length of both encodings but publishes no numbers, so you get no guidance on which one is smaller. The practical difference is durability. A pickle is tied to the class layout that wrote it, so a library upgrade that adds, renames or reorders a field can leave you with a file that no longer unpickles, and the README documents no version stamp, no migration step and no forward compatibility policy for stored payloads. The JSON side survives field changes, but it is written with by_alias=True, so the saved keys are the field aliases rather than the Python names, and anything reading those files needs the same model version to interpret them. If you are caching, keep a version marker of your own.
The name points at a proxy core, and only the README tells you which one
mihomo is a name shared with at least one unrelated product, and a reader arriving from a search will often be looking at the wrong repository. Everything inside the tree under review is Python: LICENSE, README.md, examples/, mihomo/, pyproject.toml, with a client class, a models package, a models.v1 subpackage and a tools module, all aimed at the endpoint https://api.mihomo.me/sr_info_parsed/{UID}?lang={LANG}. Nothing in the code or the documentation is a proxy, a VPN or a network core, and the declared homepage wiki.metacubex.one is the one part of the metadata that does not obviously belong to this tree. The practical consequence is that code snippets, install commands and version numbers found under this name need their source repository checked before use, since the release tags here run into the 1.19 range while the package version is 1.1.7. The project is MIT licensed, the default branch is main, and the last push was on 2026-09-25.
Editorial conclusion
Use mihomo if your Python program needs typed Honkai: Star Rail user data and you are on pydantic 1.x with aiohttp 3, and if you can live with a client that speaks only the two parsed formats the API serves. Leave it alone if your environment is already on pydantic 2, since the dependency pin is pydantic==1.* and the README documents no v2 path, and do not assume the merge helpers are safe defaults, since the README does not state which side wins on a conflict. Verify three things first: that the install command, which pulls from github.com/KT-Yeh/mihomo.git, is the tree you meant to test, that the release tags you plan to pin correspond to the 1.1.7 version in pyproject.toml, and that your own license review of the MIT file at the repository root is acceptable. The last push was on 2026-09-25.
Frequently asked questions
How do I install the mihomo Python model library?
The README gives one command, `pip install -U git+https://github.com/KT-Yeh/mihomo.git`, which installs a branch tip rather than a tagged release. Note that it pulls from a different GitHub account than the repository hosting the documentation, so clone the tree you actually want to test.
What is the difference between fetch_user and fetch_user_v1 in mihomo?
They read the two parsed formats the API serves. fetch_user_v1 adds version=v1 to the request and returns mihomo.models.v1.StarrailInfoParsedV1, while fetch_user reads the default format and returns mihomo.models.StarrailInfoParsed, with each format defined in its own directory.
Does mihomo work with pydantic v2?
The dependency is pinned to pydantic==1.*, and the persistence example loads saved JSON with StarrailInfoParsed.parse_raw, a pydantic v1 method. The README documents no pydantic v2 path or migration, so an environment already on v2 has to isolate this client or write its own client.
How do I cache Honkai Star Rail data fetched with mihomo?
The documented pattern compresses the model with pickle and zlib, and separately serialises it with data.json(by_alias=True, ensure_ascii=False), then reloads the JSON with StarrailInfoParsed.parse_raw. Pickle output depends on the model layout at write time, and the README documents no version stamp or migration for stored files.
What do the mihomo tools merge_character_data and remove_duplicate_character do?
remove_duplicate_character collapses repeated characters in one payload, and merge_character_data combines a new fetch with an older snapshot, which the example shows for the case where characters changed in game and the API has not refreshed. The README does not state which side wins a conflict or whether the call mutates its arguments.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/metacubex-mihomo)