Folder structure
Skin packs use their own root folder rather than sitting inside a resource or behavior pack. At minimum, the root directory must contain a manifest.json file, a skins.json configuration file, the PNG texture files for each skin, and a texts folder containing localization files.
When you are ready to distribute or test the pack on a device outside of your development folder, zip the contents of the root directory (not the folder itself) and rename the file extension from .zip to .mcpack. Double-clicking this archive imports it directly into the game.
The skin pack manifest
Every skin pack requires a manifest.json at its root to identify the pack to Minecraft. The format is identical to resource and behavior pack manifests, except the module type must be set to skin_pack. You must generate two unique version 4 UUIDs: one for the header and one for the module.
Unlike resource packs, skin pack manifests do not look up their display name from the manifest header in the UI. Instead, the game relies entirely on the localization files to display both the pack title and individual skin names. The name and description fields in the manifest header are primarily for internal organization.
{
"format_version": 1,
"header": {
"name": "pack.name",
"version": [1, 0, 0],
"uuid": "a1b2c3d4-e5f6-4a5b-8c9d-0e1f2a3b4c5d"
},
"modules": [
{
"version": [1, 0, 0],
"type": "skin_pack",
"uuid": "f6e5d4c3-b2a1-4f5e-8d9c-0b1a2f3e4d5c"
}
]
}Defining skins in skins.json
The skins.json file sits beside the manifest and registers every skin texture in your pack. It binds each PNG file to a base player model and a localization key, and tells the game how to group the skins in the dressing room.
The serialize_name and localization_name at the bottom of the file should be set to the same unique identifier string. This string is used as part of the translation key in your language files to name the pack and its contents.
| Field | What it does | Notes |
|---|---|---|
| localization_name (root) | Sets the base translation key for the entire pack. | Must match the serialize_name for translations to resolve properly. |
| serialize_name | Internal identifier for the skin pack. | Use lowercase letters and underscores only. |
| localization_name (skin) | Identifier for the individual skin. | Combined with the root localization_name in the .lang file. |
| geometry | Selects the arm width model for the skin. | Use geometry.humanoid.custom for 4-pixel arms or geometry.humanoid.customSlim for 3-pixel arms. |
| texture | Relative path to the skin PNG file. | Usually placed in the root folder alongside skins.json. |
| type | Defines the unlock status of the skin. | Always set to free for community and third-party packs; paid requires Marketplace encryption. |
{
"skins": [
{
"localization_name": "knight_classic",
"geometry": "geometry.humanoid.custom",
"texture": "knight.png",
"type": "free"
},
{
"localization_name": "rogue_slim",
"geometry": "geometry.humanoid.customSlim",
"texture": "rogue.png",
"type": "free"
}
],
"serialize_name": "medieval_heroes",
"localization_name": "medieval_heroes"
}Texture and geometry rules
Skin textures must be standard 64x64 or 128x128 pixel PNG files mapped to the default Bedrock humanoid UV layout. If your texture has transparency in the base layer (such as a missing head or invisible limbs), the game will fill those transparent pixels with solid black or reject the texture to prevent competitive advantages in multiplayer.
Standard community skin packs are restricted to the two built-in humanoid geometries: geometry.humanoid.custom (the classic 4-pixel wide arm model) and geometry.humanoid.customSlim (the 3-pixel slim arm model). While older versions of Bedrock allowed arbitrary geometry.json files inside skin packs to create custom 3D hats, wings, or non-humanoid shapes, modern versions restrict custom skin geometry to partner packs signed by the Marketplace.
Localizing skin names
Without a language file, your skin pack and its skins will display raw translation keys in the dressing room. Create a texts folder in the root of your skin pack, and inside it, create an en_US.lang file and a languages.json file that lists "en_US" inside a JSON array.
Skin pack translation keys follow a strict naming pattern based on the values in skins.json. The pack title uses skinpack.<localization_name>, and each individual skin uses skin.<pack_localization_name>.<skin_localization_name>. Make sure there are no spaces around the equals sign.
skinpack.medieval_heroes=Medieval Heroes Skin Pack
skin.medieval_heroes.knight_classic=Armored Knight
skin.medieval_heroes.rogue_slim=Shadow RogueWhich versions this applies to
Applies to all modern Bedrock versions (1.12.0 and later). No experimental toggles exist for skin packs since they are loaded globally outside of worlds. Format version 1 is the standard for skin pack manifests.
When it does not work
| What you see | Why | The fix |
|---|---|---|
| The pack title shows up as 'skinpack.medieval_heroes' in the dressing room. | The game cannot find your localization keys, either because texts/en_US.lang is missing, or because serialize_name and localization_name in skins.json do not match each other. | Ensure serialize_name and localization_name in skins.json are identical, verify that texts/languages.json includes "en_US", and check that your .lang file keys match those exact strings. |
| Import fails with 'Duplicate pack detected' when testing an updated .mcpack. | Minecraft caches skin packs in the skin_packs directory using the header UUID, and will not overwrite an existing pack if the version number is the same. | Delete the old pack folder from your com.mojang/skin_packs directory before re-importing, or increment the version array in manifest.json. |
| The skin imports, but the character's arms have vertical black stripes or missing pixels on the back. | A slim-arm texture (3-pixel UV layout) was paired with geometry.humanoid.custom, or a classic 4-pixel texture was paired with geometry.humanoid.customSlim. | Change the geometry field for that entry in skins.json to match the arm width the texture was painted for. |
| The pack imports with no errors, but the skins appear completely invisible or fail to equip in multiplayer. | You included a custom geometry.json file or used a texture with too many transparent pixels on the base body layer. | Remove custom geometry files and stick to the two built-in humanoid identifiers, and ensure the base skin layer is 100% opaque. |
Reference, straight from the game files
Read out of the game itself, so the ids match the version you are building for.
