Difference between revisions of "Mojang API"
(Fix order of headings, standardize indentation, add name availability, profile info, and profile name change info APIs) |
|||
(74 intermediate revisions by 35 users not shown) | |||
Line 1: | Line 1: | ||
+ | This page documents the Mojang Minecraft API. You should note that all public APIs are rate limited so you are expected to cache the results. This is currently set at 600 requests per 10 minutes but this may change. For some parts of the API, demo accounts are sometimes included, sometimes not. Mojang keeps changing this. Authenticated API endpoints require authentication with a bearer token in the request headers. For information about the current authentication API, see [[Microsoft Authentication Scheme]]. | ||
− | + | API endpoints that require account authorization sometimes have security features that can result in Account Suspensions. | |
− | + | == Account Suspensions == | |
− | + | A Minecraft account can be entered into a banned/suspended state by triggering a high volume of erroneous requests, such as a high volume of 429s while uploading a skin. | |
− | == API Status == | + | These suspensions appear to be temporary, although this is speculation and the exact functionality of this automatic suspension system is unknown. |
− | GET https://status.mojang.com/check | + | |
+ | === Example Account Suspension === | ||
+ | The following is an example of what a temporary account suspension due to API abuse can look like. See [[Microsoft Authentication Scheme]] for details on logging in with this API. | ||
+ | |||
+ | This request is performed when logging into <nowiki>minecraft.net</nowiki>, resulting in the login page simply reloading with no obvious error when it occurs (as of March 6th 2024). | ||
+ | |||
+ | POST <nowiki>https://api.minecraftservices.com/authentication/login_with_xbox</nowiki> | ||
+ | |||
+ | Returns 403 with the following JSON data | ||
+ | <syntaxhighlight lang="json"> | ||
+ | { | ||
+ | "path": "/authentication/login_with_xbox", | ||
+ | "details": { | ||
+ | "reason": "ACCOUNT_SUSPENDED" | ||
+ | }, | ||
+ | "errorMessage": "Your account has been suspended. Please contact customer service." | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Other services will report that the account is banned, such as servers serving the otherwise unused message <nowiki>You are banned from playing online</nowiki>. | ||
+ | |||
+ | These suspensions typically clear within 24 hours but may require contacting Minecraft support if they don't. | ||
+ | |||
+ | == API Status (Removed) == | ||
+ | {{Warning2|1=This service was closed down by Mojang on 8 October 2021 due to incorrect status responses, saying "it was a legacy system running that we (as you might have noticed) did not update correctly, or held an accurate representation of our services". See [https://bugs.mojang.com/browse/WEB-2303?focusedCommentId=1086543&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-1086543 WEB-2303 (comment)]}} | ||
+ | |||
+ | GET <nowiki>https://status.mojang.com/check</nowiki> | ||
Returns status of various Mojang services. Possible values are <code>green</code> (no issues), <code>yellow</code> (some issues), <code>red</code> (service unavailable). | Returns status of various Mojang services. Possible values are <code>green</code> (no issues), <code>yellow</code> (some issues), <code>red</code> (service unavailable). | ||
=== Response === | === Response === | ||
− | <syntaxhighlight lang="json | + | <syntaxhighlight lang="json"> |
[ | [ | ||
{ | { | ||
Line 41: | Line 68: | ||
== Username to UUID == | == Username to UUID == | ||
− | {{Warning2|Since November 2020, Mojang stopped supporting the timestamp parameter. If a timestamp is provided, it is silently ignored and the current | + | {{Warning2|Since November 2020, Mojang quietly stopped supporting the timestamp parameter, in preparation for fully deprecating name history. If a timestamp is provided, it is silently ignored and the current UUID is returned. This was explained in [https://help.minecraft.net/hc/en-us/articles/8969841895693-Username-History-API-Removal-FAQ- this announcement], and the [https://bugs.mojang.com/browse/WEB-3367 corresponding issue] has been marked as "Won't Fix."}} |
GET <nowiki>https://api.mojang.com/users/profiles/minecraft/<username>?at=<timestamp></nowiki> | GET <nowiki>https://api.mojang.com/users/profiles/minecraft/<username>?at=<timestamp></nowiki> | ||
Line 53: | Line 80: | ||
=== Response === | === Response === | ||
− | <syntaxhighlight lang="json | + | <syntaxhighlight lang="json"> |
{ | { | ||
"name": "KrisJelbring", | "name": "KrisJelbring", | ||
Line 65: | Line 92: | ||
* <code>demo</code> only appears when true (account unpaid) | * <code>demo</code> only appears when true (account unpaid) | ||
− | If there is no player with the given username an HTTP status code 204 (No Content) | + | If there is no player with the given username an HTTP status code 404 (Not found) is sent with a JSON body looking like this: |
+ | {{Warning2|This endpoint can also send an empty body with the HTTP status code 204 (No Content) instead the 404 (Not found) status code shown here. Mojang likes to change what this endpoint returns somewhat frequently.}} | ||
+ | <syntaxhighlight lang="json"> | ||
+ | { | ||
+ | "path": "/users/profiles/minecraft/<name>", | ||
+ | "errorMessage": "Couldn't find any profile with that name" | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
If the timestamp is not a number, too big or too small the HTTP status code 400 (Bad Request) is sent with an error message looking like this: | If the timestamp is not a number, too big or too small the HTTP status code 400 (Bad Request) is sent with an error message looking like this: | ||
− | <syntaxhighlight lang="json | + | <syntaxhighlight lang="json"> |
{ | { | ||
− | + | "error": "IllegalArgumentException", | |
− | + | "errorMessage": "Invalid timestamp." | |
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Line 77: | Line 112: | ||
== Usernames to UUIDs == | == Usernames to UUIDs == | ||
POST <nowiki>https://api.mojang.com/profiles/minecraft</nowiki> | POST <nowiki>https://api.mojang.com/profiles/minecraft</nowiki> | ||
+ | |||
+ | {{Warning2|As of 23w42a, the endpoint moved to: | ||
+ | POST <nowiki>https://api.minecraftservices.com/minecraft/profile/lookup/bulk/byname</nowiki>}} | ||
This will return player UUIDs and some extras. | This will return player UUIDs and some extras. | ||
− | === | + | === Payload === |
− | <syntaxhighlight lang="json | + | <syntaxhighlight lang="json"> |
[ | [ | ||
"foo", | "foo", | ||
Line 88: | Line 126: | ||
] | ] | ||
</syntaxhighlight> | </syntaxhighlight> | ||
+ | |||
+ | === Headers === | ||
+ | Content-Type: application/json | ||
=== Response === | === Response === | ||
− | <syntaxhighlight lang="json | + | <syntaxhighlight lang="json"> |
[ | [ | ||
{ | { | ||
Line 107: | Line 148: | ||
* demo only appears when true (account unpaid) | * demo only appears when true (account unpaid) | ||
* BadRequestException is returned when any of the usernames is null or otherwise invalid | * BadRequestException is returned when any of the usernames is null or otherwise invalid | ||
− | |||
* You cannot request more than 10 names per request | * You cannot request more than 10 names per request | ||
− | == UUID to Name History == | + | == UUID to Name History (Removed) == |
+ | {{Warning2|This endpoint has been deprecated by Mojang and was removed on 13 September 2022 at 9:25 AM CET to "improve player safety and data privacy". [https://help.minecraft.net/hc/en-us/articles/8969841895693-Username-History-API-Removal-FAQ- Official Announcement]}} | ||
+ | |||
GET <nowiki>https://api.mojang.com/user/profiles/<uuid>/names</nowiki> | GET <nowiki>https://api.mojang.com/user/profiles/<uuid>/names</nowiki> | ||
− | Returns all the usernames this user has used in the past and the one they are using currently. The UUID must be given without hyphens. | + | Returns all the usernames this user has used in the past and the one they are using currently. The UUID must be given either without, or correctly formatted hyphens. |
=== Response === | === Response === | ||
− | <syntaxhighlight lang="json | + | <syntaxhighlight lang="json"> |
[ | [ | ||
{ | { | ||
Line 128: | Line 170: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | The <code>changedToAt</code> field is a | + | The <code>changedToAt</code> field is a unix timestamp in milliseconds. |
== UUID to Profile and Skin/Cape == | == UUID to Profile and Skin/Cape == | ||
Line 135: | Line 177: | ||
This will return the player's username plus any additional information about them (e.g. skins). Example: https://sessionserver.mojang.com/session/minecraft/profile/4566e69fc90748ee8d71d7ba5aa00d20 | This will return the player's username plus any additional information about them (e.g. skins). Example: https://sessionserver.mojang.com/session/minecraft/profile/4566e69fc90748ee8d71d7ba5aa00d20 | ||
− | This | + | This rate limit is around 200 requests per minute. |
[[Category:Protocol Details]] | [[Category:Protocol Details]] | ||
Line 141: | Line 183: | ||
=== Response === | === Response === | ||
− | <syntaxhighlight lang="json | + | <syntaxhighlight lang="json"> |
{ | { | ||
"id": "<profile identifier>", | "id": "<profile identifier>", | ||
Line 151: | Line 193: | ||
"signature": "<base64 string; signed data using Yggdrasil's private key>" // Only provided if ?unsigned=false is appended to url | "signature": "<base64 string; signed data using Yggdrasil's private key>" // Only provided if ?unsigned=false is appended to url | ||
} | } | ||
− | ] | + | ], |
+ | "profileActions": [] | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | |||
* <code>"legacy": true</code> will appear in the response if the user has not migrated their minecraft.net account to mojang. | * <code>"legacy": true</code> will appear in the response if the user has not migrated their minecraft.net account to mojang. | ||
The "value" base64 string for the "textures" object decoded: | The "value" base64 string for the "textures" object decoded: | ||
− | <syntaxhighlight lang="json | + | <syntaxhighlight lang="json"> |
{ | { | ||
"timestamp": <java time in ms>, | "timestamp": <java time in ms>, | ||
Line 166: | Line 208: | ||
"textures": { | "textures": { | ||
"SKIN": { | "SKIN": { | ||
− | "url": "<player skin URL>" | + | "url": "<player skin URL>", |
+ | "metadata": { | ||
+ | "model": "slim" | ||
+ | } | ||
}, | }, | ||
"CAPE": { | "CAPE": { | ||
Line 176: | Line 221: | ||
* The timestamp is sometimes in the past (probably due to cached results?) | * The timestamp is sometimes in the past (probably due to cached results?) | ||
− | * | + | * If the player has the "Steve?" skin, <code>"metadata"</code> will be missing. |
− | * If no custom skin has been set, <code>"SKIN"</code> will be missing.<br> | + | * If no custom skin has been set, <code>"SKIN"</code> will be missing.<br>When the player has no custom skin, whether the player has the “Alex?” or “Steve?” skin depends on [http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/java/util/UUID.java#l394 the Java hashCode] of their UUID. Steve is used for even hashes. Example implementations: |
** [https://github.com/mapcrafter/mapcrafter-playermarkers/blob/c583dd9157a041a3c9ec5c68244f73b8d01ac37a/playermarkers/player.php#L8-L19 PHP] | ** [https://github.com/mapcrafter/mapcrafter-playermarkers/blob/c583dd9157a041a3c9ec5c68244f73b8d01ac37a/playermarkers/player.php#L8-L19 PHP] | ||
** [https://github.com/LapisBlue/Lapitar/blob/55ede80ce4ebb5ecc2b968164afb40f61b4cc509/mc/uuid.go#L34-L36 Go] | ** [https://github.com/LapisBlue/Lapitar/blob/55ede80ce4ebb5ecc2b968164afb40f61b4cc509/mc/uuid.go#L34-L36 Go] | ||
Line 184: | Line 229: | ||
* Likewise <code>"CAPE"</code> will be missing if the account has no cape. | * Likewise <code>"CAPE"</code> will be missing if the account has no cape. | ||
− | == | + | The "profileActions" array contains a (possibly empty) list of moderation actions taken against an account: |
− | + | <syntaxhighlight lang="json"> | |
+ | "profileActions": [ | ||
+ | "FORCED_NAME_CHANGE", | ||
+ | "USING_BANNED_SKIN" | ||
+ | ] | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | * <code>"FORCED_NAME_CHANGE"</code> appears if the player must change their name before playing multiplayer. | ||
+ | * <code>"USING_BANNED_SKIN"</code> appears if the player is using a banned skin. | ||
+ | * The <code>uuid</code> path parameter can be sent with or without hyphens (e.g. <code>ef462a84-bbfd-4c27-8038-e820ad7f881e</code> and <code>ef462a84bbfd4c278038e820ad7f881e</code> are both valid). | ||
+ | |||
+ | == Blocked Servers == | ||
+ | GET <nowiki>https://sessionserver.mojang.com/blockedservers</nowiki> | ||
+ | |||
+ | Returns a list of SHA1 hashes used to check server addresses against when the client tries to connect. | ||
+ | |||
+ | Clients check the lowercase name, using the ISO-8859-1 charset, against this list. They will also attempt to check subdomains, replacing each level with a <code>*</code>. Specifically, it splits based off of the <code>.</code> in the domain, goes through each section removing one at a time. For instance, for <code>mc.example.com</code>, it would try | ||
+ | <code>mc.example.com</code>, | ||
+ | <code>*.mc.example.com</code>, <code>*.example.com</code>, and <code>*.com</code>. With IP addresses (verified by having 4 split sections, with each section being a valid integer between 0 and 255, inclusive<!-- Decompiles seem to mess this up with an empty if, but there is logic for checking the range -->) substitution starts from the end, so for <code>192.168.0.1</code>, it would try <code>192.168.0.1</code>, <code>192.168.0.*</code>, <code>192.168.*</code>, and <code>192.*</code>. | ||
+ | |||
+ | This check is done by the bootstrap class in netty. The default netty class is overridden by one in the com.mojang:netty dependency loaded by the launcher. This allows it to affect any version that used netty (1.7+) | ||
+ | |||
+ | === Response === | ||
+ | A line-separated list of all SHA1 hashes. Some of the current ~2200 hashes have been cracked. | ||
+ | |||
+ | {| class="mw-collapsible mw-collapsed" | ||
+ | |- | ||
+ | ! style="background: #f8f9fa; border: 1px solid #eaecf0; padding:0.2em 0.3em; text-align: left; font-weight: normal;" | <span style="padding-right: 0.5em;">Known cracked hashes</span> | ||
+ | |- | ||
+ | | <pre style="margin-top: 0;"> | ||
+ | 6f2520f8bd70a718c568ab5274c56bdbbfc14ef4:*.minetime.com | ||
+ | 7ea72de5f8e70a2ac45f1aa17d43f0ca3cddeedd:*.trollingbrandon.club | ||
+ | c005ad34245a8f2105658da2d6d6e8545ef0f0de:*.skygod.us | ||
+ | c645d6c6430db3069abd291ec13afebdb320714b:*.mineaqua.es | ||
+ | 8bf58811e6ebca16a01b842ff0c012db1171d7d6:*.eulablows.host | ||
+ | 8789800277882d1989d384e7941b6ad3dadab430:*.moredotsmoredots.xyz | ||
+ | e40c3456fb05687b8eeb17213a47b263d566f179:*.brandonlovescock.bid | ||
+ | 278b24ffff7f9f46cf71212a4c0948d07fb3bc35:*.brandonlovescock.club | ||
+ | c78697e385bfa58d6bd2a013f543cdfbdc297c4f:*.mineaqua.net | ||
+ | b13009db1e2fbe05465716f67c8d58b9c0503520:*.endercraft.com | ||
+ | 3e560742576af9413fca72e70f75d7ddc9416020:*.insanefactions.org | ||
+ | 986204c70d368d50ffead9031e86f2b9e70bb6d0:*.playmc.mx | ||
+ | 65ca8860fa8141da805106c0389de9d7c17e39bf:*.howdoiblacklistsrv.host | ||
+ | 7dca807cc9484b1eed109c003831faf189b6c8bf:*.brandonlovescock.online | ||
+ | c6a2203285fb0a475c1cd6ff72527209cc0ccc6e:*.brandonlovescock.press | ||
+ | e3985eb936d66c9b07aa72c15358f92965b1194e:*.insanenetwork.org | ||
+ | b140bec2347bfbe6dcae44aa876b9ba5fe66505b:*.phoenixnexus.net | ||
+ | 27ae74becc8cd701b19f25d347faa71084f69acd:*.arkhamnetwork.org | ||
+ | 48f04e89d20b15de115503f22fedfe2cb2d1ab12:brandonisan.unusualperson.com | ||
+ | 9f0f30820cebb01f6c81f0fdafefa0142660d688:*.kidslovemy500dollarranks.club | ||
+ | cc90e7b39112a48064f430d3a08bbd78a226d670:*.eccgamers.com | ||
+ | 88f155cf583c930ffed0e3e69ebc3a186ea8cbb7:*.fucktheeula.com | ||
+ | 605e6296b8dba9f0e4b8e43269fe5d053b5f4f1b:*.mojangendorsesbrazzers.webcam | ||
+ | 5d2e23d164a43fbfc4e6093074567f39b504ab51:touchmybody.redirectme.net | ||
+ | f3df314d1f816a8c2185cd7d4bcd73bbcffc4ed8:*.mojangsentamonkeyinto.space | ||
+ | 073ca448ef3d311218d7bd32d6307243ce22e7d0:*.diacraft.org | ||
+ | 33839f4006d6044a3a6675c593fada6a690bb64d:*.diacraft.de | ||
+ | e2e12f3b7b85eab81c0ee5d2e9e188df583fe281:*.eulablacklist.club | ||
+ | 11a2c115510bfa6cb56bbd18a7259a4420498fd5:*.slaughterhousepvp.com | ||
+ | 75df09492c6c979e2db41116100093bb791b8433:*.timelesspvp.net | ||
+ | d42339c120bc10a393a0b1d2c6a2e0ed4dbdd61b:*.herowars.org | ||
+ | 4a1b3b860ba0b441fa722bbcba97a614f6af9bb8:justgiveinandblockddnsbitches.ddns.net | ||
+ | b8c876f599dcf5162911bba2d543ccbd23d18ae5:brandonisagainst.health-carereform.com | ||
+ | 9a9ae8e9d0b6f3bf54c266dcd1e4ec034e13f714:brandonwatchesporn.onthewifi.com | ||
+ | 336e718ffbc705e76b4a72884172c6b95216b57c:canyouwildcardipsplease.gotdns.ch | ||
+ | 27cf97ecf24c92f1fe5c84c5ff654728c3ee37dd:letsplaysome.servecounterstrike.com | ||
+ | 32066aa0c7dc9b097eed5b00c5629ad03f250a2d:mojangbrokeintomy.homesecuritymac.com | ||
+ | 39f4bbfd123a5a5ddbf97489877831c15a70d7f2:*.primemc.org | ||
+ | f32f824d41aaed334aef248fbe3a0f8ecf4ac1a0:*.meep.in | ||
+ | c22efe4cf7fb319ca2387bbc930c1fdf77ab72fc:*.itsjerryandharry.com | ||
+ | cc8e1ae93571d144bf4b37369cb8466093d6db5a:*.thearchon.net | ||
+ | 9c0806e5ffaccb45121e57e4ce88c7bc76e057f1:*.goatpvp.com | ||
+ | 5ca81746337088b7617c851a1376e4f00d921d9e:*.gotpvp.com | ||
+ | a5944b9707fdb2cc95ed4ef188cf5f3151ac0525:*.guildcraft.org | ||
+ | e7210344ab0a2206da3bb21d03e406c0f1365981:*.redesky.com | ||
+ | de2cbbda331606a68ec2f88827f06e24cc5d0a24:*.mushmc.com.br | ||
+ | </pre> | ||
+ | |} | ||
+ | |||
+ | A quite large list of known hashes is available at: https://github.com/Reecepbcups/FollowTheEULA/blob/master/blockedServersList.txt<br> | ||
+ | Some hashes on there might not be in the current hashes list anymore. | ||
+ | |||
+ | == Statistics == | ||
+ | {{Warning2|1=This service was closed down by Mojang on 8 March 2022 because it didn't represent the total sales of Minecraft. The counter stopped at 45.6M Minecraft Java and 305k Minecraft Dungeons sales. Ined posted a statement on [https://twitter.com/Mojang_Ined/status/1501541417784852484 Twitter]}} | ||
+ | |||
+ | POST <nowiki>https://api.mojang.com/orders/statistics</nowiki> | ||
+ | |||
+ | Get statistics on the sales of Minecraft. | ||
+ | |||
+ | === Payload === | ||
+ | The payload is a JSON list of options under the metricKeys key. | ||
+ | You will receive a single object corresponding to the sum of sales of the requested type(s). | ||
+ | You must request at least one type of sale. | ||
+ | Below is the default list used by https://minecraft.net/en/stats/ | ||
+ | <syntaxhighlight lang="json"> | ||
+ | { | ||
+ | "metricKeys": [ | ||
+ | "item_sold_minecraft", | ||
+ | "prepaid_card_redeemed_minecraft" | ||
+ | ] | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Valid options are: | ||
+ | item_sold_minecraft | ||
+ | prepaid_card_redeemed_minecraft | ||
+ | item_sold_cobalt | ||
+ | item_sold_scrolls | ||
+ | prepaid_card_redeemed_cobalt | ||
+ | item_sold_dungeons | ||
+ | |||
+ | === Headers === | ||
+ | Content-Type: application/json | ||
+ | |||
+ | === Response === | ||
+ | A JSON object is returned with the total amount of copies sold, the number of copies sold in the last 24 hours and how many sales there are per second. | ||
+ | <syntaxhighlight lang="json"> | ||
+ | { | ||
+ | "total": integer total amount sold, | ||
+ | "last24h": integer total sold in last 24 hours, | ||
+ | "saleVelocityPerSeconds": decimal average sales per second | ||
+ | } | ||
+ | </syntaxhighlight> | ||
== Profile Information == | == Profile Information == | ||
Line 196: | Line 363: | ||
=== Response === | === Response === | ||
− | <syntaxhighlight lang="json | + | <syntaxhighlight lang="json"> |
{ | { | ||
"id": "<profile UUID>", | "id": "<profile UUID>", | ||
Line 205: | Line 372: | ||
"state": "ACTIVE", | "state": "ACTIVE", | ||
"url": "<URL to the skin image>", | "url": "<URL to the skin image>", | ||
+ | "textureKey": "<key of the texture>", | ||
"variant": "CLASSIC" // Either SLIM or CLASSIC | "variant": "CLASSIC" // Either SLIM or CLASSIC | ||
} | } | ||
], | ], | ||
− | "capes": [ | + | "capes": [] |
− | + | } | |
+ | </syntaxhighlight> | ||
+ | |||
+ | == Player Attributes == | ||
+ | GET <nowiki>https://api.minecraftservices.com/player/attributes</nowiki> | ||
+ | |||
+ | {{Warning2|Before version 1.18, this endpoint was at: | ||
+ | GET <nowiki>https://api.minecraftservices.com/privileges</nowiki>}} | ||
+ | |||
+ | This API endpoint fetches or sets information about the players online safety settings and ban status. If the player is banned then they will not be able to access Multiplayer or Realms. | ||
+ | |||
+ | The booleans for enabling online chat, multiplayer, etc are based on the Xbox Live privacy settings for the account. | ||
+ | |||
+ | "You can join multiplayer games" being set to Block will set multiplayerServer and multiplayerRealms to false. | ||
+ | |||
+ | "Others can communicate with voice, text or invites" being set to Block will set onlineChat to false. | ||
+ | |||
+ | A POST request to this endpoint is used to toggle enabling or disabling the Realms profanity filter. | ||
+ | |||
+ | === Headers === | ||
+ | Authorization: Bearer '''<access token>''' | ||
+ | |||
+ | === Payload === | ||
+ | |||
+ | (Only required if POST) | ||
+ | |||
+ | <syntaxhighlight lang="json"> | ||
+ | { | ||
+ | "profanityFilterPreferences": { | ||
+ | "profanityFilterOn": false | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | === Response === | ||
+ | <syntaxhighlight lang="json"> | ||
+ | { | ||
+ | "privileges": { | ||
+ | "onlineChat": { | ||
+ | "enabled": true | ||
+ | }, | ||
+ | "multiplayerServer": { | ||
+ | "enabled": true | ||
+ | }, | ||
+ | "multiplayerRealms": { | ||
+ | "enabled": true | ||
+ | }, | ||
+ | "telemetry": { | ||
+ | "enabled": true | ||
+ | } | ||
+ | }, | ||
+ | "profanityFilterPreferences": { | ||
+ | "profanityFilterOn": false | ||
+ | }, | ||
+ | "banStatus": { | ||
+ | "bannedScopes": { | ||
+ | "MULTIPLAYER": { // Only present if the player is banned | ||
+ | "banId": "afc009f4c6aa45e89f53f1b53ad10d64", | ||
+ | "expires": 1655933932000, // Null if the ban is permanent | ||
+ | "reason": "hate_speech", | ||
+ | "reasonMessage": "" // Nullable | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Ban reasons: | ||
+ | false_reporting | ||
+ | hate_speech | ||
+ | terrorism_or_violent_extremism | ||
+ | child_sexual_exploitation_or_abuse | ||
+ | imminent_harm | ||
+ | non_consensual_intimate_imagery | ||
+ | harassment_or_bullying | ||
+ | defamation_impersonation_false_information | ||
+ | self_harm_or_suicide | ||
+ | alcohol_tobacco_drugs | ||
+ | |||
+ | == Player Blocklist == | ||
+ | GET <nowiki>https://api.minecraftservices.com/privacy/blocklist</nowiki> | ||
+ | |||
+ | This API endpoint fetches uuids belonging to accounts that have been blocked by the player on Xbox. Chat messages and realms invites from blocked players are hidden in game. | ||
+ | |||
+ | === Headers === | ||
+ | Authorization: Bearer '''<access token>''' | ||
+ | |||
+ | === Response === | ||
+ | <syntaxhighlight lang="json"> | ||
+ | { | ||
+ | "blockedProfiles": [ | ||
+ | "39a103ac391e4ff0a882d398cba36b06" | ||
] | ] | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | == Player Certificates == | ||
+ | POST <nowiki>https://api.minecraftservices.com/player/certificates</nowiki> | ||
+ | |||
+ | This API endpoint fetches the Mojang provided key-pair for a player, which are used for cryptographically signing chat messages. | ||
+ | |||
+ | === Headers === | ||
+ | Authorization: Bearer '''<access token>''' | ||
+ | |||
+ | === Response === | ||
+ | <syntaxhighlight lang="json"> | ||
+ | { | ||
+ | "keyPair": { | ||
+ | "privateKey": "-----BEGIN RSA PRIVATE KEY-----\n ... \n-----END RSA PRIVATE KEY-----\n", | ||
+ | "publicKey": "-----BEGIN RSA PUBLIC KEY-----\n ... \n-----END RSA PUBLIC KEY-----\n" | ||
+ | }, | ||
+ | "publicKeySignature": "[base64 string; signed data]", | ||
+ | "publicKeySignatureV2": "[base64 string; signed data]", | ||
+ | "expiresAt": "2022-04-30T00:11:32.174783069Z", | ||
+ | "refreshedAfter": "2022-04-29T16:11:32.174783069Z" | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Line 223: | Line 504: | ||
=== Response === | === Response === | ||
− | <syntaxhighlight lang="json | + | <syntaxhighlight lang="json"> |
{ | { | ||
"changedAt": "2019-12-17T03:19:31Z", | "changedAt": "2019-12-17T03:19:31Z", | ||
Line 230: | Line 511: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
+ | |||
+ | == Check Product Voucher == | ||
+ | GET <nowiki>https://api.minecraftservices.com/productvoucher/giftcode</nowiki> | ||
+ | |||
+ | This API endpoint checks if the gift card is valid. | ||
+ | |||
+ | === Headers === | ||
+ | Authorization: Bearer '''<access token>''' | ||
+ | |||
+ | === Error Response === | ||
+ | <syntaxhighlight lang="json"> | ||
+ | { | ||
+ | "path": "/productvoucher/giftcode", | ||
+ | "errorType": "NOT_FOUND", | ||
+ | "error": "NOT_FOUND", | ||
+ | "errorMessage": "The server has not found anything matching the request URI", | ||
+ | "developerMessage": "The server has not found anything matching the request URI" | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | {| class="wikitable" | ||
+ | |'''Status Codes''' | ||
+ | |'''Responses''' | ||
+ | |- | ||
+ | |404 | ||
+ | |Product Voucher is invalid. (Either claimed or not activated) | ||
+ | |- | ||
+ | |200/204 | ||
+ | |Success (Product voucher is valid) | ||
+ | |} | ||
== Name Availability == | == Name Availability == | ||
− | |||
GET <nowiki>https://api.minecraftservices.com/minecraft/profile/name/</nowiki>'''<name>'''/available | GET <nowiki>https://api.minecraftservices.com/minecraft/profile/name/</nowiki>'''<name>'''/available | ||
− | This API | + | This API endpoint checks if the given name is available. |
=== Headers === | === Headers === | ||
Line 241: | Line 551: | ||
=== Response === | === Response === | ||
− | <syntaxhighlight lang="json | + | <syntaxhighlight lang="json"> |
{ | { | ||
− | "status": "DUPLICATE" // | + | "status": "DUPLICATE" // Can be DUPLICATE, AVAILABLE or NOT_ALLOWED |
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Line 259: | Line 569: | ||
=== Success Response === | === Success Response === | ||
− | <syntaxhighlight lang="json | + | <syntaxhighlight lang="json"> |
{ | { | ||
− | + | "id" : "31e0ccbef5fa4eb988592f30516f65fe", | |
− | + | "name" : "newname34234", // newly acquired name | |
− | + | "skins" : [ | |
− | + | { | |
− | + | "id" : "c97f6fea-6ca8-4bf0-bdae-b7cf91fb089c", //uuid of account | |
− | + | "state" : "ACTIVE", | |
− | + | "url" : "<nowiki>http://textures.minecraft.net/texture/3b60a1f6d562f52aaebbf1434f1de147933a3affe0e764fa49ea057536623cd3</nowiki>", //skin URL | |
− | + | "variant" : "SLIM" | |
− | + | } | |
+ | ], | ||
+ | "capes" : [] | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Error Response === | === Error Response === | ||
− | Upon error the server will send back a JSON with the error. | + | Upon error, the server will send back a JSON with the error. |
+ | |||
+ | <syntaxhighlight lang="json"> | ||
+ | { | ||
+ | "path": "/minecraft/profile/name/<name>", | ||
+ | "errorType": "FORBIDDEN", // Optional, type of error | ||
+ | "error": "FORBIDDEN", // Optional, name of the error | ||
+ | "details": { // Optional, details about the name | ||
+ | "status": "DUPLICATE" | ||
+ | }, | ||
+ | "errorMessage": "Optional error message", | ||
+ | "developerMessage": "Optional error message, same as errorMessage" | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
{| class="wikitable" | {| class="wikitable" | ||
|'''Status Codes''' | |'''Status Codes''' | ||
Line 287: | Line 613: | ||
|401 | |401 | ||
|Unauthorized (Bearer token expired or is not correct) | |Unauthorized (Bearer token expired or is not correct) | ||
+ | |- | ||
+ | |429 | ||
+ | |Too many requests sent | ||
|- | |- | ||
|500 | |500 | ||
Line 303: | Line 632: | ||
The payload for this API consists of a JSON object containing the URL and variant | The payload for this API consists of a JSON object containing the URL and variant | ||
+ | <syntaxhighlight lang="json"> | ||
{ | { | ||
"variant": "classic", | "variant": "classic", | ||
"url": "http://assets.mojang.com/SkinTemplates/steve.png" | "url": "http://assets.mojang.com/SkinTemplates/steve.png" | ||
} | } | ||
+ | </syntaxhighlight> | ||
variant is either "classic" or "slim" | variant is either "classic" or "slim" | ||
Line 312: | Line 643: | ||
=== Headers === | === Headers === | ||
Authorization: Bearer '''<access token>''' | Authorization: Bearer '''<access token>''' | ||
− | Content-Type: application/json | + | Content-Type: application/json |
=== Response === | === Response === | ||
Line 321: | Line 652: | ||
== Upload Skin == | == Upload Skin == | ||
+ | This endpoint has a rate limit of 20 requests a minute. Exceeding this will result in 429 errors. | ||
+ | Repeatedly exceeding this rate limit can result in a suspension of online services ([https://twitter.com/codeHusky/status/1765536066390429808 such as in this case]). | ||
+ | |||
POST <nowiki>https://api.minecraftservices.com/minecraft/profile/skins</nowiki> | POST <nowiki>https://api.minecraftservices.com/minecraft/profile/skins</nowiki> | ||
Line 329: | Line 663: | ||
{| class="wikitable" | {| class="wikitable" | ||
|'''variant''' | |'''variant''' | ||
− | | | + | |Either "classic" for normal models or "slim" for slim models. |
|- | |- | ||
|'''file''' | |'''file''' | ||
Line 344: | Line 678: | ||
curl -X POST -H "Authorization: Bearer '''<access token>'''" -F variant=classic -F file="@steeevee.png;type=image/png" <nowiki>https://api.minecraftservices.com/minecraft/profile/skins</nowiki> | curl -X POST -H "Authorization: Bearer '''<access token>'''" -F variant=classic -F file="@steeevee.png;type=image/png" <nowiki>https://api.minecraftservices.com/minecraft/profile/skins</nowiki> | ||
− | + | <syntaxhighlight lang="http"> | |
− | + | PUT /minecraft/profile/skins HTTP/1.1 | |
− | + | Host: api.minecraftservices.com | |
− | + | User-Agent: curl/7.49.0 | |
− | + | Accept: */* | |
− | + | Authorization: Bearer '''<access token>''' | |
− | + | Content-Length: '''<length>''' | |
− | + | Content-Type: multipart/form-data; boundary='''<boundary>''' | |
− | + | ||
− | + | --'''<boundary>''' | |
− | + | Content-Disposition: form-data; name="variant" | |
− | + | ||
− | + | classic | |
− | + | --'''<boundary>''' | |
− | + | Content-Disposition: form-data; name="file"; filename="alex.png" | |
− | + | Content-Type: image/png | |
− | + | ||
− | + | '''<image data>''' | |
+ | --'''<boundary>'''-- | ||
+ | </syntaxhighlight> | ||
== Reset Skin == | == Reset Skin == | ||
− | DELETE <nowiki>https://api. | + | DELETE <nowiki>https://api.minecraftservices.com/minecraft/profile/skins/active</nowiki> |
Resets the user's skin to the default one. | Resets the user's skin to the default one. | ||
Line 375: | Line 711: | ||
=== Example === | === Example === | ||
− | curl -X DELETE -H "Authorization: Bearer '''<access token>'''" <nowiki>https://api. | + | curl -X DELETE -H "Authorization: Bearer '''<access token>'''" <nowiki>https://api.minecraftservices.com/minecraft/profile/skins/active</nowiki> |
+ | |||
+ | <syntaxhighlight lang="http"> | ||
+ | DELETE /minecraft/profile/skins/active HTTP/1.1 | ||
+ | Host: api.minecraftservices.com | ||
+ | User-Agent: curl/7.46.0 | ||
+ | Accept: */* | ||
+ | Authorization: Bearer '''<access token>''' | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | == Hide Cape == | ||
+ | DELETE <nowiki>https://api.minecraftservices.com/minecraft/profile/capes/active</nowiki> | ||
+ | |||
+ | Prevents the current cape from being shown on the account. | ||
− | + | === Headers === | |
− | |||
− | |||
− | |||
Authorization: Bearer '''<access token>''' | Authorization: Bearer '''<access token>''' | ||
+ | |||
+ | === Response === | ||
+ | There is no response body. | ||
+ | |||
+ | {| class="wikitable" | ||
+ | |'''Status Codes''' | ||
+ | |'''Responses''' | ||
+ | |- | ||
+ | |401 | ||
+ | |Unauthorized (Bearer token expired or is not correct) | ||
+ | |- | ||
+ | |200 | ||
+ | |Success (Cape has been hidden) | ||
+ | |} | ||
+ | |||
+ | == Show Cape == | ||
+ | PUT <nowiki>https://api.minecraftservices.com/minecraft/profile/capes/active</nowiki> | ||
+ | |||
+ | === Headers === | ||
+ | Authorization: Bearer '''<access token>''' | ||
+ | Content-Type: application/json | ||
+ | |||
+ | === Success Response === | ||
+ | <syntaxhighlight lang="json"> | ||
+ | { | ||
+ | "id": "<profile UUID>", | ||
+ | "name": "<profile name>", | ||
+ | "skins": [ | ||
+ | { | ||
+ | "id": "8c94945e-d0b4-4df8-97d1-d8d397624f93", | ||
+ | "state": "ACTIVE", | ||
+ | "url": "<URL to the skin image>", | ||
+ | "variant": "CLASSIC" // Either SLIM or CLASSIC | ||
+ | } | ||
+ | ], | ||
+ | "capes": [ | ||
+ | { | ||
+ | "id": "capeid", | ||
+ | "state": "ACTIVE", | ||
+ | "url": "<URL to the cape image>", | ||
+ | "alias": "Cape Name" | ||
+ | } | ||
+ | ] | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | === Error Response === | ||
+ | <syntaxhighlight lang="json"> | ||
+ | { | ||
+ | "path": "/minecraft/profile/capes/active", | ||
+ | "errorMessage": "profile does not own cape", | ||
+ | "developerMessage": "profile does not own cape" | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | === Payload === | ||
+ | <syntaxhighlight lang="json"> | ||
+ | { | ||
+ | "capeId": "Id" | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | {| class="wikitable" | ||
+ | |'''Status Codes''' | ||
+ | |'''Responses''' | ||
+ | |- | ||
+ | |200 | ||
+ | |Success | ||
+ | |- | ||
+ | |400 | ||
+ | |Bad Request (Profile doesn't own cape) | ||
+ | |- | ||
+ | |401 | ||
+ | |Unauthorized (Bearer token expired or is not correct) | ||
+ | |} | ||
== Verify Security Location == | == Verify Security Location == | ||
Line 395: | Line 816: | ||
=== Error Response === | === Error Response === | ||
− | <syntaxhighlight lang="json | + | <syntaxhighlight lang="json"> |
{ | { | ||
"error": "ForbiddenOperationException", | "error": "ForbiddenOperationException", | ||
Line 409: | Line 830: | ||
=== Response === | === Response === | ||
− | <syntaxhighlight lang="json | + | <syntaxhighlight lang="json"> |
[ | [ | ||
{ | { | ||
Line 441: | Line 862: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | {| class="mw-collapsible mw-collapsed" style="margin-top: 0.5em;" | |
− | <pre> | + | |- |
+ | ! style="background: #f8f9fa; border: 1px solid #eaecf0; padding:0.2em 0.3em; text-align: left; font-weight: normal;" | <span style="padding-right: 0.5em;">Possible questions IDs</span> | ||
+ | |- | ||
+ | | <pre style="margin-top: 0;"> | ||
1 What is your favorite pet's name? | 1 What is your favorite pet's name? | ||
2 What is your favorite movie? | 2 What is your favorite movie? | ||
Line 483: | Line 907: | ||
39 What is your lucky number? | 39 What is your lucky number? | ||
</pre> | </pre> | ||
+ | |} | ||
== Send Security Answers == | == Send Security Answers == | ||
− | POST https://api.mojang.com/user/security/location | + | POST <nowiki>https://api.mojang.com/user/security/location</nowiki> |
=== Payload === | === Payload === | ||
− | <syntaxhighlight lang="json | + | <syntaxhighlight lang="json"> |
[ | [ | ||
{ | { | ||
Line 507: | Line 932: | ||
=== Headers === | === Headers === | ||
Authorization: Bearer '''<access token>''' | Authorization: Bearer '''<access token>''' | ||
+ | Content-Type: application/json | ||
=== Success Response === | === Success Response === | ||
Line 514: | Line 940: | ||
On failure, you will get some sort of error. Unless it's a syntax or json structure error, it will be this: | On failure, you will get some sort of error. Unless it's a syntax or json structure error, it will be this: | ||
− | <syntaxhighlight lang="json | + | <syntaxhighlight lang="json"> |
{ | { | ||
"error": "ForbiddenOperationException", | "error": "ForbiddenOperationException", | ||
Line 521: | Line 947: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | == | + | == Get Account Migration Information == |
− | GET https:// | + | GET <nowiki>https://api.minecraftservices.com/rollout/v1/msamigration</nowiki> |
+ | |||
+ | This API endpoint fetches information about the current account's ability to migrate. | ||
+ | |||
+ | === Headers === | ||
+ | Authorization: Bearer '''<access token>''' | ||
+ | |||
+ | === Response === | ||
+ | <syntaxhighlight lang="json"> | ||
+ | { | ||
+ | "feature": "msamigration", | ||
+ | "rollout": true | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | == Account Migration OTP == | ||
+ | POST <nowiki>https://api.minecraftservices.com/twofactorauth/migration/otp</nowiki> | ||
+ | |||
+ | This API endpoint returns an OTP Id used for transferring the current account later. | ||
+ | |||
+ | === Payload === | ||
+ | No payload needed. | ||
+ | |||
+ | === Headers === | ||
+ | Authorization: Bearer '''<access token>''' | ||
+ | Content-Type: application/json | ||
+ | |||
+ | === Success Response === | ||
+ | <syntaxhighlight lang="json"> | ||
+ | { | ||
+ | "otpId" : "cb694fff-220a-4213-a12e-e54e49fd7dd4" | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | {| class="wikitable" | ||
+ | |'''Status Codes''' | ||
+ | |'''Responses''' | ||
+ | |- | ||
+ | |201 | ||
+ | |Success (OTP has been received successfully) | ||
+ | |- | ||
+ | |401 | ||
+ | |Unauthorized (Bearer token expired or is not correct) | ||
+ | |} | ||
+ | |||
+ | == Verify Account Migration OTP == | ||
+ | POST <nowiki>https://api.minecraftservices.com/twofactorauth/migration/otp/<otpId>/verify</nowiki> | ||
− | + | Verifies the code sent to an account's email after a POST request to /otp. | |
− | + | === Headers === | |
+ | Authorization: Bearer '''<access token>''' | ||
+ | Content-Type: application/json | ||
− | + | === Payload === | |
+ | <syntaxhighlight lang="json"> | ||
+ | { | ||
+ | "otp": "code" | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | {| class="wikitable" | ||
+ | |'''Status Codes''' | ||
+ | |'''Responses''' | ||
+ | |- | ||
+ | |204 | ||
+ | |Success | ||
+ | |- | ||
+ | |401 | ||
+ | |Unauthorized (Bearer token expired or is not correct) | ||
+ | |} | ||
=== Response === | === Response === | ||
− | + | There is no response body. | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | == | + | == Submit Migration Token == |
− | POST <nowiki>https://api. | + | POST <nowiki>https://api.minecraftservices.com/migration/token</nowiki> |
+ | |||
+ | Used to submit the current account's email upon migrating. | ||
− | + | === Headers === | |
+ | Authorization: Bearer '''<access token>''' | ||
+ | Content-Type: application/json | ||
=== Payload === | === Payload === | ||
− | + | <syntaxhighlight lang="json"> | |
− | |||
− | |||
− | |||
− | <syntaxhighlight lang="json | ||
{ | { | ||
− | + | "sessionEmail": "accountemail" | |
− | |||
− | |||
− | |||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | {| class="wikitable" | |
− | + | |'''Status Codes''' | |
− | + | |'''Responses''' | |
− | + | |- | |
− | + | |200 | |
− | + | |Success | |
− | + | |- | |
+ | |401 | ||
+ | |Unauthorized (Bearer token expired or is not correct) | ||
+ | |} | ||
=== Response === | === Response === | ||
− | + | There is no response body. | |
− | <syntaxhighlight lang="json" | + | |
+ | == Connect Xbox Live == | ||
+ | POST <nowiki>https://sisu.xboxlive.com/connect/XboxLive</nowiki> | ||
+ | |||
+ | Connects the Mojang account to Xbox live. | ||
+ | |||
+ | === Headers === | ||
+ | Content-Type: application/json | ||
+ | |||
+ | === Payload === | ||
+ | <syntaxhighlight lang="json"> | ||
+ | { | ||
+ | "AppId": "1142970254", | ||
+ | "Callback": "https://www.minecraft.net/en-us/link-accounts", | ||
+ | "CobrandId": "fb937bf5-b9a1-4b61-b744-82f9a1adc248", | ||
+ | "ProfileName": "accountname", | ||
+ | "State": "postUpsell", | ||
+ | "TitleId": "896928775", | ||
+ | "UseModernGamertag": true | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | {| class="wikitable" | ||
+ | |'''Status Codes''' | ||
+ | |'''Responses''' | ||
+ | |- | ||
+ | |200 | ||
+ | |Success | ||
+ | |- | ||
+ | |401 | ||
+ | |Unauthorized | ||
+ | |} | ||
+ | |||
+ | === Success Response === | ||
+ | <syntaxhighlight lang="json"> | ||
{ | { | ||
− | + | "RedirectTo" : "authflowloginurl" | |
− | |||
− | |||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
+ | == Get Mojang Public Keys == | ||
+ | GET <nowiki>https://api.minecraftservices.com/publickeys</nowiki> | ||
+ | Gets the Mojang public keys used to verify player public keys. | ||
+ | There are two key lists. playerCertificateKeys are used for verifying player public keys | ||
+ | There can be multiple keys. In order for a player's public key to be deemed valid it needs to be signed by any of the keys. | ||
+ | The keys are base64 encoded. | ||
+ | |||
+ | {| class="wikitable" | ||
+ | |'''Status Codes''' | ||
+ | |'''Responses''' | ||
+ | |- | ||
+ | |200 | ||
+ | |Success | ||
+ | |} | ||
+ | |||
+ | === Success Response === | ||
+ | <syntaxhighlight lang="json"> | ||
+ | { | ||
+ | "profilePropertyKeys": [ | ||
+ | { | ||
+ | "publicKey": "MIIC....." | ||
+ | }, | ||
+ | { | ||
+ | "publicKey": "MIIC....." | ||
+ | } | ||
+ | ], | ||
+ | "playerCertificateKeys": [ | ||
+ | { | ||
+ | "publicKey": "MIIC....." | ||
+ | }, | ||
+ | { | ||
+ | "publicKey": "MIIC....." | ||
+ | } | ||
+ | ] | ||
+ | } | ||
+ | </syntaxhighlight> | ||
== Examples == | == Examples == | ||
* [https://github.com/hawezo/MojangSharp C#] - Full API wrapper | * [https://github.com/hawezo/MojangSharp C#] - Full API wrapper | ||
* [https://github.com/CmlLib/MojangAPI C#] - Full API wrapper with Mojang/Microsoft Authentication | * [https://github.com/CmlLib/MojangAPI C#] - Full API wrapper with Mojang/Microsoft Authentication | ||
+ | * [https://github.com/spnda/dart_minecraft Dart] - Almost full API wrapper with Mojang Authentication | ||
* [https://github.com/Lukaesebrot/mojango Go] - Full API wrapper | * [https://github.com/Lukaesebrot/mojango Go] - Full API wrapper | ||
* [https://github.com/PhilipBorgesen/minecraft/tree/master/profile Go] - UUIDs or names to profiles with skins, capes and name histories | * [https://github.com/PhilipBorgesen/minecraft/tree/master/profile Go] - UUIDs or names to profiles with skins, capes and name histories | ||
* [https://github.com/summer/mojang Python] - Full API Wrapper. Also supports authentication & parts of the Minecraft website | * [https://github.com/summer/mojang Python] - Full API Wrapper. Also supports authentication & parts of the Minecraft website | ||
− | * [https://github.com/ | + | * [https://github.com/Lucino772/pymojang Python] - Pymojang is a full wrapper around de Mojang API and Mojang Authentication API. Also support RCON, Query and Server List Ping |
− | * [https://github.com/ | + | * [https://github.com/SynchronousX/mojang-api Python] - Full API wrapper (not updated since 2018) |
− | * [https:// | + | * [https://github.com/techkid6/AccountsClientPython Python] - UUIDs or names to profiles (not updated since 2018) |
* [https://github.com/elyby/mojang-api PHP] - Complete Mojang's API wrapper | * [https://github.com/elyby/mojang-api PHP] - Complete Mojang's API wrapper | ||
+ | * [https://github.com/Davidoc26/mojang-api PHP] - Almost full API wrapper with Mojang Authentication. Also support head rendering | ||
* [https://github.com/MineTheCube/MojangAPI PHP] - UUIDs or names to profiles with skins, heads and name histories | * [https://github.com/MineTheCube/MojangAPI PHP] - UUIDs or names to profiles with skins, heads and name histories | ||
* [https://gist.github.com/ezfe/a71feccd3a837a2592f1 PHP] - UUIDs to names | * [https://gist.github.com/ezfe/a71feccd3a837a2592f1 PHP] - UUIDs to names | ||
Line 633: | Line 1,146: | ||
* [https://github.com/SparklingComet/java-mojang-api Java] - Almost full API Wrapper | * [https://github.com/SparklingComet/java-mojang-api Java] - Almost full API Wrapper | ||
* [https://github.com/dpkgsoft/mojang Java] - Almost full API Wrapper with auth | * [https://github.com/dpkgsoft/mojang Java] - Almost full API Wrapper with auth | ||
+ | * [https://github.com/novastosha/NMoyang Java] - Almost full API with Mojang Authentication and can also work as a console Application. | ||
* [https://github.com/thechunknetwork/mojang-api JavaScript] - UUIDs or names to profiles with skins, capes and name histories | * [https://github.com/thechunknetwork/mojang-api JavaScript] - UUIDs or names to profiles with skins, capes and name histories | ||
− | |||
[[Category:Minecraft Modern]] | [[Category:Minecraft Modern]] |
Latest revision as of 14:34, 5 September 2024
This page documents the Mojang Minecraft API. You should note that all public APIs are rate limited so you are expected to cache the results. This is currently set at 600 requests per 10 minutes but this may change. For some parts of the API, demo accounts are sometimes included, sometimes not. Mojang keeps changing this. Authenticated API endpoints require authentication with a bearer token in the request headers. For information about the current authentication API, see Microsoft Authentication Scheme.
API endpoints that require account authorization sometimes have security features that can result in Account Suspensions.
Contents
- 1 Account Suspensions
- 2 API Status (Removed)
- 3 Username to UUID
- 4 Usernames to UUIDs
- 5 UUID to Name History (Removed)
- 6 UUID to Profile and Skin/Cape
- 7 Blocked Servers
- 8 Statistics
- 9 Profile Information
- 10 Player Attributes
- 11 Player Blocklist
- 12 Player Certificates
- 13 Profile Name Change Information
- 14 Check Product Voucher
- 15 Name Availability
- 16 Change Name
- 17 Change Skin
- 18 Upload Skin
- 19 Reset Skin
- 20 Hide Cape
- 21 Show Cape
- 22 Verify Security Location
- 23 Get Security Questions
- 24 Send Security Answers
- 25 Get Account Migration Information
- 26 Account Migration OTP
- 27 Verify Account Migration OTP
- 28 Submit Migration Token
- 29 Connect Xbox Live
- 30 Get Mojang Public Keys
- 31 Examples
Account Suspensions
A Minecraft account can be entered into a banned/suspended state by triggering a high volume of erroneous requests, such as a high volume of 429s while uploading a skin.
These suspensions appear to be temporary, although this is speculation and the exact functionality of this automatic suspension system is unknown.
Example Account Suspension
The following is an example of what a temporary account suspension due to API abuse can look like. See Microsoft Authentication Scheme for details on logging in with this API.
This request is performed when logging into minecraft.net, resulting in the login page simply reloading with no obvious error when it occurs (as of March 6th 2024).
POST https://api.minecraftservices.com/authentication/login_with_xbox
Returns 403 with the following JSON data
{
"path": "/authentication/login_with_xbox",
"details": {
"reason": "ACCOUNT_SUSPENDED"
},
"errorMessage": "Your account has been suspended. Please contact customer service."
}
Other services will report that the account is banned, such as servers serving the otherwise unused message You are banned from playing online.
These suspensions typically clear within 24 hours but may require contacting Minecraft support if they don't.
API Status (Removed)
This service was closed down by Mojang on 8 October 2021 due to incorrect status responses, saying "it was a legacy system running that we (as you might have noticed) did not update correctly, or held an accurate representation of our services". See WEB-2303 (comment)
GET https://status.mojang.com/check
Returns status of various Mojang services. Possible values are green
(no issues), yellow
(some issues), red
(service unavailable).
Response
[
{
"minecraft.net": "green"
},
{
"session.minecraft.net": "green"
},
{
"account.mojang.com": "green"
},
{
"authserver.mojang.com": "green"
},
{
"sessionserver.mojang.com": "red"
},
{
"api.mojang.com": "green"
},
{
"textures.minecraft.net": "green"
},
{
"mojang.com": "green"
}
]
Username to UUID
Since November 2020, Mojang quietly stopped supporting the timestamp parameter, in preparation for fully deprecating name history. If a timestamp is provided, it is silently ignored and the current UUID is returned. This was explained in this announcement, and the corresponding issue has been marked as "Won't Fix."
GET https://api.mojang.com/users/profiles/minecraft/<username>?at=<timestamp>
This will return the UUID of the name at the timestamp provided.
?at=0
can be used to get the UUID of the original user of that username, however, it only works if the name was changed at least once, or if the account is legacy.
- The timestamp is a UNIX timestamp (without milliseconds)
- When the
at
parameter is not sent, the current time is used
Response
{
"name": "KrisJelbring",
"id": "7125ba8b1c864508b92bb5c042ccfe2b"
}
id
is the uuidname
is the current name of that uuid, it is not the name requested!legacy
only appears when true (not migrated to mojang account)demo
only appears when true (account unpaid)
If there is no player with the given username an HTTP status code 404 (Not found) is sent with a JSON body looking like this:
This endpoint can also send an empty body with the HTTP status code 204 (No Content) instead the 404 (Not found) status code shown here. Mojang likes to change what this endpoint returns somewhat frequently.
{
"path": "/users/profiles/minecraft/<name>",
"errorMessage": "Couldn't find any profile with that name"
}
If the timestamp is not a number, too big or too small the HTTP status code 400 (Bad Request) is sent with an error message looking like this:
{
"error": "IllegalArgumentException",
"errorMessage": "Invalid timestamp."
}
Usernames to UUIDs
POST https://api.mojang.com/profiles/minecraft
As of 23w42a, the endpoint moved to:
POST https://api.minecraftservices.com/minecraft/profile/lookup/bulk/byname
This will return player UUIDs and some extras.
Payload
[
"foo",
"bar",
"nonExistingPlayer"
]
Headers
Content-Type: application/json
Response
[
{
"id": "14f19f5050cb44cd9f0bbe906ad59753",
"name": "Bar"
},
{
"id": "9b15dea6606e47a4a241420251703c59",
"name": "Foo"
}
]
- name is case-corrected
- legacy only appears when true (profile not migrated to mojang.com)
- demo only appears when true (account unpaid)
- BadRequestException is returned when any of the usernames is null or otherwise invalid
- You cannot request more than 10 names per request
UUID to Name History (Removed)
This endpoint has been deprecated by Mojang and was removed on 13 September 2022 at 9:25 AM CET to "improve player safety and data privacy". Official Announcement
GET https://api.mojang.com/user/profiles/<uuid>/names
Returns all the usernames this user has used in the past and the one they are using currently. The UUID must be given either without, or correctly formatted hyphens.
Response
[
{
"name": "Gold"
},
{
"name": "Diamond",
"changedToAt": 1414059749000
}
]
The changedToAt
field is a unix timestamp in milliseconds.
UUID to Profile and Skin/Cape
GET https://sessionserver.mojang.com/session/minecraft/profile/<uuid>
This will return the player's username plus any additional information about them (e.g. skins). Example: https://sessionserver.mojang.com/session/minecraft/profile/4566e69fc90748ee8d71d7ba5aa00d20
This rate limit is around 200 requests per minute.
Response
{
"id": "<profile identifier>",
"name": "<player name>",
"properties": [
{
"name": "textures",
"value": "<base64 string>",
"signature": "<base64 string; signed data using Yggdrasil's private key>" // Only provided if ?unsigned=false is appended to url
}
],
"profileActions": []
}
"legacy": true
will appear in the response if the user has not migrated their minecraft.net account to mojang.
The "value" base64 string for the "textures" object decoded:
{
"timestamp": <java time in ms>,
"profileId": "<profile uuid>",
"profileName": "<player name>",
"signatureRequired": true, // Only present if ?unsigned=false is appended to url
"textures": {
"SKIN": {
"url": "<player skin URL>",
"metadata": {
"model": "slim"
}
},
"CAPE": {
"url": "<player cape URL>"
}
}
}
- The timestamp is sometimes in the past (probably due to cached results?)
- If the player has the "Steve?" skin,
"metadata"
will be missing. - If no custom skin has been set,
"SKIN"
will be missing.
When the player has no custom skin, whether the player has the “Alex?” or “Steve?” skin depends on the Java hashCode of their UUID. Steve is used for even hashes. Example implementations:- PHP
- Go
- JavaScript (includes explanation)
- Java (includes sample UUIDs)
- Likewise
"CAPE"
will be missing if the account has no cape.
The "profileActions" array contains a (possibly empty) list of moderation actions taken against an account:
"profileActions": [
"FORCED_NAME_CHANGE",
"USING_BANNED_SKIN"
]
"FORCED_NAME_CHANGE"
appears if the player must change their name before playing multiplayer."USING_BANNED_SKIN"
appears if the player is using a banned skin.- The
uuid
path parameter can be sent with or without hyphens (e.g.ef462a84-bbfd-4c27-8038-e820ad7f881e
andef462a84bbfd4c278038e820ad7f881e
are both valid).
Blocked Servers
GET https://sessionserver.mojang.com/blockedservers
Returns a list of SHA1 hashes used to check server addresses against when the client tries to connect.
Clients check the lowercase name, using the ISO-8859-1 charset, against this list. They will also attempt to check subdomains, replacing each level with a *
. Specifically, it splits based off of the .
in the domain, goes through each section removing one at a time. For instance, for mc.example.com
, it would try
mc.example.com
,
*.mc.example.com
, *.example.com
, and *.com
. With IP addresses (verified by having 4 split sections, with each section being a valid integer between 0 and 255, inclusive) substitution starts from the end, so for 192.168.0.1
, it would try 192.168.0.1
, 192.168.0.*
, 192.168.*
, and 192.*
.
This check is done by the bootstrap class in netty. The default netty class is overridden by one in the com.mojang:netty dependency loaded by the launcher. This allows it to affect any version that used netty (1.7+)
Response
A line-separated list of all SHA1 hashes. Some of the current ~2200 hashes have been cracked.
Known cracked hashes |
---|
6f2520f8bd70a718c568ab5274c56bdbbfc14ef4:*.minetime.com 7ea72de5f8e70a2ac45f1aa17d43f0ca3cddeedd:*.trollingbrandon.club c005ad34245a8f2105658da2d6d6e8545ef0f0de:*.skygod.us c645d6c6430db3069abd291ec13afebdb320714b:*.mineaqua.es 8bf58811e6ebca16a01b842ff0c012db1171d7d6:*.eulablows.host 8789800277882d1989d384e7941b6ad3dadab430:*.moredotsmoredots.xyz e40c3456fb05687b8eeb17213a47b263d566f179:*.brandonlovescock.bid 278b24ffff7f9f46cf71212a4c0948d07fb3bc35:*.brandonlovescock.club c78697e385bfa58d6bd2a013f543cdfbdc297c4f:*.mineaqua.net b13009db1e2fbe05465716f67c8d58b9c0503520:*.endercraft.com 3e560742576af9413fca72e70f75d7ddc9416020:*.insanefactions.org 986204c70d368d50ffead9031e86f2b9e70bb6d0:*.playmc.mx 65ca8860fa8141da805106c0389de9d7c17e39bf:*.howdoiblacklistsrv.host 7dca807cc9484b1eed109c003831faf189b6c8bf:*.brandonlovescock.online c6a2203285fb0a475c1cd6ff72527209cc0ccc6e:*.brandonlovescock.press e3985eb936d66c9b07aa72c15358f92965b1194e:*.insanenetwork.org b140bec2347bfbe6dcae44aa876b9ba5fe66505b:*.phoenixnexus.net 27ae74becc8cd701b19f25d347faa71084f69acd:*.arkhamnetwork.org 48f04e89d20b15de115503f22fedfe2cb2d1ab12:brandonisan.unusualperson.com 9f0f30820cebb01f6c81f0fdafefa0142660d688:*.kidslovemy500dollarranks.club cc90e7b39112a48064f430d3a08bbd78a226d670:*.eccgamers.com 88f155cf583c930ffed0e3e69ebc3a186ea8cbb7:*.fucktheeula.com 605e6296b8dba9f0e4b8e43269fe5d053b5f4f1b:*.mojangendorsesbrazzers.webcam 5d2e23d164a43fbfc4e6093074567f39b504ab51:touchmybody.redirectme.net f3df314d1f816a8c2185cd7d4bcd73bbcffc4ed8:*.mojangsentamonkeyinto.space 073ca448ef3d311218d7bd32d6307243ce22e7d0:*.diacraft.org 33839f4006d6044a3a6675c593fada6a690bb64d:*.diacraft.de e2e12f3b7b85eab81c0ee5d2e9e188df583fe281:*.eulablacklist.club 11a2c115510bfa6cb56bbd18a7259a4420498fd5:*.slaughterhousepvp.com 75df09492c6c979e2db41116100093bb791b8433:*.timelesspvp.net d42339c120bc10a393a0b1d2c6a2e0ed4dbdd61b:*.herowars.org 4a1b3b860ba0b441fa722bbcba97a614f6af9bb8:justgiveinandblockddnsbitches.ddns.net b8c876f599dcf5162911bba2d543ccbd23d18ae5:brandonisagainst.health-carereform.com 9a9ae8e9d0b6f3bf54c266dcd1e4ec034e13f714:brandonwatchesporn.onthewifi.com 336e718ffbc705e76b4a72884172c6b95216b57c:canyouwildcardipsplease.gotdns.ch 27cf97ecf24c92f1fe5c84c5ff654728c3ee37dd:letsplaysome.servecounterstrike.com 32066aa0c7dc9b097eed5b00c5629ad03f250a2d:mojangbrokeintomy.homesecuritymac.com 39f4bbfd123a5a5ddbf97489877831c15a70d7f2:*.primemc.org f32f824d41aaed334aef248fbe3a0f8ecf4ac1a0:*.meep.in c22efe4cf7fb319ca2387bbc930c1fdf77ab72fc:*.itsjerryandharry.com cc8e1ae93571d144bf4b37369cb8466093d6db5a:*.thearchon.net 9c0806e5ffaccb45121e57e4ce88c7bc76e057f1:*.goatpvp.com 5ca81746337088b7617c851a1376e4f00d921d9e:*.gotpvp.com a5944b9707fdb2cc95ed4ef188cf5f3151ac0525:*.guildcraft.org e7210344ab0a2206da3bb21d03e406c0f1365981:*.redesky.com de2cbbda331606a68ec2f88827f06e24cc5d0a24:*.mushmc.com.br |
A quite large list of known hashes is available at: https://github.com/Reecepbcups/FollowTheEULA/blob/master/blockedServersList.txt
Some hashes on there might not be in the current hashes list anymore.
Statistics
This service was closed down by Mojang on 8 March 2022 because it didn't represent the total sales of Minecraft. The counter stopped at 45.6M Minecraft Java and 305k Minecraft Dungeons sales. Ined posted a statement on Twitter
POST https://api.mojang.com/orders/statistics
Get statistics on the sales of Minecraft.
Payload
The payload is a JSON list of options under the metricKeys key. You will receive a single object corresponding to the sum of sales of the requested type(s). You must request at least one type of sale. Below is the default list used by https://minecraft.net/en/stats/
{
"metricKeys": [
"item_sold_minecraft",
"prepaid_card_redeemed_minecraft"
]
}
Valid options are:
item_sold_minecraft prepaid_card_redeemed_minecraft item_sold_cobalt item_sold_scrolls prepaid_card_redeemed_cobalt item_sold_dungeons
Headers
Content-Type: application/json
Response
A JSON object is returned with the total amount of copies sold, the number of copies sold in the last 24 hours and how many sales there are per second.
{
"total": integer total amount sold,
"last24h": integer total sold in last 24 hours,
"saleVelocityPerSeconds": decimal average sales per second
}
Profile Information
GET https://api.minecraftservices.com/minecraft/profile
This API endpoint fetches information about the current account including UUID, username, skins, and capes.
Headers
Authorization: Bearer <access token>
Response
{
"id": "<profile UUID>",
"name": "<profile name>",
"skins": [
{
"id": "8c94945e-d0b4-4df8-97d1-d8d397624f93",
"state": "ACTIVE",
"url": "<URL to the skin image>",
"textureKey": "<key of the texture>",
"variant": "CLASSIC" // Either SLIM or CLASSIC
}
],
"capes": []
}
Player Attributes
GET https://api.minecraftservices.com/player/attributes
This API endpoint fetches or sets information about the players online safety settings and ban status. If the player is banned then they will not be able to access Multiplayer or Realms.
The booleans for enabling online chat, multiplayer, etc are based on the Xbox Live privacy settings for the account.
"You can join multiplayer games" being set to Block will set multiplayerServer and multiplayerRealms to false.
"Others can communicate with voice, text or invites" being set to Block will set onlineChat to false.
A POST request to this endpoint is used to toggle enabling or disabling the Realms profanity filter.
Headers
Authorization: Bearer <access token>
Payload
(Only required if POST)
{
"profanityFilterPreferences": {
"profanityFilterOn": false
}
}
Response
{
"privileges": {
"onlineChat": {
"enabled": true
},
"multiplayerServer": {
"enabled": true
},
"multiplayerRealms": {
"enabled": true
},
"telemetry": {
"enabled": true
}
},
"profanityFilterPreferences": {
"profanityFilterOn": false
},
"banStatus": {
"bannedScopes": {
"MULTIPLAYER": { // Only present if the player is banned
"banId": "afc009f4c6aa45e89f53f1b53ad10d64",
"expires": 1655933932000, // Null if the ban is permanent
"reason": "hate_speech",
"reasonMessage": "" // Nullable
}
}
}
}
Ban reasons:
false_reporting hate_speech terrorism_or_violent_extremism child_sexual_exploitation_or_abuse imminent_harm non_consensual_intimate_imagery harassment_or_bullying defamation_impersonation_false_information self_harm_or_suicide alcohol_tobacco_drugs
Player Blocklist
GET https://api.minecraftservices.com/privacy/blocklist
This API endpoint fetches uuids belonging to accounts that have been blocked by the player on Xbox. Chat messages and realms invites from blocked players are hidden in game.
Headers
Authorization: Bearer <access token>
Response
{
"blockedProfiles": [
"39a103ac391e4ff0a882d398cba36b06"
]
}
Player Certificates
POST https://api.minecraftservices.com/player/certificates
This API endpoint fetches the Mojang provided key-pair for a player, which are used for cryptographically signing chat messages.
Headers
Authorization: Bearer <access token>
Response
{
"keyPair": {
"privateKey": "-----BEGIN RSA PRIVATE KEY-----\n ... \n-----END RSA PRIVATE KEY-----\n",
"publicKey": "-----BEGIN RSA PUBLIC KEY-----\n ... \n-----END RSA PUBLIC KEY-----\n"
},
"publicKeySignature": "[base64 string; signed data]",
"publicKeySignatureV2": "[base64 string; signed data]",
"expiresAt": "2022-04-30T00:11:32.174783069Z",
"refreshedAfter": "2022-04-29T16:11:32.174783069Z"
}
Profile Name Change Information
GET https://api.minecraftservices.com/minecraft/profile/namechange
This API endpoint fetches information about the profile name such as the date the name was changed and the date the account was created.
Headers
Authorization: Bearer <access token>
Response
{
"changedAt": "2019-12-17T03:19:31Z",
"createdAt": "2015-11-13T01:59:46Z",
"nameChangeAllowed": true
}
Check Product Voucher
GET https://api.minecraftservices.com/productvoucher/giftcode
This API endpoint checks if the gift card is valid.
Headers
Authorization: Bearer <access token>
Error Response
{
"path": "/productvoucher/giftcode",
"errorType": "NOT_FOUND",
"error": "NOT_FOUND",
"errorMessage": "The server has not found anything matching the request URI",
"developerMessage": "The server has not found anything matching the request URI"
}
Status Codes | Responses |
404 | Product Voucher is invalid. (Either claimed or not activated) |
200/204 | Success (Product voucher is valid) |
Name Availability
GET https://api.minecraftservices.com/minecraft/profile/name/<name>/available
This API endpoint checks if the given name is available.
Headers
Authorization: Bearer <access token>
Response
{
"status": "DUPLICATE" // Can be DUPLICATE, AVAILABLE or NOT_ALLOWED
}
Change Name
PUT https://api.minecraftservices.com/minecraft/profile/name/<name>
This will set the name for the account that the access token in the Authorization header belongs to.
Payload
No payload needed.
Headers
Authorization: Bearer <access token>
Success Response
{
"id" : "31e0ccbef5fa4eb988592f30516f65fe",
"name" : "newname34234", // newly acquired name
"skins" : [
{
"id" : "c97f6fea-6ca8-4bf0-bdae-b7cf91fb089c", //uuid of account
"state" : "ACTIVE",
"url" : "<nowiki>http://textures.minecraft.net/texture/3b60a1f6d562f52aaebbf1434f1de147933a3affe0e764fa49ea057536623cd3</nowiki>", //skin URL
"variant" : "SLIM"
}
],
"capes" : []
}
Error Response
Upon error, the server will send back a JSON with the error.
{
"path": "/minecraft/profile/name/<name>",
"errorType": "FORBIDDEN", // Optional, type of error
"error": "FORBIDDEN", // Optional, name of the error
"details": { // Optional, details about the name
"status": "DUPLICATE"
},
"errorMessage": "Optional error message",
"developerMessage": "Optional error message, same as errorMessage"
}
Status Codes | Responses |
400 | Name is invalid, longer than 16 characters or contains characters other than (a-zA-Z0-9_) |
403 | Name is unavailable (Either taken or has not become available) |
401 | Unauthorized (Bearer token expired or is not correct) |
429 | Too many requests sent |
500 | Timed out (API lagged out and could not respond) |
200 | Success (Name changed) |
Change Skin
POST https://api.minecraftservices.com/minecraft/profile/skins
This will set the skin for the selected profile, but Mojang's servers will fetch the skin from a URL.
Payload
The payload for this API consists of a JSON object containing the URL and variant
{
"variant": "classic",
"url": "http://assets.mojang.com/SkinTemplates/steve.png"
}
variant is either "classic" or "slim"
Headers
Authorization: Bearer <access token> Content-Type: application/json
Response
Upon error, the server will send back a JSON with the error. (Success is a blank payload)
Example
curl -H "Authorization: Bearer <access token>" -H "Content-Type: application/json; charset=utf-8" --request POST --data '{"variant": "classic", "url": "http://assets.mojang.com/SkinTemplates/steve.png"}' https://api.minecraftservices.com/minecraft/profile/skins
Upload Skin
This endpoint has a rate limit of 20 requests a minute. Exceeding this will result in 429 errors. Repeatedly exceeding this rate limit can result in a suspension of online services (such as in this case).
POST https://api.minecraftservices.com/minecraft/profile/skins
This uploads a skin to Mojang's servers. It also sets the user's skin. This works on legacy accounts as well.
Payload
The payload for this API consists of multipart form data. There are two parts (order does not matter b/c of boundary):
variant | Either "classic" for normal models or "slim" for slim models. |
file | Raw image file data |
Headers
Authorization: Bearer <access token>
Response
No response unless an error occurred.
Example
curl -X POST -H "Authorization: Bearer <access token>" -F variant=classic -F file="@steeevee.png;type=image/png" https://api.minecraftservices.com/minecraft/profile/skins
PUT /minecraft/profile/skins HTTP/1.1
Host: api.minecraftservices.com
User-Agent: curl/7.49.0
Accept: */*
Authorization: Bearer '''<access token>'''
Content-Length: '''<length>'''
Content-Type: multipart/form-data; boundary='''<boundary>'''
--'''<boundary>'''
Content-Disposition: form-data; name="variant"
classic
--'''<boundary>'''
Content-Disposition: form-data; name="file"; filename="alex.png"
Content-Type: image/png
'''<image data>'''
--'''<boundary>'''--
Reset Skin
DELETE https://api.minecraftservices.com/minecraft/profile/skins/active
Resets the user's skin to the default one.
Headers
Authorization: Bearer <access token>
Response
No response unless an error occurred.
Example
curl -X DELETE -H "Authorization: Bearer <access token>" https://api.minecraftservices.com/minecraft/profile/skins/active
DELETE /minecraft/profile/skins/active HTTP/1.1
Host: api.minecraftservices.com
User-Agent: curl/7.46.0
Accept: */*
Authorization: Bearer '''<access token>'''
Hide Cape
DELETE https://api.minecraftservices.com/minecraft/profile/capes/active
Prevents the current cape from being shown on the account.
Headers
Authorization: Bearer <access token>
Response
There is no response body.
Status Codes | Responses |
401 | Unauthorized (Bearer token expired or is not correct) |
200 | Success (Cape has been hidden) |
Show Cape
PUT https://api.minecraftservices.com/minecraft/profile/capes/active
Headers
Authorization: Bearer <access token> Content-Type: application/json
Success Response
{
"id": "<profile UUID>",
"name": "<profile name>",
"skins": [
{
"id": "8c94945e-d0b4-4df8-97d1-d8d397624f93",
"state": "ACTIVE",
"url": "<URL to the skin image>",
"variant": "CLASSIC" // Either SLIM or CLASSIC
}
],
"capes": [
{
"id": "capeid",
"state": "ACTIVE",
"url": "<URL to the cape image>",
"alias": "Cape Name"
}
]
}
Error Response
{
"path": "/minecraft/profile/capes/active",
"errorMessage": "profile does not own cape",
"developerMessage": "profile does not own cape"
}
Payload
{
"capeId": "Id"
}
Status Codes | Responses |
200 | Success |
400 | Bad Request (Profile doesn't own cape) |
401 | Unauthorized (Bearer token expired or is not correct) |
Verify Security Location
GET https://api.mojang.com/user/security/location
Verify's that the current IP is trusted by the server for the account and the token can be used.
Headers
Authorization: Bearer <access token>
Success Response
204 NO CONTENT
Error Response
{
"error": "ForbiddenOperationException",
"errorMessage": "Current IP is not secured"
}
Get Security Questions
GET https://api.mojang.com/user/security/challenges
Headers
Authorization: Bearer <access token>
Response
[
{
"answer": {
"id": 123
},
"question": {
"id": 1,
"question": "What is your favorite pet's name?"
}
},
{
"answer": {
"id": 456
},
"question": {
"id": 2,
"question": "What is your favorite movie?"
}
},
{
"answer": {
"id": 789
},
"question": {
"id": 3,
"question": "What is your favorite author's last name?"
}
}
],
Possible questions IDs |
---|
1 What is your favorite pet's name? 2 What is your favorite movie? 3 What is your favorite author's last name? 4 What is your favorite artist's last name? 5 What is your favorite actor's last name? 6 What is your favorite activity? 7 What is your favorite restaurant? 8 What is the name of your favorite cartoon? 9 What is the name of the first school you attended? 10 What is the last name of your favorite teacher? 11 What is your best friend's first name? 12 What is your favorite cousin's name? 13 What was the first name of your first girl/boyfriend? 14 What was the name of your first stuffed animal? 15 What is your mother's middle name? 16 What is your father's middle name? 17 What is your oldest sibling's middle name? 18 In what city did your parents meet? 19 In what hospital were you born? 20 What is your favorite team? 21 How old were you when you got your first computer? 22 How old were you when you got your first gaming console? 23 What was your first video game? 24 What is your favorite card game? 25 What is your favorite board game? 26 What was your first gaming console? 27 What was the first book you ever read? 28 Where did you go on your first holiday? 29 In what city does your grandmother live? 30 In what city does your grandfather live? 31 What is your grandmother's first name? 32 What is your grandfather's first name? 33 What is your least favorite food? 34 What is your favorite ice cream flavor? 35 What is your favorite ice cream flavor? 36 What is your favorite place to visit? 37 What is your dream job? 38 What color was your first pet? 39 What is your lucky number? |
Send Security Answers
POST https://api.mojang.com/user/security/location
Payload
[
{
"id": 123,
"answer" : "foo"
},
{
"id": 456,
"answer" : "bar"
},
{
"id": 589,
"answer" : "baz"
}
]
Headers
Authorization: Bearer <access token> Content-Type: application/json
Success Response
204 NO CONTENT
Error Response
On failure, you will get some sort of error. Unless it's a syntax or json structure error, it will be this:
{
"error": "ForbiddenOperationException",
"errorMessage": "At least one answer was incorrect"
}
Get Account Migration Information
GET https://api.minecraftservices.com/rollout/v1/msamigration
This API endpoint fetches information about the current account's ability to migrate.
Headers
Authorization: Bearer <access token>
Response
{
"feature": "msamigration",
"rollout": true
}
Account Migration OTP
POST https://api.minecraftservices.com/twofactorauth/migration/otp
This API endpoint returns an OTP Id used for transferring the current account later.
Payload
No payload needed.
Headers
Authorization: Bearer <access token> Content-Type: application/json
Success Response
{
"otpId" : "cb694fff-220a-4213-a12e-e54e49fd7dd4"
}
Status Codes | Responses |
201 | Success (OTP has been received successfully) |
401 | Unauthorized (Bearer token expired or is not correct) |
Verify Account Migration OTP
POST https://api.minecraftservices.com/twofactorauth/migration/otp/<otpId>/verify
Verifies the code sent to an account's email after a POST request to /otp.
Headers
Authorization: Bearer <access token> Content-Type: application/json
Payload
{
"otp": "code"
}
Status Codes | Responses |
204 | Success |
401 | Unauthorized (Bearer token expired or is not correct) |
Response
There is no response body.
Submit Migration Token
POST https://api.minecraftservices.com/migration/token
Used to submit the current account's email upon migrating.
Headers
Authorization: Bearer <access token> Content-Type: application/json
Payload
{
"sessionEmail": "accountemail"
}
Status Codes | Responses |
200 | Success |
401 | Unauthorized (Bearer token expired or is not correct) |
Response
There is no response body.
Connect Xbox Live
POST https://sisu.xboxlive.com/connect/XboxLive
Connects the Mojang account to Xbox live.
Headers
Content-Type: application/json
Payload
{
"AppId": "1142970254",
"Callback": "https://www.minecraft.net/en-us/link-accounts",
"CobrandId": "fb937bf5-b9a1-4b61-b744-82f9a1adc248",
"ProfileName": "accountname",
"State": "postUpsell",
"TitleId": "896928775",
"UseModernGamertag": true
}
Status Codes | Responses |
200 | Success |
401 | Unauthorized |
Success Response
{
"RedirectTo" : "authflowloginurl"
}
Get Mojang Public Keys
GET https://api.minecraftservices.com/publickeys
Gets the Mojang public keys used to verify player public keys. There are two key lists. playerCertificateKeys are used for verifying player public keys There can be multiple keys. In order for a player's public key to be deemed valid it needs to be signed by any of the keys. The keys are base64 encoded.
Status Codes | Responses |
200 | Success |
Success Response
{
"profilePropertyKeys": [
{
"publicKey": "MIIC....."
},
{
"publicKey": "MIIC....."
}
],
"playerCertificateKeys": [
{
"publicKey": "MIIC....."
},
{
"publicKey": "MIIC....."
}
]
}
Examples
- C# - Full API wrapper
- C# - Full API wrapper with Mojang/Microsoft Authentication
- Dart - Almost full API wrapper with Mojang Authentication
- Go - Full API wrapper
- Go - UUIDs or names to profiles with skins, capes and name histories
- Python - Full API Wrapper. Also supports authentication & parts of the Minecraft website
- Python - Pymojang is a full wrapper around de Mojang API and Mojang Authentication API. Also support RCON, Query and Server List Ping
- Python - Full API wrapper (not updated since 2018)
- Python - UUIDs or names to profiles (not updated since 2018)
- PHP - Complete Mojang's API wrapper
- PHP - Almost full API wrapper with Mojang Authentication. Also support head rendering
- PHP - UUIDs or names to profiles with skins, heads and name histories
- PHP - UUIDs to names
- PHP - UUIDs to names, names to uuids
- Java - Almost full API Wrapper
- Java - Almost full API Wrapper with auth
- Java - Almost full API with Mojang Authentication and can also work as a console Application.
- JavaScript - UUIDs or names to profiles with skins, capes and name histories