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.

Base URL https://switchperformance.biasedproject.com

Authentication

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.

Using a token
curl "https://switchperformance.biasedproject.com/api/v1/games?q=example" \
  -H "Authorization: Bearer spk_your_token_here"

Your tokens

/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 a groupId, and their data is shared too.
  • Frame rates and resolutions in a profile are what the game targets, from community reports: target_fps is a number or "Unlocked", resolution is "1920x1080", and resolution_type is how it scales (Fixed, Dynamic and 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

NameTypeWhat it does
qstringWords from a name (every word must match, ignoring accents and case), or a 16-digit title ID for an exact match.
pageintegerPage number, from 1.
platformstringswitch (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_cardstringSet 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.
sortstringrelevance-desc (the default with q), date-desc (the default without), name-asc, or size-desc.
publisherstringOnly this publisher (case and accent insensitive, whole name).
docked_fpsstringOnly games whose newest profile targets this frame rate when docked, such as 30 or 60.
handheld_fpsstringThe same for handheld.
res_typestringOnly games whose resolution is of this type, such as Fixed or Dynamic.
regionstringThe country whose name and artwork to prefer, as a 2-letter code. Defaults to US.
region_filterstringOnly games released in this country (a 2-letter code), or in a whole region: Europe, Asia or Americas.

Example

Request
GET /api/v1/games?q=example&sort=name-asc&page=1
Response
{
  "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

NameTypeWhat it does
idrequiredstringA 16-digit title ID, in the path. Upper or lower case.

Example

Request
GET /api/v1/games/0100000000010000
Response
{
  "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.

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

NameTypeWhat it does
regionstringA 2-letter country code: only games released there, and the contributions to them.
publisherstringOnly this publisher.
yearintegerOnly games released this year.
sizeBucketstringOnly games in this download size, as it is labelled on the page: <100MB, 100-200MB, … 15-20GB, >20GB.

Example

Request
GET /api/v1/stats?region=US
Response
{
  "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

NameTypeWhat it does
urlrequiredstringThe image address, https only, from raw.githubusercontent.com or a Nintendo domain (nintendo.net, nintendo.com). Anything else is refused with 403.
wintegerWidth in pixels. The image is never enlarged.
hintegerHeight in pixels. With both, the image is cropped to fill.

Example

Request
GET /api/v1/proxy/image?url=https%3A%2F%2Fimg-eshop.cdn.nintendo.net%2F…&w=240
Response
image/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

NameTypeWhat it does
idrequiredstringA 16-digit title ID, then .jpg. The older .png address redirects here.

Example

Request
GET /api/og/0100000000010000.jpg
Response
image/jpeg

System 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

NameTypeWhat it does
strictstringSet 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

Request
GET /api/v1/status?strict=1
Response
{
  "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

Request
GET /api/health
Response
{
  "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

Request
GET /api/version
Response
{
  "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.

StatusMeaning
400A required parameter is missing.
401A token was sent, but it is not valid or has been revoked. (Sending none is fine.)
403The image proxy was asked for an address it does not serve.
404No such game.
429Over the limit: 30 a minute without a token, 300 with one. Retry-After says how many seconds to wait.
500Something went wrong on our side. The message is deliberately vague. Try again shortly, and check the status page.
503Only from /api/v1/status?strict=1, when the system is down.
An error
{ "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-Remaining and X-RateLimit-Tier headers. 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/status is cached for 30 seconds already.
  • To read the entire library, page through /api/v1/games rather 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.