EML Lib v2.3.0: Skin management
EML Lib v2.3.0 is now available on npm. The headline feature of this release is the new Skin class, which brings full skin and cape management support to the library — across all three authentication backends.
The Skin class
Skin management has been a recurring request, and it is now covered out of the box. The Skin class supports Microsoft (MSA), Yggdrasil (e.g. Drasl) and Azuriom accounts. It exposes a consistent interface regardless of the underlying backend, abstracting away the differences between each provider’s API.
Instantiation is straightforward — you pass in the authenticated account object returned by any of EML Lib’s authentication classes:
import { Skin } from 'eml-lib'
const skin = new Skin(account) Data is lazy-loaded and cached: the first call to getSkin(), getCape() or getAvatar() will trigger a fetch if the cache is empty. Call reload() at any time to invalidate the cache and get the latest data from the server.
Fetching skin data
// All skins on the account
const skins = await skin.getSkin()
// Active skin only
const [activeSkin] = await skin.getSkin(true)
// All capes, active cape only
const capes = await skin.getCape()
const [activeCape] = await skin.getCape(true)
// Avatar (face crop — null in Node.js main process)
const avatar = await skin.getAvatar() The avatar URL is computed from the skin texture using the Canvas API when available — it returns null in the Electron main process, where the DOM is not accessible.
Updating skins
Skins can be uploaded either from a URL or from a File/Blob object:
// By URL (MSA and Azuriom only — Yggdrasil servers such as Drasl do not support URL-based uploads)
await skin.updateSkin('https://example.com/my-skin.png', 'slim')
// By Blob — works for all backends
const blob = new Blob([await fs.readFile('/path/to/skin.png')], { type: 'image/png' })
await skin.updateSkin(blob, 'classic') The second argument controls the skin variant (classic or slim). For Azuriom accounts, it is ignored as that backend does not expose a variant concept.
Managing capes
Cape support varies significantly between backends, reflecting their underlying API differences.
Microsoft accounts ship with a fixed set of capes tied to the user’s purchases and entitlements. The library exposes two operations:
// Switch to a specific cape (use getCape() to list available cape IDs)
await skin.switchCape(capeId)
// Remove the active cape from display (does not delete it)
await skin.hideCape() Azuriom accounts support uploading a custom cape image:
const capeBlob = new Blob([await fs.readFile('/path/to/cape.png')], { type: 'image/png' })
await skin.updateCape(capeBlob)
// Delete the active cape entirely
await skin.deleteCape() Note that Yggdrasil does not expose a standard endpoint for cape uploads. The updateCape() method is therefore not supported for Yggdrasil accounts and will throw an EMLLibError. Cape deletion, however, works as expected via DELETE /minecraft/profile/capes/active.
Other changes
- The
Bootstrapsclass has been renamed toBootstrap. The old name is deprecated and will be removed in a future release. AzAuth-authenticated accounts now include ameta.urlproperty exposing the Azuriom instance URL, making it available downstream for skin API calls and other requests.MicrosoftAuthnow exposes alogout()method for consistency withYggdrasilAuthandAzAuth.- Various JSDoc improvements across the codebase.
Full release notes are available on GitHub. To update:
npm install eml-lib@latest