If you have climbed out of Bronze in Marvel Rivals and want proof beyond a screenshot, a personal Marvel Rivals rank tracker gives you a running log of every rank score change, hero you queued, and match result tied to your account. Season 9.5 is live as of August 2026, competitive mode now spans nine core ranks and 23 total divisions, and a handful of community-run APIs make it possible to pull your own stats without waiting on an official NetEase dashboard. This tutorial walks through building a working tracker from scratch: fetching your rank score, storing it locally, charting your climb, and getting a Discord ping when your rating moves. Budget about 30 minutes for the core setup, longer if you add the automation and alerting steps at the end.
Why Build Your Own Marvel Rivals Rank Tracker
Sites like RivalsMeta and RivalsDB already show hero win rates, pick rates, and season leaderboards, and they do a good job of it. What they do not do well is track your personal rank score (RS) history over time, tell you exactly when a loss streak started, or ping you the moment you cross into a new tier. A self-hosted tracker fills that gap. It also gives you raw data to answer questions a public leaderboard can’t, like which heroes correlate with your best win rates or how much RS you lose per loss versus gain per win at your current tier.
There’s a practical reason too. Marvel Rivals does not expose the level of match-history detail that, say, Overwatch 2’s career profile does. Community projects such as MarvelRivalsAPI.com stepped in to fill that hole by scraping and caching player stats behind a documented REST API. Building your own tracker on top of one of these APIs means you own your data, can back it up, and can extend it however you want instead of being locked into a third-party site’s UI.
A good comparison is what serious ladder climbers already do in other competitive games. Chess players export their rating history from Chess.com. League of Legends players screenshot their LP graph before a reset. A Marvel Rivals rank tracker just automates that habit instead of relying on memory or manual screenshots, and it captures data at a consistent cadence so gaps in your history don’t depend on whether you remembered to check that day. Once you have a few months of snapshots, patterns show up that are invisible match to match: whether you climb faster on certain days, whether a particular hero pick correlates with longer win streaks, or whether your RS gains taper off the moment you hit a specific tier.
Prerequisites: What You Need Before Starting
This tutorial uses Python because its standard library already ships with SQLite support, which keeps the dependency list short. You don’t need to be an experienced developer, but you should be comfortable running commands in a terminal. Here’s what to have installed and ready before Step 1:
- Python 3.11 or newer (check with
python3 --version). Python ships sqlite3 built in, so no separate database install is needed. - pip 23.x or newer for installing the two external packages this project needs.
- requests 2.31+, which handles the HTTP calls to the stats API.
- matplotlib 3.8+, used later to chart your rank score over time.
- A Marvel Rivals account that has unlocked competitive mode (Account Level 10), since the tracker is only useful once you have ranked matches to log.
- Your exact in-game display name or player ID, which you’ll use to query the stats API.
- Optional: a Discord server where you have permission to create a webhook, for the alerting step near the end.
You’ll also want roughly 30 minutes of uninterrupted time for the core build (Steps 1 through 6), plus another 15 to 20 minutes if you want to add the automation, charting, and Discord alert steps. None of this requires paid API access. The community stats providers used here are free for personal, low-volume use.
Marvel Rivals Season 9.5 Rank System, Explained
Before writing any code, it helps to know exactly what data you’re tracking. Marvel Rivals competitive mode runs on nine core ranks, and every rank from Bronze through Celestial splits into three sub-tiers (III, the lowest, up to I, the highest). That gives you 21 sub-tiers, plus Eternity and One Above All, which have no sub-divisions, for 23 total skill divisions. Climbing from one sub-tier to the next generally costs around 100 rank score points, and a full rank jump (say Gold I to Platinum III) costs roughly 300 points, based on current season guides. Once you reach Eternity, the tier system drops away and you simply accumulate or lose rating points directly. One Above All isn’t a fixed rating threshold. It’s reserved for the top 500 players by RS on each platform during the season.
| Rank | Sub-Tiers | Approx. RS Range | Notes |
|---|---|---|---|
| Bronze | III–I | 0–899 | Default starting rank for new competitive players |
| Silver | III–I | 900–1,799 | |
| Gold | III–I | 1,800–2,699 | Hero bans unlock once all players are Gold III+ |
| Platinum | III–I | 2,700–3,599 | Chrono Shield recharges slower, no full reset after a loss |
| Diamond | III–I | 3,600–4,499 | |
| Grandmaster | III–I | 4,500–5,399 | |
| Celestial | III–I | 5,400+ (season-relative) | Last tiered rank before open-ended scoring |
| Eternity | None | Points accumulate directly | No sub-tiers, no rank floor loss below this point |
| One Above All | None | Top 500 players by RS | Season 9.5 top scores cluster around 5,300–5,450 RS |
RS thresholds shift slightly between seasons as the developer rebalances matchmaking, so treat the ranges above as directional rather than exact. Your tracker will pull the live rank name and RS value directly from the API on every run, which matters more than memorizing cutoffs.
Rank Score vs. MMR: What Your Tracker Actually Sees
It helps to separate two numbers that get conflated a lot in community discussion: rank score and matchmaking rating. Rank score (RS) is the visible number tied to your tier and division, the one that goes up on a win and down on a loss. Matchmaking rating (MMR) is a hidden internal value the matchmaker uses to build balanced lobbies, and it can diverge from your visible RS, especially right after a season reset or a long break from ranked play. A community stats API only ever exposes RS, since MMR isn’t a public field NetEase publishes. That’s fine for a rank tracker: RS is what determines your tier, your climb, and what shows up on the leaderboard, so it’s the number worth logging. If you ever see your rank stay flat for several matches despite winning, that’s usually the gap between visible RS and the hidden MMR narrowing behind the scenes, not a bug in your tracker.
Step 1: Pick Your Data Source
NetEase has not published a fully open official stats API for Marvel Rivals, so community projects fill that role. The two most commonly referenced in 2026 guides are MarvelRivalsAPI.com, which exposes a documented v2 REST API including a player leaderboard endpoint, and a separate community project called mrapi.org that offers rank distribution and player endpoints. This tutorial builds against MarvelRivalsAPI.com’s documented structure because it publishes stable, versioned endpoints and clear docs. If that service is ever rate-limited or down when you try this, the same code pattern below works against any JSON-returning stats API with minor field-name changes.
Sign up for a free API key if the provider requires one for your usage tier, and keep it somewhere you won’t accidentally commit to a public repository. A simple environment variable works fine for a personal project like this.
Worth noting: these community APIs exist because fans built them, not because NetEase officially endorses a specific one. That means uptime and response shape can shift without warning when the maintainer pushes an update. Building your Marvel Rivals rank tracker with a thin API client layer, like rivals_client.py in the next step, keeps that risk contained. If the provider changes its endpoint structure, you only have to update one file instead of hunting through every script that touches player data.
Step 2: Set Up Your Project Environment
Create a dedicated folder and a virtual environment so this project’s dependencies stay isolated from anything else on your machine.
mkdir marvel-rivals-tracker
cd marvel-rivals-tracker
python3 -m venv venv
source venv/bin/activate # on Windows: venv\Scripts\activate
pip install requests matplotlib
Confirm both packages installed correctly before moving on:
python3 -c "import requests, matplotlib; print(requests.__version__, matplotlib.__version__)"
You should see two version numbers printed with no errors. If you get a ModuleNotFoundError here, double-check that the virtual environment is actually activated (your terminal prompt should show (venv) at the start).
Step 3: Write the API Client Function
Create a file called rivals_client.py. This module handles all communication with the stats API, so the rest of your tracker never has to know the details of the HTTP request itself.
import os
import requests
API_BASE = "https://marvelrivalsapi.com/api/v2"
API_KEY = os.environ.get("MRAPI_KEY", "")
def fetch_player_stats(player_name: str) -> dict:
"""Fetch current rank, RS, and match summary for a player."""
headers = {"Accept": "application/json"}
if API_KEY:
headers["Authorization"] = f"Bearer {API_KEY}"
url = f"{API_BASE}/players/{player_name}"
response = requests.get(url, headers=headers, timeout=10)
response.raise_for_status()
return response.json()
if __name__ == "__main__":
import sys
name = sys.argv[1] if len(sys.argv) > 1 else "your_ign_here"
data = fetch_player_stats(name)
print(data)
Run it with your own in-game name to confirm you’re getting real data back:
python3 rivals_client.py YourIGN
A working response returns a JSON object with fields for rank name, rank score, and a match history array. If you get a 404, double-check your exact display name including capitalization, since most stats APIs are case-sensitive on player lookups.
What a Real Response Looks Like
Before writing the parser in Step 4, it’s worth looking at the actual shape of the data you’re working with. A trimmed example response from a player lookup looks roughly like this (field names vary by provider, so treat this as illustrative):
{
"name": "YourIGN",
"season": "9.5",
"rank": {
"tier": "Gold",
"division": "II",
"score": 2140
},
"competitive": {
"wins": 84,
"losses": 71,
"matches_played": 155
},
"heroes": [
{"name": "Peni Parker", "win_rate": 0.58, "matches": 22},
{"name": "Mantis", "win_rate": 0.54, "matches": 17}
]
}
Notice the nested heroes array. That’s the same data source you’ll tap in the Advanced Tips section later if you want per-hero win rates alongside your overall rank score.
Step 4: Parse the Rank and MMR Fields
Raw API responses usually bundle far more than you need, including hero-level breakdowns and cosmetic data. Write a small parser that pulls out just the fields your tracker cares about, so downstream code isn’t tightly coupled to the full API shape.
def parse_rank_snapshot(raw: dict) -> dict:
"""Reduce a full API response to the fields we track over time."""
rank_info = raw.get("rank", {})
return {
"player_name": raw.get("name"),
"rank_tier": rank_info.get("tier", "Unranked"),
"rank_division": rank_info.get("division"),
"rank_score": rank_info.get("score", 0),
"wins": raw.get("competitive", {}).get("wins", 0),
"losses": raw.get("competitive", {}).get("losses", 0),
"season": raw.get("season", "9.5"),
}
Field names will vary slightly depending on which community API you land on, so treat the keys above as a template. Open the raw JSON in a formatter, or just print(json.dumps(raw, indent=2)), and match the actual key names before finalizing this function.
Step 5: Create a SQLite Store for Historical Snapshots
A single API call only shows you where you stand right now. To track progress you need a history, and SQLite is the simplest way to persist one without standing up a separate database server. Create a new file, storage.py.
import sqlite3
from datetime import datetime
DB_PATH = "rivals_tracker.db"
def init_db():
conn = sqlite3.connect(DB_PATH)
conn.execute("""
CREATE TABLE IF NOT EXISTS rank_snapshots (
id INTEGER PRIMARY KEY AUTOINCREMENT,
player_name TEXT NOT NULL,
rank_tier TEXT,
rank_division TEXT,
rank_score INTEGER,
wins INTEGER,
losses INTEGER,
season TEXT,
captured_at TEXT
)
""")
conn.commit()
conn.close()
def save_snapshot(snapshot: dict, captured_at: str):
conn = sqlite3.connect(DB_PATH)
conn.execute("""
INSERT INTO rank_snapshots
(player_name, rank_tier, rank_division, rank_score, wins, losses, season, captured_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
""", (
snapshot["player_name"], snapshot["rank_tier"], snapshot["rank_division"],
snapshot["rank_score"], snapshot["wins"], snapshot["losses"],
snapshot["season"], captured_at
))
conn.commit()
conn.close()
Note the captured_at field is passed in rather than generated inside the function. Since this script may run inside an automated job, keeping the timestamp logic in the calling code makes the storage layer easier to test in isolation.
Step 6: Wire It Together Into One Run Script
Now build the script you’ll actually run day to day. Create track.py, which calls the API client, parses the response, and writes a snapshot row.
import sys
from datetime import datetime, timezone
from rivals_client import fetch_player_stats
from storage import init_db, save_snapshot
def parse_rank_snapshot(raw):
rank_info = raw.get("rank", {})
return {
"player_name": raw.get("name"),
"rank_tier": rank_info.get("tier", "Unranked"),
"rank_division": rank_info.get("division"),
"rank_score": rank_info.get("score", 0),
"wins": raw.get("competitive", {}).get("wins", 0),
"losses": raw.get("competitive", {}).get("losses", 0),
"season": raw.get("season", "9.5"),
}
def main():
if len(sys.argv) < 2:
print("Usage: python3 track.py ")
sys.exit(1)
init_db()
raw = fetch_player_stats(sys.argv[1])
snapshot = parse_rank_snapshot(raw)
now = datetime.now(timezone.utc).isoformat()
save_snapshot(snapshot, now)
print(f"Saved snapshot: {snapshot['rank_tier']} {snapshot['rank_division']} "
f"({snapshot['rank_score']} RS) at {now}")
if __name__ == "__main__":
main()
Run it once manually to confirm it works end to end:
python3 track.py YourIGN
Expected output:
Saved snapshot: Gold II (2,140 RS) at 2026-08-22T14:03:11.482910+00:00
If that line prints without an error, you have a working end-to-end pipeline: API call, parse, store. Everything from here is automation and presentation layered on top of this core.
Step 7: Automate Daily Snapshots With Cron
Running the script manually defeats the point of a tracker. On macOS or Linux, cron is the simplest scheduler for a job this small. Open your crontab with crontab -e and add a line that runs the script once a day, using the venv’s Python binary directly so cron doesn’t need the environment activated:
# Run every day at 11:00 PM local time
0 23 * * * /path/to/marvel-rivals-tracker/venv/bin/python3 /path/to/marvel-rivals-tracker/track.py YourIGN >> /path/to/marvel-rivals-tracker/tracker.log 2>&1
On Windows, Task Scheduler does the same job: point it at the venv’s python.exe and pass track.py plus your IGN as the argument, on a daily trigger. Either way, redirect output to a log file, since silent cron failures are one of the most common reasons trackers quietly stop updating.
Step 8: Calculate Rank Score Delta Between Snapshots
Raw snapshots are only half useful. What you actually want to see is how much your RS moved since the last check-in. Add this function to storage.py to pull the two most recent rows and diff them.
def get_recent_delta(player_name: str):
conn = sqlite3.connect(DB_PATH)
conn.row_factory = sqlite3.Row
rows = conn.execute("""
SELECT rank_score, captured_at FROM rank_snapshots
WHERE player_name = ?
ORDER BY captured_at DESC LIMIT 2
""", (player_name,)).fetchall()
conn.close()
if len(rows) < 2:
return None
latest, previous = rows[0], rows[1]
return {
"delta": latest["rank_score"] - previous["rank_score"],
"current_score": latest["rank_score"],
"since": previous["captured_at"],
}
A positive delta means you climbed since the last snapshot, negative means you dropped. This is the same number a Discord alert (Step 10) will use to decide whether to notify you.
Step 9: Chart Your Rank Progress Over Time
With a few weeks of snapshots in the database, a chart tells the story better than a table of numbers. Create plot_progress.py:
import sqlite3
import matplotlib.pyplot as plt
from datetime import datetime
DB_PATH = "rivals_tracker.db"
def plot_rank_history(player_name: str):
conn = sqlite3.connect(DB_PATH)
rows = conn.execute("""
SELECT captured_at, rank_score FROM rank_snapshots
WHERE player_name = ? ORDER BY captured_at ASC
""", (player_name,)).fetchall()
conn.close()
dates = [datetime.fromisoformat(r[0]) for r in rows]
scores = [r[1] for r in rows]
plt.figure(figsize=(10, 5))
plt.plot(dates, scores, marker="o", linewidth=2)
plt.title(f"{player_name} — Rank Score Over Time")
plt.xlabel("Date")
plt.ylabel("Rank Score (RS)")
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig(f"{player_name}_rank_history.png")
print(f"Chart saved to {player_name}_rank_history.png")
if __name__ == "__main__":
import sys
plot_rank_history(sys.argv[1])
Run python3 plot_progress.py YourIGN after at least three or four snapshots exist. Two points make a mostly meaningless line, but a week of daily snapshots is enough to see whether you're trending up or stuck.
Step 10: Send a Discord Alert on Rank Changes
This step is optional but turns a passive log into something that actually notifies you. Create a webhook in your Discord server (Server Settings → Integrations → Webhooks), copy the URL, and add this function to track.py.
import requests
DISCORD_WEBHOOK_URL = "https://discord.com/api/webhooks/your-webhook-id/your-token"
def notify_discord(snapshot, delta_info):
if not delta_info or delta_info["delta"] == 0:
return
direction = "climbed" if delta_info["delta"] > 0 else "dropped"
message = (
f"**{snapshot['player_name']}** {direction} to "
f"{snapshot['rank_tier']} {snapshot['rank_division']} "
f"({delta_info['current_score']} RS, {delta_info['delta']:+d} since last check)"
)
requests.post(DISCORD_WEBHOOK_URL, json={"content": message}, timeout=10)
Call notify_discord(snapshot, get_recent_delta(sys.argv[1])) at the end of your main() function in track.py, and your cron job will now ping a Discord channel every time your rank score changes between runs.
Step 11: The Complete Working Project
At this point your project folder should contain four files: rivals_client.py (API calls), storage.py (SQLite persistence and delta math), track.py (the daily entry point, wired into cron), and plot_progress.py (charting, run manually whenever you want an updated graph). Together they form a complete, working pipeline: fetch your live rank, store it with a timestamp, calculate how much it moved, notify you in Discord, and visualize the trend on demand. Nothing here depends on a paid service, and the entire dataset lives in a single portable SQLite file you can back up or move to a new machine by copying one file.
Total setup time for the core four files, from an empty folder to a working track.py run, lands around 25 to 30 minutes for most people who already have Python installed. The cron automation and Discord webhook add another 10 to 15 minutes, mostly spent copying webhook URLs and confirming absolute file paths. That's a reasonable trade for a tool that keeps running quietly in the background for the rest of the season without any further attention from you.
From here, natural extensions include tracking hero-level win rates alongside overall RS (the same API responses that carry rank data usually carry a per-hero breakdown too), or exporting the SQLite table to a CSV for deeper analysis in a spreadsheet.
What Else Your Marvel Rivals Rank Tracker Can Log
Rank score is the headline number, but it isn't the only useful thing sitting in the API response you're already fetching. A GamesRadar breakdown of the ranked system points out that rank-dependent rules, like the hero ban system that unlocks at Gold III, change how a match plays out well before you touch the top ranks. If your tracker only logs RS, you lose the context of when those rule changes started applying to your matches. Extending the rank_snapshots table with a handful of extra columns fixes that cheaply.
- Win/loss streaks. Derive this from consecutive snapshot deltas rather than storing it directly, since it's cheaper to compute on read than to keep in sync on write.
- Matches played since last snapshot. Comparing
matches_playedbetween two rows tells you how active a session was, which is useful context when RS moves a lot in one day. - Season boundary markers. Storing the season string per snapshot, as the schema in Step 5 already does, lets you filter charts to a single season instead of a misleading line that crosses a reset.
- Hero pick history. A current tier breakdown of Marvel Rivals ranks reinforces that climbing strategy shifts meaningfully by tier, so knowing which heroes you queued at each rank helps you spot whether a specific pick correlates with your best or worst RS swings.
None of these require a new API call. They're already sitting in the same JSON payload your fetch_player_stats function pulls down in Step 3, so the marginal cost of tracking them is a few extra lines in your parser, not a second round trip to the API.
Step 12: Common Pitfalls When Building a Marvel Rivals Rank Tracker
- Hardcoding field names before checking the raw response. Community APIs change their JSON shape between updates more often than official ones. Always print the raw response once and confirm key names before writing your parser.
- Skipping timeout values on requests.get(). Without a timeout parameter, a single slow API response can hang your cron job indefinitely, blocking every future scheduled run behind it.
- Storing rank tier as a raw string without the sub-division. "Gold" alone loses the difference between Gold III and Gold I. Always store tier and division as separate fields, as shown in Step 4, so later queries can sort correctly.
- Forgetting that display names can contain spaces or special characters. URL-encode the player name before inserting it into your API request, or you'll get intermittent 400 errors that are hard to reproduce.
- Not handling season rollovers. RS resets or compresses at the start of a new competitive season. If your chart suddenly shows a large negative drop on a specific date, check whether that date lines up with a season change before assuming your code is broken.
- Running the tracker more often than the API's rate limit allows. Free community API tiers are usually capped in the low hundreds of requests per hour. Once a day per player is plenty for a personal tracker, since polling every few minutes will get you throttled or blocked.
- Assuming the API is always up. Community-run services don't carry the uptime guarantees of an official first-party API. Wrap every
fetch_player_statscall in a try/except that logs the failure and exits cleanly, so one bad night for the API doesn't crash your cron job or leave a corrupted row in the database.
Troubleshooting Guide
Even a small script like this hits predictable snags, and most of them show up in the first week while you're still tuning field names and cron paths. Here are the issues most likely to come up, roughly in the order you're likely to hit them as you move from a manual test run to a fully automated Marvel Rivals rank tracker.
| Symptom | Likely Cause | Fix |
|---|---|---|
| ModuleNotFoundError on import requests | Virtual environment not activated | Run source venv/bin/activate before executing any script |
| HTTP 404 on player lookup | Display name mismatch (case or spacing) | Copy the exact IGN from your in-game profile, including capitalization |
| HTTP 429 responses | Rate limit exceeded | Reduce polling frequency, a daily cron job is enough for personal tracking |
| KeyError when parsing the response | API response shape changed or field is missing for unranked players | Use .get() with defaults everywhere instead of direct dict indexing |
| sqlite3.OperationalError: database is locked | Two processes writing to the same DB file simultaneously | Ensure only one cron job or script instance runs at a time |
| Cron job never runs | Wrong Python path or missing absolute paths in crontab | Use the full path to the venv's python3 binary and the full script path |
| Chart shows no data / empty plot | Fewer than two snapshots exist yet | Wait for at least two cron runs, or run track.py manually a couple times first |
| Discord webhook silently does nothing | Delta is zero, or webhook URL is wrong | Check that your rank score actually changed since the last snapshot, then test the webhook URL with a manual curl POST |
| SSL / connection errors on fetch_player_stats | Local firewall, VPN, or the API endpoint is temporarily down | Retry after a few minutes, and wrap the call in a try/except to log failures instead of crashing the whole job |
Advanced Tips for a Better Tracker
Track Hero-Level Performance Alongside Rank
Most stats APIs return a per-hero breakdown in the same response you're already fetching for rank data. RivalsMeta's Season 9.5 aggregate data shows heroes like Peni Parker and Mantis posting win rates in the 57% range across the wider player base. Extending your rank_snapshots table with a second hero_snapshots table, keyed the same way, lets you compare your personal hero win rates against that kind of season-wide baseline instead of just staring at your own numbers in isolation.
Add a Rank Decay Warning
If your competitive queue tends to go quiet for stretches, add a check in track.py that compares the current timestamp against your last snapshot's captured_at value. If more than seven days have passed with no new matches, fire a separate Discord message reminding you that inactivity can affect your seasonal placement in some rank systems.
Export to a Public Dashboard
Once the SQLite pipeline is stable, a lightweight Flask or FastAPI endpoint that reads from the same database can expose a simple read-only JSON feed. That's a natural next step if you want to embed your rank history chart on a personal site or share progress with teammates without giving them file access to your database.
Track a Full Duo or Team Roster
If you queue with a regular group, add a small config file listing every teammate's in-game name, then loop track.py over that list inside the same cron job. Store each player's snapshots in the same rank_snapshots table, since the player_name column already separates them. From there, a single chart function can plot multiple lines on the same figure, useful for spotting whether the whole squad climbs together or whether one player's RS is dragging behind the rest during a losing stretch.
How This Compares to Existing Marvel Rivals Trackers
Building your own tracker doesn't mean the established sites aren't useful, they're just built for a different job: aggregate meta analysis across the whole player base rather than a personal history log. Here's how the main options stack up as of Season 9.5.
| Tool | Type | Best For | Personal History Log |
|---|---|---|---|
| RivalsMeta | Web dashboard | Hero tier lists, win/pick rates, season leaderboards | No, snapshot only |
| RivalsDB | Web dashboard | Thorough score-based player rankings | No, snapshot only |
| RivalsTracker | Web dashboard | Live leaderboard, 55 tracked heroes | No, snapshot only |
| MarvelRivalsAPI.com | Community REST API | Programmatic access, building custom tools | You build it (this tutorial) |
| Your self-hosted tracker | Python + SQLite | Personal RS history, alerts, custom charts | Yes, by design |
In practice, most serious climbers end up using both: a public dashboard for hero meta research before queuing, and a personal tracker like the one built here for the actual rank progress log that no aggregate site keeps for you. A 2025 writeup from TheGamer on the rise of fan-made Marvel Rivals tracking sites made a similar point about the original wave of community trackers: they exist because players wanted to see how good they actually are, not just where they rank in a single snapshot. A personal, self-hosted tracker takes that same idea and narrows it down to one account, which is exactly the use case an aggregate leaderboard was never designed to serve.
Frequently Asked Questions
Does Marvel Rivals have an official stats API?
Not a fully open one as of Season 9.5. NetEase has not published a public, official stats API comparable to what some other shooters offer. Community projects like MarvelRivalsAPI.com and mrapi.org built their own APIs by aggregating publicly visible player data, and they're the de facto option for anyone building a custom tracker. That could change in a future season if NetEase decides to open a first-party endpoint, but until then, the pattern in this tutorial (a thin client wrapping a community API) is the standard approach.
Is it against the rules to use a third-party Marvel Rivals tracker or API?
Read-only stats tools that pull publicly visible profile data, without modifying the game client or automating in-match actions, fall into a very different category from cheats or gameplay-altering mods. The tracker built in this tutorial never touches your game client, never sends inputs into a match, and never reads memory from the running game process. It's a separate script that talks to a web API over HTTP, the same way your browser does when you check a public leaderboard. Still, always check the current terms of service for your account region, since policies can change between seasons, and avoid any tool that asks for your account password rather than just your public in-game name.
How many ranks does Marvel Rivals have in 2026?
Nine core ranks: Bronze, Silver, Gold, Platinum, Diamond, Grandmaster, Celestial, Eternity, and One Above All. Bronze through Celestial each split into three sub-tiers, bringing the total number of distinct skill divisions to 23.
What is One Above All in Marvel Rivals?
It's the top competitive rank, reserved for the top 500 players by rank score on a given platform during the season, rather than a fixed RS threshold anyone can hit by grinding to a set number.
Can I run this tracker for a teammate's account instead of my own?
Yes, as long as the data comes from a public profile lookup rather than an authenticated session tied to their account credentials. Pass their in-game name into the same scripts, and be mindful of API rate limits if you're tracking several players from one machine.
Why does my rank score drop even though I won my last match?
Match performance and matchmaking rating adjustments can offset a win's expected RS gain in some rank systems, and a season transition or placement recalculation can also cause an unexpected dip. If your tracker shows a drop right after a win, check the raw API response for that snapshot before assuming a bug in your own code.
Do I need to pay for API access to build this?
No. The community API used in this tutorial offers free access for low-volume, personal use such as a single daily snapshot per player. Heavier usage, like polling many accounts frequently, may require a paid tier depending on the provider's current limits.
Can I track hero-specific stats instead of just overall rank?
Yes. Most community API responses already include a per-hero breakdown alongside the rank data. Extend the parse_rank_snapshot function from Step 4 to pull that section out and store it in a second table, as covered in the Advanced Tips section above. Between hero-level tracking, the rank score history from Step 5, and Discord alerts from Step 10, you end up with a fuller picture of your climb than any single public leaderboard offers, since it's built entirely around your own account instead of the whole player base.
Related Coverage
- Marvel Rivals vs Valorant Ranks: 23 Steps vs 25 [2026]
- Rainbow Six Siege Stats Tracker Setup: 10 Steps, 30 Min [2026]
- Deadlock Tier List Tracker: 38 Heroes, 12 Steps [2026]
- Valorant vs Deadlock Ranks: 25 Tiers vs 66 Steps [2026]
- How to Climb Valorant Ranks: 25 Tiers, 12 Steps [2026]
- More Esports Coverage




