Documentation
API
The data behind this site, as JSON. Games, their performance profiles and graphics settings, and statistics for the whole library. It is the API the site itself uses, and anyone can try it with no sign-up. For more requests a minute, sign in with GitHub and make a token.
https://switchperformance.biasedproject.comAuthentication
You can call the data endpoints with nothing at all, up to 30 requests a minute (counted by IP address). If
you need more, make a token below and send it in an Authorization header: it raises your limit to 300 a minute. A token is yours, you can revoke it
whenever you like, and it is how we can tell your use apart
from everyone else’s.
To spot very heavy use, we count requests per token (or per IP address, when there is no token) for 30 days: how many, how many were turned away, when last, and the User-Agent. We do not keep what you ask for. See the privacy policy.
curl "https://switchperformance.biasedproject.com/api/v1/games?q=example" \
-H "Authorization: Bearer spk_your_token_here"Your tokens
Sign in with GitHub to make a token for a higher limit. We only read your GitHub username.
/api/v1/status, /api/health, /api/version, the image proxy and the share images
have no limit of this kind and need no token.
Conventions
- Read only. Every endpoint here is a
GET. There is nothing in this API that changes data. - JSON in UTF-8, except the image endpoints. Times are ISO 8601 in UTC.
- Title IDs are 16 hexadecimal digits, such as
0100000000010000. Games that are the same game in another region or edition share agroupId, and their data is shared too. - Frame rates and resolutions in a profile are what the game targets, from community reports:
target_fpsis a number or"Unlocked",resolutionis"1920x1080", andresolution_typeis how it scales (Fixed,Dynamicand so on). - Browsers. The JSON endpoints do not send CORS headers, so call them from a server or a script, not from another site’s page, and keep your token out of anything a visitor can read. The image proxy does allow cross-site use.
List and search games
GET/api/v1/games
Games with the newest performance profile of each, a page at a time. With no filters it is the whole library, newest first.
Parameters
| Name | Type | What it does |
|---|---|---|
q | string | Words from a name (every word must match, ignoring accents and case), or a 16-digit title ID for an exact match. |
page | integer | Page number, from 1. |
platform | string | switch (the default) or switch2. Each console is its own listing: Switch 2 titles have IDs starting 04 and are not mixed into the default one. |
key_card | string | Set to 1, with platform=switch2, to list only Game-Key Cards: releases where the card holds a key to download the game rather than the game. Flagged by contributors. |
sort | string | relevance-desc (the default with q), date-desc (the default without), name-asc, or size-desc. |
publisher | string | Only this publisher (case and accent insensitive, whole name). |
docked_fps | string | Only games whose newest profile targets this frame rate when docked, such as 30 or 60. |
handheld_fps | string | The same for handheld. |
res_type | string | Only games whose resolution is of this type, such as Fixed or Dynamic. |
region | string | The country whose name and artwork to prefer, as a 2-letter code. Defaults to US. |
region_filter | string | Only games released in this country (a 2-letter code), or in a whole region: Europe, Asia or Americas. |
Example
GET /api/v1/games?q=example&sort=name-asc&page=1{
"results": [
{
"id": "0100000000010000",
"groupId": "0100000000010000",
"names": ["Example Game"],
"regions": ["US", "GB"],
"iconUrl": "https://img-eshop.cdn.nintendo.net/…",
"bannerUrl": "https://img-eshop.cdn.nintendo.net/…",
"publisher": "Example Publisher",
"releaseDate": 20200301,
"lastUpdated": "2026-10-03T14:18:07.925Z",
"sizeInBytes": 4200000000,
"performance": {
"docked": { "resolution": "1920x1080", "target_fps": 30, "fps_behavior": "Locked", "resolution_type": "Fixed" },
"handheld": { "resolution": "1280x720", "target_fps": 30, "fps_behavior": "Stable", "resolution_type": "Fixed" }
}
}
],
"pagination": { "currentPage": 1, "totalPages": 3, "totalItems": 112 }
}- A page holds a fixed number of games. Read pagination.totalPages to know how many pages there are.
- performance is the newest profile of the game, or empty when there is none.
One game
GET/api/v1/games/{id}
Everything held about a title: its details, its graphics settings, and every performance profile, newest version first. Data for the other titles that share its group (other regions, editions) is included.
Parameters
| Name | Type | What it does |
|---|---|---|
idrequired | string | A 16-digit title ID, in the path. Upper or lower case. |
Example
GET /api/v1/games/0100000000010000{
"id": "0100000000010000",
"groupId": "0100000000010000",
"names": ["Example Game"],
"regions": ["US", "GB"],
"publisher": "Example Publisher",
"releaseDate": 20200301,
"sizeInBytes": 4200000000,
"iconUrl": "…",
"bannerUrl": "…",
"screenshots": ["…"],
"lastUpdated": "2026-10-03T14:18:07.925Z",
"graphics": {
"groupId": "0100000000010000",
"settings": { },
"contributor": ["someone"],
"status": "approved"
},
"performanceHistory": [
{
"gameVersion": "1.2.0",
"suffix": "",
"profiles": {
"docked": { "resolution": "1920x1080", "target_fps": 30, "fps_behavior": "Locked", "resolution_type": "Fixed" },
"handheld": { "resolution": "1280x720", "target_fps": 30, "fps_behavior": "Stable", "resolution_type": "Fixed" }
},
"contributor": ["someone"],
"sourcePrUrl": "https://github.com/biase-d/nx-performance/pull/…",
"lastUpdated": "2026-10-03T20:25:38.127Z"
}
],
"contributor": ["someone"],
"seo": { }
}- 404 when the ID is unknown.
- graphics is null when there are no settings for the game. seo is for the site's own pages and is not a stable part of the API.
Quick search
GET/api/v1/games/search
A short list of matches for as-you-type search: just the ID, the first name and the group.
Parameters
| Name | Type | What it does |
|---|---|---|
qrequired | string | At least three characters. Shorter, and the answer is an empty list. |
Example
GET /api/v1/games/search?q=exam[
{ "id": "0100000000010000", "name": "Example Game", "groupId": "0100000000010000" }
]- It takes the same filters as the list above, but only the first page is useful here. Use the list endpoint for anything more.
Library statistics
GET/api/v1/stats
The numbers behind the Insights page: how much of the library has data, frame-rate tallies, contributors, requests, and the timeline. Every figure follows the filters.
Parameters
| Name | Type | What it does |
|---|---|---|
region | string | A 2-letter country code: only games released there, and the contributions to them. |
publisher | string | Only this publisher. |
year | integer | Only games released this year. |
sizeBucket | string | Only games in this download size, as it is labelled on the page: <100MB, 100-200MB, … 15-20GB, >20GB. |
Example
GET /api/v1/stats?region=US{
"kpis": {
"titles": 6300, "groups": 6100, "publishers": 410, "totalSize": 59325000000000,
"profiles": 3700, "graphics": 2100, "videos": 1200,
"groupsWithData": 3800, "coverage": 0.62,
"contributors": 150, "contributions": 4300, "requests": 1200, "favorites": 90
},
"regions": [{ "code": "US", "titles": 5200 }],
"releasesByYear": [{ "year": 2020, "count": 840 }],
"topPublishers": [{ "publisher": "Example Publisher", "count": 120 }],
"sizeDistribution": [{ "bucket": "1-2GB", "count": 700 }],
"performance": {
"sampled": 3700,
"dockedFps": [{ "label": "30", "count": 2100 }],
"handheldFps": [{ "label": "30", "count": 2300 }],
"resolutionTypes": [{ "label": "Dynamic", "count": 1500 }]
},
"activityByMonth": [{ "month": "2026-09", "count": 120 }],
"topContributors": [{ "name": "someone", "contributions": 95, "groups": 80 }],
"topRequested": [{ "gameId": "…", "name": "…", "count": 12 }],
"topFavorited": [{ "gameId": "…", "name": "…", "count": 9 }],
"filteredGames": [],
"activeFilters": { "region": "US", "publisher": null, "year": null, "sizeBucket": null }
}- coverage is the share of title groups with a performance profile or graphics settings, from 0 to 1.
- A contribution is one pull request, however many files it touched. Names are matched ignoring case.
Image proxy
GET/api/v1/proxy/image
Fetches a cover or banner, resizes it and returns it as WebP. This is how the site serves artwork: cached, at a size that fits.
Parameters
| Name | Type | What it does |
|---|---|---|
urlrequired | string | The image address, https only, from raw.githubusercontent.com or a Nintendo domain (nintendo.net, nintendo.com). Anything else is refused with 403. |
w | integer | Width in pixels. The image is never enlarged. |
h | integer | Height in pixels. With both, the image is cropped to fill. |
Example
GET /api/v1/proxy/image?url=https%3A%2F%2Fimg-eshop.cdn.nintendo.net%2F…&w=240image/webp
Cache-Control: public, max-age=31536000, immutable
Access-Control-Allow-Origin: *- Responses are cached for a year, so ask for the sizes you need and stick to them.
Share image
GET/api/og/{id}.jpg
The picture used when a game page is shared: its artwork and numbers on one card.
Parameters
| Name | Type | What it does |
|---|---|---|
idrequired | string | A 16-digit title ID, then .jpg. The older .png address redirects here. |
Example
GET /api/og/0100000000010000.jpgimage/jpegSystem status
GET/api/v1/status
Whether the site and the services it depends on are up, with how long each took to answer. Cached for 30 seconds.
Parameters
| Name | Type | What it does |
|---|---|---|
strict | string | Set to 1 and the HTTP status carries the verdict: 503 when the system is down. Without it the answer is always 200 and you read the body. Use it for uptime monitors. |
Example
GET /api/v1/status?strict=1{
"status": "up",
"timestamp": "2026-10-04T10:53:19.540Z",
"latency_ms": 922,
"services": {
"database": { "status": "up", "latency": 3 },
"nintendoCdn": { "status": "up", "latency": 652 },
"github": { "status": "up", "latency": 921 },
"imageCache": { "status": "up", "latency": 1 }
},
"system": { "uptime": 5769.2, "node_version": "v24.13.0", "memory": { "rss": 278265856 } }
}- status is up, degraded or down.
Health check
GET/api/health
A lighter check of the database and storage, and whether game data is being rebuilt. 200 even when degraded; 500 only when the check itself could not run.
Example
GET /api/health{
"status": "healthy",
"latency": 3,
"services": {
"database": { "status": "healthy", "latency": "1ms" },
"storage": { "status": "up", "latency": "1ms" },
"build": { "isBuilding": false, "phase": null, "startedAt": null, "completedAt": null }
},
"timestamp": "2026-10-04T10:53:19.562Z"
}- While game data is being rebuilt, build.isBuilding is true and some pages may be briefly empty.
Version
GET/api/version
The running version, feature flags and the notices shown at the top of the site.
Example
GET /api/version{
"version": "1791105431104",
"features": { "newContributionFlow": true, "cloudStorage": true },
"announcements": [
{ "id": "…", "date": "2026-02-15", "message": "…", "type": "success", "link": "/contribute", "active": true }
],
"lastUpdated": "…"
}Errors
A request that cannot be answered gets an ordinary HTTP status, with a short message.
| Status | Meaning |
|---|---|
400 | A required parameter is missing. |
401 | A token was sent, but it is not valid or has been revoked. (Sending none is fine.) |
403 | The image proxy was asked for an address it does not serve. |
404 | No such game. |
429 | Over the limit: 30 a minute without a token, 300 with one. Retry-After says how many seconds to wait. |
500 | Something went wrong on our side. The message is deliberately vague. Try again shortly, and check the status page. |
503 | Only from /api/v1/status?strict=1, when the system is down. |
{ "message": "Game not found" }Using it kindly
- This is a community project run on a small budget. Without a token the limit is 30 a minute, with one 300, and every answer carries
X-RateLimit-Limit,X-RateLimit-RemainingandX-RateLimit-Tierheaders. A few a second is plenty, and a crawl of the whole library should be spread out. - Cache what you fetch. Profiles change when a pull request is merged, not by the minute, so an hour or a day is usually fresh enough.
/api/v1/statusis cached for 30 seconds already. - To read the entire library, page through
/api/v1/gamesrather than asking for every game one by one. Or take the data straight from its source, below. - If you run something regular, make a token for it and name it, so that if it misbehaves it can be revoked without stopping anything else. Never put a token in code that is published or that visitors can read.
- The signed-in endpoints the site uses for favourites, requests and preferences (
/api/v1/favorites,/api/v1/requests,/api/v1/preferences) work from a signed-in browser session. They are not part of this API, and may change without notice.
The data
Performance profiles, graphics settings and video links are collected in the open, in the nx-performance repository, one file per game and version, each added by a pull request with its author credited. This API is a reading view of that repository. If you want all of it, or want to correct something, that is the place to go.
The site’s own code is open source under the AGPL v3, at titledb-browser. Found something wrong in the API or these docs? Open an issue.
Nintendo Switch is a trademark of Nintendo. Switch Performance is not affiliated with Nintendo.