Difference between revisions of "Mojang API"

From wiki.vg
Jump to navigation Jump to search
m (Mojang removed the ratelimit from UUID -> Profile + Skin/Cape)
 
(8 intermediate revisions by 2 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 authentication API, see [[Authentication]].
== Notes ==
 
 
 
* 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.
 
  
 
== API Status ==
 
== API Status ==
 
+
GET <nowiki>https://status.mojang.com/check</nowiki>
  GET https://status.mojang.com/check
 
  
 
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="javascript" style="overflow-x: scroll">
 
 
[
 
[
  {
+
    {
    "minecraft.net": "yellow"
+
        "minecraft.net": "green"
  },
+
    },
  {
+
    {
    "session.minecraft.net": "green"
+
        "session.minecraft.net": "green"
  },
+
    },
  {
+
    {
    "account.mojang.com": "green"
+
        "account.mojang.com": "green"
  },
+
     },
  {
+
     {
     "auth.mojang.com": "green"
+
        "authserver.mojang.com": "green"
  },
+
    },
  {
+
    {
     "skins.minecraft.net": "green"
+
        "sessionserver.mojang.com": "red"
  },
+
    },
  {
+
    {
    "authserver.mojang.com": "green"
+
        "api.mojang.com": "green"
  },
+
    },
  {
+
    {
    "sessionserver.mojang.com": "yellow"
+
        "textures.minecraft.net": "green"
  },
+
    },
  {
+
    {
    "api.mojang.com": "green"
+
        "mojang.com": "green"
  },
+
    }
  {
 
    "textures.minecraft.net": "red"
 
  },
 
  {
 
    "mojang.com": "green"
 
  }
 
 
]
 
]
 
</syntaxhighlight>
 
</syntaxhighlight>
  
== Username -> UUID at time ==
+
== 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 uuid is returned. Please remind them to fix this here: [https://bugs.mojang.com/browse/WEB-3367 WEB-3367]}}
  
  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>
  
 
This will return the UUID of the name at the timestamp provided.
 
This will return the UUID of the name at the timestamp provided.
Line 58: Line 47:
 
* The timestamp is a [[wikipedia:Unix time|UNIX timestamp]] (without milliseconds)
 
* The timestamp is a [[wikipedia:Unix time|UNIX timestamp]] (without milliseconds)
 
* When the <code>at</code> parameter is not sent, the current time is used
 
* When the <code>at</code> parameter is not sent, the current time is used
 
{{Warning2|Since November 2020, Mojang stopped supporting the timestamp parameter. If a timestamp is provided, it is silently ignored and the current uuid is returned. Please remind them to fix this here: [https://bugs.mojang.com/browse/WEB-3367 WEB-3367]}}
 
  
 
=== Response ===
 
=== Response ===
 
+
<syntaxhighlight lang="json">
<syntaxhighlight lang="javascript" style="overflow-x: scroll">
 
 
{
 
{
  "id": "7125ba8b1c864508b92bb5c042ccfe2b",
+
    "name": "KrisJelbring",
  "name": "KrisJelbring"
+
    "id": "7125ba8b1c864508b92bb5c042ccfe2b"
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>
Line 78: Line 64:
 
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="javascript" style="overflow-x: scroll">
+
<syntaxhighlight lang="json">
 
{
 
{
  "error": "IllegalArgumentException",
+
    "error": "IllegalArgumentException",
  "errorMessage": "Invalid timestamp."
+
    "errorMessage": "Invalid timestamp."
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>
  
== UUID -> Name history ==
+
== Usernames to UUIDs ==
 
+
POST <nowiki>https://api.mojang.com/profiles/minecraft</nowiki>
  <nowiki>GET 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.
 
 
 
=== Response ===
 
 
 
<syntaxhighlight lang="javascript" style="overflow-x: scroll">
 
[
 
  {
 
    "name": "Gold"
 
  },
 
  {
 
    "name": "Diamond",
 
    "changedToAt": 1414059749000
 
  }
 
]
 
</syntaxhighlight>
 
 
 
The <code>changedToAt</code> field is a Java timestamp in milliseconds.
 
 
 
== Playernames -> UUIDs ==
 
 
 
  POST <nowiki>https://api.mojang.com/profiles/minecraft</nowiki>
 
  
 
This will return player UUIDs and some extras.
 
This will return player UUIDs and some extras.
  
 
=== Payload ===
 
=== Payload ===
 
+
<syntaxhighlight lang="json">
<syntaxhighlight lang="javascript" style="overflow-x: scroll">
 
 
[
 
[
     "maksimkurb",
+
     "foo",
     "nonExistingPlayer" //Test for non-existing player
+
    "bar",
 +
     "nonExistingPlayer"
 
]
 
]
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 +
=== Headers ===
 +
Content-Type: application/json
  
 
=== Response ===
 
=== Response ===
 
+
<syntaxhighlight lang="json">
<syntaxhighlight lang="javascript" style="overflow-x: scroll">
 
 
[
 
[
 
     {
 
     {
         "id": "0d252b7218b648bfb86c2ae476954d32",
+
         "id": "14f19f5050cb44cd9f0bbe906ad59753",
         "name": "maksimkurb",
+
         "name": "Bar"
         "legacy": true,
+
    },
         "demo": true
+
    {
 +
         "id": "9b15dea6606e47a4a241420251703c59",
 +
         "name": "Foo"
 
     }
 
     }
 
]
 
]
Line 139: Line 106:
 
* 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
* The <code>Content-Type</code> HTTP header must be <code>application/json</code>
 
 
* You cannot request more than 10 names per request
 
* You cannot request more than 10 names per request
  
== UUID -> Profile + Skin/Cape ==
+
== UUID to Name History ==
 +
GET <nowiki>https://api.mojang.com/user/profiles/<uuid>/names</nowiki>
  
  <nowiki>GET https://sessionserver.mojang.com/session/minecraft/profile/<uuid></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.
 +
 
 +
=== Response ===
 +
<syntaxhighlight lang="json">
 +
[
 +
    {
 +
        "name": "Gold"
 +
    },
 +
    {
 +
        "name": "Diamond",
 +
        "changedToAt": 1414059749000
 +
    }
 +
]
 +
</syntaxhighlight>
 +
 
 +
The <code>changedToAt</code> field is a Java timestamp in milliseconds.
 +
 
 +
== UUID to Profile and Skin/Cape ==
 +
GET <nowiki>https://sessionserver.mojang.com/session/minecraft/profile/<uuid></nowiki>
  
 
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
Line 154: Line 139:
  
 
=== Response ===
 
=== Response ===
<syntaxhighlight lang="javascript" style="overflow-x: scroll">
+
<syntaxhighlight lang="json">
 
{
 
{
 
     "id": "<profile identifier>",
 
     "id": "<profile identifier>",
Line 167: Line 152:
 
}
 
}
 
</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="javascript" style="overflow-x: scroll">
+
<syntaxhighlight lang="json">
 
{
 
{
 
     "timestamp": <java time in ms>,
 
     "timestamp": <java time in ms>,
Line 196: Line 180:
 
** [https://web.archive.org/web/20151022205119/https://gist.github.com/jomo/9968b8d572c38e1b1f4c Java] (includes sample UUIDs)
 
** [https://web.archive.org/web/20151022205119/https://gist.github.com/jomo/9968b8d572c38e1b1f4c Java] (includes sample UUIDs)
 
* 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.
 +
 +
== 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>*.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
 +
</pre>
 +
|}
 +
 +
== Statistics ==
 +
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 ==
 +
GET <nowiki>https://api.minecraftservices.com/minecraft/profile</nowiki>
 +
 +
This API endpoint fetches information about the current account including UUID, username, skins, and capes.
 +
 +
=== Headers ===
 +
Authorization: Bearer '''<access token>'''
 +
 +
=== 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": []
 +
}
 +
</syntaxhighlight>
 +
 +
== Profile Name Change Information ==
 +
GET <nowiki>https://api.minecraftservices.com/minecraft/profile/namechange</nowiki>
 +
 +
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 ===
 +
<syntaxhighlight lang="json">
 +
{
 +
    "changedAt": "2019-12-17T03:19:31Z",
 +
    "createdAt": "2015-11-13T01:59:46Z",
 +
    "nameChangeAllowed": true
 +
}
 +
</syntaxhighlight>
 +
 +
== Name Availability ==
 +
GET <nowiki>https://api.minecraftservices.com/minecraft/profile/name/</nowiki>'''<name>'''/available
 +
 +
This API endpoints check if the given name is available.
 +
 +
=== Headers ===
 +
Authorization: Bearer '''<access token>'''
 +
 +
=== Response ===
 +
<syntaxhighlight lang="json">
 +
{
 +
    "status": "DUPLICATE" // Either DUPLICATE or AVAILABLE
 +
}
 +
</syntaxhighlight>
  
 
== Change Name ==
 
== Change Name ==
Line 202: Line 347:
 
This will set the name for the account that the access token in the Authorization header belongs to.
 
This will set the name for the account that the access token in the Authorization header belongs to.
  
=== Response ===
+
=== Payload ===
Upon error the server will send back a JSON with the error.
+
No payload needed.
 +
 
 +
=== Headers ===
 +
Authorization: Bearer '''<access token>'''
 +
 
 +
=== Success Response ===
 +
<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>
 +
 
 +
=== Error Response ===
 +
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 216: Line 398:
 
|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 224: Line 409:
 
|}
 
|}
  
=== Headers ===
+
== Change Skin ==
  Authorization: Bearer '''<access token>'''
+
  POST <nowiki>https://api.minecraftservices.com/minecraft/profile/skins</nowiki>
 +
 
 +
This will set the skin for the selected profile, but Mojang's servers will fetch the skin from a URL.
  
 
=== Payload ===
 
=== Payload ===
No payload needed.
+
The payload for this API consists of a JSON object containing the URL and variant
  
=== Success Response ===
+
<syntaxhighlight lang="json">
<syntaxhighlight lang="javascript" style="overflow-x: scroll">
 
 
{
 
{
  "id" : "31e0ccbef5fa4eb988592f30516f65fe",
+
     "variant": "classic",
  "name" : "newname34234", //newly acquired name
+
     "url": "http://assets.mojang.com/SkinTemplates/steve.png"
  "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>
  
 +
variant is either "classic" or "slim"
  
== Change Skin ==
 
POST <nowiki>https://api.minecraftservices.com/minecraft/profile/skins</nowiki>
 
 
This will set the skin for the selected profile, but Mojang's servers will fetch the skin from a URL.
 
 
=== Response ===
 
Upon error the server will send back a JSON with the error. (Success is a blank payload)
 
 
=== Headers ===
 
=== Headers ===
 
  Authorization: Bearer '''<access token>'''
 
  Authorization: Bearer '''<access token>'''
  Content-Type: application/json; charset=utf-8
+
  Content-Type: application/json
 
 
=== 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"
 
  
 +
=== Response ===
 +
Upon error, the server will send back a JSON with the error. (Success is a blank payload)
  
 
=== Example ===
 
=== Example ===
Line 274: Line 439:
 
  POST <nowiki>https://api.minecraftservices.com/minecraft/profile/skins</nowiki>
 
  POST <nowiki>https://api.minecraftservices.com/minecraft/profile/skins</nowiki>
  
This uploads a skin to Mojang's servers. It also sets the users skin. This works on legacy counts as well.
+
This uploads a skin to Mojang's servers. It also sets the user's skin. This works on legacy accounts as well.
 
 
=== Response ===
 
No response unless error
 
=== Headers ===
 
Authorization: Bearer '''<access token>'''
 
  
 
=== Payload ===
 
=== Payload ===
Line 285: Line 445:
 
{| class="wikitable"
 
{| class="wikitable"
 
|'''variant'''
 
|'''variant'''
|either "classic" for normal model or "slim" for slim model.
+
|Either "classic" for normal models or "slim" for slim models.
 
|-
 
|-
 
|'''file'''
 
|'''file'''
 
|Raw image file data
 
|Raw image file data
 
|}
 
|}
 +
 +
=== Headers ===
 +
Authorization: Bearer '''<access token>'''
 +
 +
=== Response ===
 +
No response unless an error occurred.
 +
 
=== Example ===
 
=== Example ===
 
  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>
  
PUT /minecraft/profile/skins HTTP/1.1
+
<syntaxhighlight lang="http">
Host: api.minecraftservices.com
+
PUT /minecraft/profile/skins HTTP/1.1
User-Agent: curl/7.49.0
+
Host: api.minecraftservices.com
Accept: */*
+
User-Agent: curl/7.49.0
Authorization: Bearer '''<access token>'''
+
Accept: */*
Content-Length: '''<length>'''
+
Authorization: Bearer '''<access token>'''
Content-Type: multipart/form-data; boundary='''<boundary>'''
+
Content-Length: '''<length>'''
+
Content-Type: multipart/form-data; boundary='''<boundary>'''
--'''<boundary>'''
+
 
Content-Disposition: form-data; name="variant"
+
--'''<boundary>'''
+
Content-Disposition: form-data; name="variant"
classic
+
 
--'''<boundary>'''
+
classic
Content-Disposition: form-data; name="file"; filename="alex.png"
+
--'''<boundary>'''
Content-Type: image/png
+
Content-Disposition: form-data; name="file"; filename="alex.png"
+
Content-Type: image/png
'''<image data>'''
+
 
--'''<boundary>'''--
+
'''<image data>'''
 +
--'''<boundary>'''--
 +
</syntaxhighlight>
  
 
== Reset Skin ==
 
== Reset Skin ==
Line 316: Line 485:
  
 
Resets the user's skin to the default one.
 
Resets the user's skin to the default one.
 
=== Response ===
 
No response unless error
 
  
 
=== Headers ===
 
=== Headers ===
 
  Authorization: Bearer '''<access token>'''
 
  Authorization: Bearer '''<access token>'''
 +
 +
=== Response ===
 +
No response unless an error occurred.
  
 
=== Example ===
 
=== Example ===
 
  curl -X DELETE -H "Authorization: Bearer '''<access token>'''" <nowiki>https://api.mojang.com/user/profile/</nowiki>'''<uuid>'''/skin
 
  curl -X DELETE -H "Authorization: Bearer '''<access token>'''" <nowiki>https://api.mojang.com/user/profile/</nowiki>'''<uuid>'''/skin
  
DELETE /user/profile/'''<uuid>'''/skin HTTP/1.1
+
<syntaxhighlight lang="http">
Host: api.mojang.com
+
DELETE /user/profile/'''<uuid>'''/skin HTTP/1.1
User-Agent: curl/7.46.0
+
Host: api.mojang.com
Accept: */*
+
User-Agent: curl/7.46.0
Authorization: Bearer '''<access token>'''
+
Accept: */*
 +
Authorization: Bearer '''<access token>'''
 +
</syntaxhighlight>
  
== Security question-answer flow ==  
+
== Verify Security Location ==
 +
GET <nowiki>https://api.mojang.com/user/security/location</nowiki>
  
This is required to get the skin change endpoint to work in case the services do not trust your IP yet.
+
Verify's that the current IP is trusted by the server for the account and the token can be used.
  
=== Check if security questions are needed ===
+
=== Headers ===
 
 
GET https://api.mojang.com/user/security/location
 
 
  Authorization: Bearer '''<access token>'''
 
  Authorization: Bearer '''<access token>'''
  
Good answer:
+
=== Success Response ===
 
  204 NO CONTENT
 
  204 NO CONTENT
  
Bad answer:
+
=== Error Response ===
<syntaxhighlight lang="javascript" style="overflow-x: scroll">
+
<syntaxhighlight lang="json">
 
{
 
{
 
     "error": "ForbiddenOperationException",
 
     "error": "ForbiddenOperationException",
Line 352: Line 522:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
=== Get list of questions ===
+
== Get Security Questions ==
  GET https://api.mojang.com/user/security/challenges
+
  GET <nowiki>https://api.mojang.com/user/security/challenges</nowiki>
 +
 
 +
=== Headers ===
 
  Authorization: Bearer '''<access token>'''
 
  Authorization: Bearer '''<access token>'''
  
Answer:
+
=== Response ===
<syntaxhighlight lang="javascript" style="overflow-x: scroll">
+
<syntaxhighlight lang="json">
 
[
 
[
 
     {
 
     {
Line 389: Line 561:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
The possible IDs are these:
+
{| 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 431: Line 606:
 
39 What is your lucky number?
 
39 What is your lucky number?
 
</pre>
 
</pre>
 +
|}
  
=== Send back the answers ===
+
== Send Security Answers ==
  POST https://api.mojang.com/user/security/location
+
  POST <nowiki>https://api.mojang.com/user/security/location</nowiki>
Authorization: Bearer '''<access token>'''
 
  
<syntaxhighlight lang="javascript" style="overflow-x: scroll">
+
=== Payload ===
 +
<syntaxhighlight lang="json">
 
[
 
[
 
     {
 
     {
Line 453: Line 629:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 +
=== 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:
 
On failure, you will get some sort of error. Unless it's a syntax or json structure error, it will be this:
  
<syntaxhighlight lang="javascript" style="overflow-x: scroll">
+
<syntaxhighlight lang="json">
 
{
 
{
 
   "error": "ForbiddenOperationException",
 
   "error": "ForbiddenOperationException",
 
   "errorMessage": "At least one answer was incorrect"
 
   "errorMessage": "At least one answer was incorrect"
}
 
</syntaxhighlight>
 
 
On success:
 
204 NO CONTENT
 
 
== 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 <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>*.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.
 
<pre>
 
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
 
</pre>
 
 
== Statistics ==
 
  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="javascript" style="overflow-x: scroll">
 
{
 
    "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
 
 
=== Response ===
 
A json object is returned with the total amount of copies sold, the amount of copies sold in the last 24h and how many sales there are per second.
 
<syntaxhighlight lang="javascript" style="overflow-x: scroll">
 
{
 
    "total": integer total amount sold,
 
    "last24h": integer total sold in last 24 hours,
 
    "saleVelocityPerSeconds": decimal average sales per second
 
 
}
 
}
 
</syntaxhighlight>
 
</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/Lukaesebrot/mojango Go] - Full API wrapper
[https://github.com/CmlLib/MojangAPI C#] | full API wrapper with Mojang/Microsoft Authentication
+
* [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/Lukaesebrot/mojango Go] | full API wrapper
+
* [https://github.com/SynchronousX/mojang-api Python] - Full API wrapper
 
+
* [https://github.com/techkid6/AccountsClientPython Python] - UUIDs or names to profiles
[https://github.com/PhilipBorgesen/minecraft/tree/master/profile Go] | UUIDs or names to profiles with skins, capes and name histories
+
* [https://gist.github.com/jomo/74944770e7647855ac9d Python] - Names file to uuids+names file
 
+
* [https://github.com/elyby/mojang-api PHP] - Complete Mojang's API wrapper
[https://github.com/summer/mojang Python] | Full API Wrapper. Also supports authentication & parts of the Minecraft website
+
* [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://github.com/SynchronousX/mojang-api Python] | full API wrapper
+
* [https://github.com/ozzyfant/AccountsClientPHP PHP] - UUIDs to names, names to uuids
 
+
* [https://github.com/SparklingComet/java-mojang-api Java] - Almost full API Wrapper
[https://github.com/techkid6/AccountsClientPython Python] | UUIDs or names to profiles
+
* [https://github.com/dpkgsoft/mojang Java] - Almost full API Wrapper with auth
 
+
* [https://github.com/thechunknetwork/mojang-api JavaScript] - UUIDs or names to profiles with skins, capes and name histories
[https://gist.github.com/jomo/74944770e7647855ac9d Python] | names file to uuids+names file
 
 
 
[https://github.com/elyby/mojang-api PHP] | Complete Mojang's API wrapper
 
 
 
[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://github.com/ozzyfant/AccountsClientPHP PHP] | UUIDs to names, names to uuids
 
 
 
[https://github.com/SparklingComet/java-mojang-api Java] | Almost full API Wrapper
 
 
 
[https://github.com/thechunknetwork/mojang-api JavaScript] | UUIDs or names to profiles with skins, capes and name histories
 
  
 
[[Category:Protocol Details]]
 
[[Category:Protocol Details]]
 
[[Category:Minecraft Modern]]
 
[[Category:Minecraft Modern]]

Latest revision as of 05:08, 6 May 2021

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 authentication API, see Authentication.

API Status

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

Warning.png Since November 2020, Mojang stopped supporting the timestamp parameter. If a timestamp is provided, it is silently ignored and the current uuid is returned. Please remind them to fix this here: WEB-3367

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 uuid
  • name 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 204 (No Content) is sent without any HTTP body.
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

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

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 without hyphens.

Response

[
    {
        "name": "Gold"
    },
    {
        "name": "Diamond",
        "changedToAt": 1414059749000
    }
]

The changedToAt field is a Java 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 has no ratelimit.

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
        }
    ]
}
  • "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>"
        },
        "CAPE": {
            "url": "<player cape URL>"
        }
    }
}
  • The timestamp is sometimes in the past (probably due to cached results?)
  • The "SKIN" object will have "metadata": {"model": "slim"} if the player model has slim arms (“Alex?” style). For square arms (“Steve?” style), "metadata" will be missing.
  • If no custom skin has been set, "SKIN" will be missing.
    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:
  • Likewise "CAPE" will be missing if the account has no cape.

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, *.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

Statistics

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>",
            "variant": "CLASSIC" // Either SLIM or CLASSIC
        }
    ],
    "capes": []
}

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
}

Name Availability

GET https://api.minecraftservices.com/minecraft/profile/name/<name>/available

This API endpoints check if the given name is available.

Headers

Authorization: Bearer <access token>

Response

{
    "status": "DUPLICATE" // Either DUPLICATE or AVAILABLE
}

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

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.mojang.com/user/profile/<uuid>/skin

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.mojang.com/user/profile/<uuid>/skin
DELETE /user/profile/'''<uuid>'''/skin HTTP/1.1
Host: api.mojang.com
User-Agent: curl/7.46.0
Accept: */*
Authorization: Bearer '''<access token>'''

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"
}

Examples

  • C# - Full API wrapper
  • C# - Full API wrapper with Mojang/Microsoft 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 - Full API wrapper
  • Python - UUIDs or names to profiles
  • Python - Names file to uuids+names file
  • PHP - Complete Mojang's API wrapper
  • 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
  • JavaScript - UUIDs or names to profiles with skins, capes and name histories