Skip to content

Instantly share code, notes, and snippets.

@Woozl
Last active June 22, 2022 20:47
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Woozl/fff1065677ec8c7c5c8da3556ee9a439 to your computer and use it in GitHub Desktop.
Save Woozl/fff1065677ec8c7c5c8da3556ee9a439 to your computer and use it in GitHub Desktop.
Downloads a Minecraft skin using Mojang's player API
// https://davidglymph.com/blog/https-api-fetch-with-promises/
// To run script, make sure you have ts-node installed "npm i -g ts-node",
// replace {USERNAME} with a valid Minecraft account
//
// ts-node download-minecraft-skin.ts {USERNAME}
import https from 'https';
import http from 'http';
import fs from 'fs';
getUuid(process.argv[2])
.then(getProfile)
.then(saveSkin)
.then(console.log)
.catch(console.log);
function getUuid(profileName: string) {
const getUuidUrl = (profileName: string) => `https://api.mojang.com/users/profiles/minecraft/${profileName}`;
return new Promise<string>((resolve, reject) => {
if(profileName === undefined) reject(`Invalid or missing command argument`);
https.get(getUuidUrl(profileName), response => {
if(response.statusCode === 200) {
let chunk = '';
response.on('data', data => chunk += data);
response.on('end', () => resolve(JSON.parse(chunk).id));
}
else {
reject(`UUID fetch was invalid with status code ${response.statusCode}`);
}
}).on('error', reject);
});
}
function getProfile(uuid: string) {
const getProfileUrl = (uuid: string) => `https://sessionserver.mojang.com/session/minecraft/profile/${uuid}`;
return new Promise((resolve, reject) => {
https.get(getProfileUrl(uuid), response => {
if(response.statusCode === 200) {
let chunk = '';
response.on('data', data => chunk += data);
response.on('end', () => resolve(JSON.parse(chunk)));
}
else {
reject(`Profile fetch was invalid with status code ${response.statusCode}`);
}
}).on('error', reject);
});
}
function saveSkin(profile: any) {
const textureObjectBuffer = Buffer.from(profile.properties[0].value, 'base64url');
const textureObject = JSON.parse(textureObjectBuffer.toString('ascii'));
const profileName = textureObject.profileName;
const skinUrl = textureObject.textures.SKIN.url;
return downloadImageFromUrl(skinUrl, `./${profileName}.png`);
}
function downloadImageFromUrl(url: string, filepath: string) {
return new Promise((resolve, reject) => {
http.get(url, response => {
if(response.statusCode === 200)
response.pipe(fs.createWriteStream(filepath))
.on('error', reject)
.on('close', () => resolve(`File saved to ${filepath}`));
else
response.resume()
.on('end', () => reject(`Downloading image failed with status code ${response.statusCode}`));
}).on('error', reject);
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment