Mojang API
Contents
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
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": "yellow"
},
{
"session.minecraft.net": "green"
},
{
"account.mojang.com": "green"
},
{
"auth.mojang.com": "green"
},
{
"skins.minecraft.net": "green"
},
{
"authserver.mojang.com": "green"
},
{
"sessionserver.mojang.com": "yellow"
},
{
"api.mojang.com": "green"
},
{
"textures.minecraft.net": "red"
}
]
Username -> UUID at time
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
{
"id": "7125ba8b1c864508b92bb5c042ccfe2b",
"name": "KrisJelbring"
}
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."
}
UUID -> Name history
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.
Playernames -> UUIDs
POST https://api.mojang.com/profiles/minecraft
Where 'minecraft' - agent name
This will return player UUIDS and some extras.
Payload
[
"maksimkurb",
"nonExistingPlayer" //Test for non-existing player
]
Response
[
{
"id": "0d252b7218b648bfb86c2ae476954d32",
"name": "maksimkurb",
"legacy": true,
"demo": true
}
]
- name is case-corrected
- legacy only appears when true (profile not migrated to mojang.com)
- demo only appears when true (account unpaid)
- IllegalArgumentException is returned when any of the usernames is null or ""
- The
Content-Type
HTTP header must beapplication/json
- You cannot request more than 100 names per request
UUID -> Profile + Skin/Cape
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 a much stricter rate limit: You can request the same profile once per minute, however you can send as many unique requests as you like.
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
}
]
}
The "value" base64 string for the "textures" object decoded:
{
"timestamp": "<java time in ms>",
"profileId": "<profile uuid>",
"profileName": "<player name>",
"isPublic": "<true or false>",
"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.
Change Skin
POST https://api.mojang.com/user/profile/<uuid>/skin
This will set the skin for the selected profile, but Mojang's servers will fetch the skin from a URL. This will also work for legacy accounts.
Response
Upon error the server will send back a JSON with the error. (Success is a blank payload)
Headers
Authorization: Bearer <access token>
Payload
The payload for this API consists of two url-encoded form fields (conjoined by '&').
model=<alex/steve>&url=<skin url>
Example
curl -H "Authorization: Bearer <access token>" --data-urlencode "model=steve" --data-urlencode "url=http://assets.mojang.com/SkinTemplates/steve.png" https://api.mojang.com/user/profile/<uuid>/skin
POST /user/profile/<uuid>/skin HTTP/1.1 Host: api.mojang.com User-Agent: curl/7.49.0 Accept: */* Authorization: Bearer <access token> Content-Length: <74> Content-Type: application/x-www-form-urlencoded model=steve&url=http%3A%2F%2Fassets.mojang.com%2FSkinTemplate%2Fsteve.png
Upload Skin
PUT https://api.mojang.com/user/profile/<uuid>/skin
This uploads a skin to Mojang's servers. It also sets the users skin. This works on legacy counts as well.
Response
No response unless error
Headers
Authorization: Bearer <access token>
Payload
The payload for this API consists of multipart form data. There are two parts (order does not matter b/c of boundary):
model=<steve/alex> file=<raw file>
Example
curl -X PUT -H "Authorization: Bearer <access token>" -F model=steve -F file=@steve.png https://api.mojang.com/user/profile/<uuid>/skin PUT /user/profile/<uuid>/skin HTTP/1.1 Host: api.mojang.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="model" steve <boundary> Content-Disposition: form-data; name="file"; filename="steve.png" Content-Type=application/octet-stream <image data> <boundary>
User Info
GET https://api.mojang.com/user
Returns information on the logged in Mojang account.
Response
{
"id": "<Account Identifier?>",
"email": "<Email attached to account>",
"username": "<Username of account, with migrated accounts this is the same as email>",
"registerIp": "<IP used to register account>",
"registeredAt": <Epoch timestamp in ms of date the Mojang account was registered>,
"passwordChangedAt": <Epoch timestamp of time password was last changed>,
"dateOfBirth": <Epoch timestamp of date of birth for this Mojang Account>,
"deleted": <Unknown, probably whether account has been deleted or not>,
"blocked": <Unknown, probably whether account has been blocked or not>,
"secured": <Whether security questions are enabled on this Mojang Account>,
"migrated": <Whether the account has been migrated, if the account was made after Mojang Accounts were mandatory for new accounts this is set to false>,
"emailVerified": <Whether the email attached to the account is verified>,
"legacyUser": <Whether the account is a legacy user?>,
"verifiedByParent": <Whether the account has been verified by parent, is set to false if no parent verification was needed>,
"fullName": "<Full name attached to Mojang account, can be an empty string>",
"fromMigratedUser": <Not sure, probably related to migrated?>,
"hashed": <Unsure, seems to be set to false?>
}
Headers
Authorization: Bearer <access token>
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
a26f64ba73e751fec1e3c57e04ca184b32f575de e5477a2abfba7383cee228af82ad0c2ded388823 7769862d9ededd5d68dbb3fa0e36eabea693737a c78045f5aef524a3f899041269fa9daa3639c8bf 447985e7ef8477134681d8589961480b171f73dc c798f76e83ac9513a16574cb7b52c5cf76ad1bdd 206cf1a19de370289447c931ab53e1f8e9eaded4 879f1dea801746b51a2a908b04f7fe6fff5f7a47 7429bf7ad3c1f20d5443b2159f8c420556a5de6d cf883cb0b153f8777fc46bb9f40cd08446043165 5f2eceb54f642fb5f58abca0b52f7f0349f06cef ad9ad38574b4966fa537dd64e82807a185b7185a 5ff97c1058f402ef8f5bcd310f610bad8ad34460 a2e2be30dc9be014f171c8a3bbe955e55fd66d87 5c0394de667213e400dd21ffe4370b05566da22a ec43b2d08469e46f465a9acccc78690a316d5ef3 699994152eacdc9279944c3f1fe0ee7645b605e7 da9225e1f2baab028e37a1f34441bf18ce01298e 6d22ec6bc474410014a96712077dd1d4ba42d8d8 f71d2762d4267cd0b3cefd502e6d6f016625a4b1 8d278c5485692602e0cc0838373003512f1a7a11 ff232cafc67eb1a23594a2898fc627c2b1020064 954aeb4ee90feb42f30de0ec1a0e8685660a7336 18a825afbbe872f6138d07f16840c312ff971baa 980343d3239d599ab44f82a5a56b1cfc5d4623d4 7f97b2029f696caf320acb36ca56546c6860bdd0 e749acc18647b42cda870d87cb8c47f5b8df8a3c b1540c3a84161a990e3347821859da577272479c 9d1cebe7c9b20bccaee420d31336cb589692aded c40f20149f3d694ef47c152f7bc21b1e16ff702d 8c86c0e833d42efa4a38fad7e5267eb24bc120ed
All of the current hashes have been cracked. They are as follows:
a26f64ba73e751fec1e3c57e04ca184b32f575de : timelesspvp.net e5477a2abfba7383cee228af82ad0c2ded388823 : play.gotpvp.com 7769862d9ededd5d68dbb3fa0e36eabea693737a : play.endercraft.com c78045f5aef524a3f899041269fa9daa3639c8bf : hub.endercraft.com 447985e7ef8477134681d8589961480b171f73dc : ps.endercraft.com c798f76e83ac9513a16574cb7b52c5cf76ad1bdd : brawl.com 206cf1a19de370289447c931ab53e1f8e9eaded4 : mc.minevast.com 879f1dea801746b51a2a908b04f7fe6fff5f7a47 : play.insanenetwork.org 7429bf7ad3c1f20d5443b2159f8c420556a5de6d : play.insanefactions.org cf883cb0b153f8777fc46bb9f40cd08446043165 : insanefactions.org 5f2eceb54f642fb5f58abca0b52f7f0349f06cef : skygod.us ad9ad38574b4966fa537dd64e82807a185b7185a : phoenixnexus.net 5ff97c1058f402ef8f5bcd310f610bad8ad34460 : play.paradise-mc.net a2e2be30dc9be014f171c8a3bbe955e55fd66d87 : play.mineaqua.net 5c0394de667213e400dd21ffe4370b05566da22a : mc.eldercraft.de ec43b2d08469e46f465a9acccc78690a316d5ef3 : play.phanaticmc.com 699994152eacdc9279944c3f1fe0ee7645b605e7 : ftb.phanaticmc.com da9225e1f2baab028e37a1f34441bf18ce01298e : play.guildcraft.org 6d22ec6bc474410014a96712077dd1d4ba42d8d8 : join.block-city.de f71d2762d4267cd0b3cefd502e6d6f016625a4b1 : play.primemc.org 8d278c5485692602e0cc0838373003512f1a7a11 : play.ih-mc.com ff232cafc67eb1a23594a2898fc627c2b1020064 : pvp.thearchon.net 954aeb4ee90feb42f30de0ec1a0e8685660a7336 : epicpvp.eu 18a825afbbe872f6138d07f16840c312ff971baa : pvp.muxcraft.eu 980343d3239d599ab44f82a5a56b1cfc5d4623d4 : minetime.com 7f97b2029f696caf320acb36ca56546c6860bdd0 : play.datpixel.net e749acc18647b42cda870d87cb8c47f5b8df8a3c : mc.desiredcraft.net b1540c3a84161a990e3347821859da577272479c : powercraft.me 9d1cebe7c9b20bccaee420d31336cb589692aded : fadecloud.com c40f20149f3d694ef47c152f7bc21b1e16ff702d : mc.diacraft.org 8c86c0e833d42efa4a38fad7e5267eb24bc120ed : play.menoxia.com
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. Below is the default list used by https://minecraft.net/en/stats/
{
"metricKeys": [
"item_sold_minecraft",
"prepaid_card_redeemed_minecraft"
]
}
Valid options (Sales > 0) are:
item_sold_minecraft prepaid_card_redeemed_minecraft item_sold_cobalt item_sold_scrolls
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.
{
"total": integer total amount sold,
"last24h": integer total sold in last 24 hours,
"saleVelocityPerSeconds": integer average sales per second
}
Examples
Go | uuids or names to profiles with skins, capes and name histories
Python | uuids or names to profiles
Python | names file to uuids+names file
PHP | uuids or names to profiles with skins, heads and name histories
PHP | uuids to names
PHP | uuids to names, names to uuids
JavaScript | uuids or names to profiles with skins, capes and name histories